Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
/* GStreamer
* Copyright ( C ) 1999 Erik Walthinsen < omega @ cse . ogi . edu >
* Copyright ( C ) 2005 Tim - Philipp Müller < tim centricular net >
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*/
/* TODO:
*
* - in : : start ( ) , we want to post a tags message with an array or a list
* of tagslists of all tracks , so that applications know at least the
* number of tracks and all track durations immediately without having
* to do any querying . We have to decide what type and name to use for
* this array of track taglists .
*
* - FIX cddb discid calculation algorithm for mixed mode CDs - do we use
* offsets and duration of ALL tracks ( data + audio ) for the CDDB ID
* calculation , or only audio tracks ?
*
* - Do we really need properties for the TOC bias / offset stuff ? Wouldn ' t
* environment variables make much more sense ? Do we need this at all
* ( does it only affect ancient hardware ? )
*/
/**
* SECTION : gstcddabasesrc
* @ short_description : Base class for CD digital audio ( CDDA ) sources
*
* < refsect2 >
* < para >
* Provides a base class for CDDA sources , which handles things like seeking ,
* querying , discid calculation , tags , and buffer timestamping .
* < / para >
2006-03-12 14:56:31 +00:00
* < title > Using GstCddaBaseSrc - based elements in applications < / title >
* < para >
* GstCddaBaseSrc registers two # GstFormat < ! - - - - > s of its own , namely
* the " track " format and the " sector " format . Applications will usually
* only find the " track " format interesting . You can retrieve that # GstFormat
* for use in seek events or queries with gst_format_get_by_nick ( " track " ) .
* < / para >
* < para >
* In order to query the number of tracks , for example , an application would
* set the CDDA source element to READY or PAUSED state and then query the
* the number of tracks via gst_element_query_duration ( ) using the track
* format acquired above . Applications can query the currently playing track
* in the same way .
* < / para >
* < para >
* Alternatively , applications may retrieve the currently playing track and
* the total number of tracks from the taglist that will posted on the bus
* whenever the CD is opened or the currently playing track changes . The
* taglist will contain GST_TAG_TRACK_NUMBER and GST_TAG_TRACK_COUNT tags .
* < / para >
* < para >
* Applications playing back CD audio using playbin and cdda : //n URIs should
* issue a seek command in track format to change between tracks , rather than
* setting a new cdda : //n+1 URI on playbin (as setting a new URI on playbin
* involves closing and re - opening the CD device , which is much much slower ) .
* < / para >
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
* < / refsect2 >
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <string.h>
# include "gstcddabasesrc.h"
# include "gst/gst-i18n-plugin.h"
GST_DEBUG_CATEGORY_STATIC ( gst_cdda_base_src_debug ) ;
# define GST_CAT_DEFAULT gst_cdda_base_src_debug
# define DEFAULT_DEVICE " / dev / cdrom"
# define CD_FRAMESIZE_RAW (2352)
# define SECTORS_PER_SECOND (75)
# define SECTORS_PER_MINUTE (75*60)
# define SAMPLES_PER_SECTOR (CD_FRAMESIZE_RAW >> 2)
# define TIME_INTERVAL_FROM_SECTORS(sectors) ((SAMPLES_PER_SECTOR * sectors * GST_SECOND) / 44100)
# define SECTORS_FROM_TIME_INTERVAL(dtime) (dtime * 44100 / (SAMPLES_PER_SECTOR * GST_SECOND))
# define GST_TYPE_CDDA_BASE_SRC_MODE (gst_cdda_base_src_mode_get_type ())
enum
{
ARG_0 ,
ARG_MODE ,
ARG_DEVICE ,
ARG_TRACK ,
ARG_TOC_OFFSET ,
ARG_TOC_BIAS
} ;
static void gst_cdda_base_src_get_property ( GObject * object , guint prop_id ,
GValue * value , GParamSpec * pspec ) ;
static void gst_cdda_base_src_set_property ( GObject * object , guint prop_id ,
const GValue * value , GParamSpec * pspec ) ;
static void gst_cdda_base_src_finalize ( GObject * obj ) ;
static const GstQueryType * gst_cdda_base_src_get_query_types ( GstPad * pad ) ;
static gboolean gst_cdda_base_src_query ( GstBaseSrc * src , GstQuery * query ) ;
static gboolean gst_cdda_base_src_handle_event ( GstBaseSrc * basesrc ,
GstEvent * event ) ;
static gboolean gst_cdda_base_src_do_seek ( GstBaseSrc * basesrc ,
GstSegment * segment ) ;
static void gst_cdda_base_src_setup_interfaces ( GType type ) ;
static gboolean gst_cdda_base_src_start ( GstBaseSrc * basesrc ) ;
static gboolean gst_cdda_base_src_stop ( GstBaseSrc * basesrc ) ;
static GstFlowReturn gst_cdda_base_src_create ( GstPushSrc * pushsrc ,
GstBuffer * * buf ) ;
static gboolean gst_cdda_base_src_is_seekable ( GstBaseSrc * basesrc ) ;
static void gst_cdda_base_src_update_duration ( GstCddaBaseSrc * src ) ;
static void gst_cdda_base_src_set_index ( GstElement * src , GstIndex * index ) ;
static GstIndex * gst_cdda_base_src_get_index ( GstElement * src ) ;
GST_BOILERPLATE_FULL ( GstCddaBaseSrc , gst_cdda_base_src , GstPushSrc ,
GST_TYPE_PUSH_SRC , gst_cdda_base_src_setup_interfaces ) ;
# define SRC_CAPS \
" audio/x-raw-int, " \
" endianness = (int) BYTE_ORDER, " \
" signed = (boolean) true, " \
" width = (int) 16, " \
" depth = (int) 16, " \
" rate = (int) 44100, " \
" channels = (int) 2 " \
static GstStaticPadTemplate gst_cdda_base_src_src_template =
GST_STATIC_PAD_TEMPLATE ( " src " ,
GST_PAD_SRC ,
GST_PAD_ALWAYS ,
GST_STATIC_CAPS ( SRC_CAPS )
) ;
/* our two formats */
static GstFormat track_format ;
static GstFormat sector_format ;
static GType
gst_cdda_base_src_mode_get_type ( void )
{
static GType mode_type ; /* 0 */
static GEnumValue modes [ ] = {
{ GST_CDDA_BASE_SRC_MODE_NORMAL , " Stream consists of a single track " ,
" normal " } ,
{ GST_CDDA_BASE_SRC_MODE_CONTINUOUS , " Stream consists of the whole disc " ,
" continuous " } ,
{ 0 , NULL , NULL }
} ;
if ( mode_type = = 0 )
mode_type = g_enum_register_static ( " GstCddaBaseSrcMode " , modes ) ;
return mode_type ;
}
static void
gst_cdda_base_src_base_init ( gpointer g_class )
{
GstElementClass * element_class = GST_ELEMENT_CLASS ( g_class ) ;
gst_element_class_add_pad_template ( element_class ,
gst_static_pad_template_get ( & gst_cdda_base_src_src_template ) ) ;
/* our very own formats */
track_format = gst_format_register ( " track " , " CD track " ) ;
sector_format = gst_format_register ( " sector " , " CD sector " ) ;
/* tags */
gst_tag_register ( GST_TAG_CDDA_CDDB_DISCID , GST_TAG_FLAG_META ,
G_TYPE_STRING , " discid " , " CDDB discid for metadata retrieval " ,
gst_tag_merge_use_first ) ;
gst_tag_register ( GST_TAG_CDDA_CDDB_DISCID_FULL , GST_TAG_FLAG_META ,
G_TYPE_STRING , " discid full " ,
" CDDB discid for metadata retrieval (full) " , gst_tag_merge_use_first ) ;
gst_tag_register ( GST_TAG_CDDA_MUSICBRAINZ_DISCID , GST_TAG_FLAG_META ,
G_TYPE_STRING , " musicbrainz-discid " ,
" Musicbrainz discid for metadata retrieval " , gst_tag_merge_use_first ) ;
gst_tag_register ( GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL , GST_TAG_FLAG_META ,
G_TYPE_STRING , " musicbrainz-discid-full " ,
" Musicbrainz discid for metadata retrieval (full) " ,
gst_tag_merge_use_first ) ;
#if 0
///// FIXME: what type to use here? ///////
gst_tag_register ( GST_TAG_CDDA_TRACK_TAGS , GST_TAG_FLAG_META , GST_TYPE_TAG_LIST , " track-tags " , " CDDA taglist for one track " , gst_tag_merge_use_first ) ; ///////////// FIXME: right function??? ///////
# endif
GST_DEBUG_CATEGORY_INIT ( gst_cdda_base_src_debug , " cddabasesrc " , 0 ,
" CDDA Base Source " ) ;
}
static void
gst_cdda_base_src_class_init ( GstCddaBaseSrcClass * klass )
{
GstElementClass * element_class ;
GstPushSrcClass * pushsrc_class ;
GstBaseSrcClass * basesrc_class ;
GObjectClass * gobject_class ;
gobject_class = ( GObjectClass * ) klass ;
element_class = ( GstElementClass * ) klass ;
basesrc_class = ( GstBaseSrcClass * ) klass ;
pushsrc_class = ( GstPushSrcClass * ) klass ;
gobject_class - > set_property = gst_cdda_base_src_set_property ;
gobject_class - > get_property = gst_cdda_base_src_get_property ;
gobject_class - > finalize = gst_cdda_base_src_finalize ;
g_object_class_install_property ( G_OBJECT_CLASS ( klass ) , ARG_DEVICE ,
g_param_spec_string ( " device " , " Device " , " CD device location " ,
NULL , G_PARAM_READWRITE ) ) ;
g_object_class_install_property ( G_OBJECT_CLASS ( klass ) , ARG_MODE ,
g_param_spec_enum ( " mode " , " Mode " , " Mode " , GST_TYPE_CDDA_BASE_SRC_MODE ,
GST_CDDA_BASE_SRC_MODE_NORMAL , G_PARAM_READWRITE ) ) ;
g_object_class_install_property ( G_OBJECT_CLASS ( klass ) , ARG_TRACK ,
g_param_spec_uint ( " track " , " Track " , " Track " , 1 , 99 , 1 ,
G_PARAM_READWRITE ) ) ;
#if 0
/* Do we really need this toc adjustment stuff as properties? does the user
* have a chance to set it in practice , e . g . when using sound - juicer , rb ,
* totem , whatever ? Shouldn ' t we rather use environment variables
* for this ? ( tpm ) */
g_object_class_install_property ( G_OBJECT_CLASS ( klass ) , ARG_TOC_OFFSET ,
g_param_spec_int ( " toc-offset " , " Table of contents offset " ,
" Add <n> sectors to the values reported " , G_MININT , G_MAXINT , 0 ,
G_PARAM_READWRITE ) ) ;
g_object_class_install_property ( G_OBJECT_CLASS ( klass ) , ARG_TOC_BIAS ,
g_param_spec_boolean ( " toc-bias " , " Table of contents bias " ,
" Assume that the beginning offset of track 1 as reported in the TOC "
" will be addressed as LBA 0. Necessary for some Toshiba drives to "
" get track boundaries " , FALSE , G_PARAM_READWRITE ) ) ;
# endif
element_class - > set_index = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_set_index ) ;
element_class - > get_index = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_get_index ) ;
basesrc_class - > start = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_start ) ;
basesrc_class - > stop = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_stop ) ;
basesrc_class - > query = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_query ) ;
basesrc_class - > event = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_handle_event ) ;
basesrc_class - > do_seek = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_do_seek ) ;
basesrc_class - > is_seekable =
GST_DEBUG_FUNCPTR ( gst_cdda_base_src_is_seekable ) ;
pushsrc_class - > create = GST_DEBUG_FUNCPTR ( gst_cdda_base_src_create ) ;
}
static void
gst_cdda_base_src_init ( GstCddaBaseSrc * src , GstCddaBaseSrcClass * klass )
{
gst_pad_set_query_type_function ( GST_BASE_SRC_PAD ( src ) ,
GST_DEBUG_FUNCPTR ( gst_cdda_base_src_get_query_types ) ) ;
/* we're not live and we operate in time */
gst_base_src_set_format ( GST_BASE_SRC ( src ) , GST_FORMAT_TIME ) ;
gst_base_src_set_live ( GST_BASE_SRC ( src ) , FALSE ) ;
src - > device = NULL ;
src - > mode = GST_CDDA_BASE_SRC_MODE_NORMAL ;
src - > uri_track = - 1 ;
}
static void
gst_cdda_base_src_finalize ( GObject * obj )
{
GstCddaBaseSrc * cddasrc = GST_CDDA_BASE_SRC ( obj ) ;
g_free ( cddasrc - > uri ) ;
g_free ( cddasrc - > device ) ;
G_OBJECT_CLASS ( parent_class ) - > finalize ( obj ) ;
}
static void
gst_cdda_base_src_set_property ( GObject * object , guint prop_id ,
const GValue * value , GParamSpec * pspec )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( object ) ;
GST_OBJECT_LOCK ( src ) ;
switch ( prop_id ) {
case ARG_MODE : {
src - > mode = g_value_get_enum ( value ) ;
break ;
}
case ARG_DEVICE : {
const gchar * dev = g_value_get_string ( value ) ;
g_free ( src - > device ) ;
if ( dev & & * dev ) {
src - > device = g_strdup ( dev ) ;
} else {
src - > device = NULL ;
}
break ;
}
case ARG_TRACK : {
guint track = g_value_get_uint ( value ) ;
if ( src - > num_tracks > 0 & & track > src - > num_tracks ) {
g_warning ( " Invalid track %u " , track ) ;
} else if ( track > 0 & & src - > tracks ! = NULL ) {
src - > cur_sector = src - > tracks [ track - 1 ] . start ;
src - > uri_track = track ;
} else {
src - > uri_track = track ; /* seek will be done in start() */
}
break ;
}
case ARG_TOC_OFFSET : {
src - > toc_offset = g_value_get_int ( value ) ;
break ;
}
case ARG_TOC_BIAS : {
src - > toc_bias = g_value_get_boolean ( value ) ;
break ;
}
default : {
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , prop_id , pspec ) ;
break ;
}
}
GST_OBJECT_UNLOCK ( src ) ;
}
static void
gst_cdda_base_src_get_property ( GObject * object , guint prop_id ,
GValue * value , GParamSpec * pspec )
{
GstCddaBaseSrcClass * klass = GST_CDDA_BASE_SRC_GET_CLASS ( object ) ;
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( object ) ;
GST_OBJECT_LOCK ( src ) ;
switch ( prop_id ) {
case ARG_MODE :
g_value_set_enum ( value , src - > mode ) ;
break ;
case ARG_DEVICE : {
if ( src - > device = = NULL & & klass - > get_default_device ! = NULL ) {
gchar * d = klass - > get_default_device ( src ) ;
if ( d ! = NULL ) {
g_value_set_string ( value , DEFAULT_DEVICE ) ;
g_free ( d ) ;
break ;
}
}
if ( src - > device = = NULL )
g_value_set_string ( value , DEFAULT_DEVICE ) ;
else
g_value_set_string ( value , src - > device ) ;
break ;
}
case ARG_TRACK : {
if ( src - > num_tracks < = 0 & & src - > uri_track > 0 ) {
g_value_set_uint ( value , src - > uri_track ) ;
} else {
g_value_set_uint ( value , src - > cur_track + 1 ) ;
}
break ;
}
case ARG_TOC_OFFSET :
g_value_set_int ( value , src - > toc_offset ) ;
break ;
case ARG_TOC_BIAS :
g_value_set_boolean ( value , src - > toc_bias ) ;
break ;
default : {
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , prop_id , pspec ) ;
break ;
}
}
GST_OBJECT_UNLOCK ( src ) ;
}
static gint
gst_cdda_base_src_get_track_from_sector ( GstCddaBaseSrc * src , gint sector )
{
gint i ;
for ( i = 0 ; i < src - > num_tracks ; + + i ) {
if ( sector > = src - > tracks [ i ] . start & & sector < = src - > tracks [ i ] . end )
return i ;
}
return - 1 ;
}
static const GstQueryType *
gst_cdda_base_src_get_query_types ( GstPad * pad )
{
static const GstQueryType src_query_types [ ] = {
GST_QUERY_DURATION ,
GST_QUERY_POSITION ,
GST_QUERY_CONVERT ,
0
} ;
return src_query_types ;
}
static gboolean
gst_cdda_base_src_convert ( GstCddaBaseSrc * src , GstFormat src_format ,
gint64 src_val , GstFormat dest_format , gint64 * dest_val )
{
gboolean started ;
GST_LOG_OBJECT ( src , " converting value % " G_GINT64_FORMAT " from %s into %s " ,
src_val , gst_format_get_name ( src_format ) ,
gst_format_get_name ( dest_format ) ) ;
if ( src_format = = dest_format ) {
* dest_val = src_val ;
return TRUE ;
}
started = GST_OBJECT_FLAG_IS_SET ( GST_BASE_SRC ( src ) , GST_BASE_SRC_STARTED ) ;
if ( src_format = = track_format ) {
if ( ! started )
goto not_started ;
if ( src_val < 0 | | src_val > = src - > num_tracks ) {
GST_DEBUG_OBJECT ( src , " track number %d out of bounds " , ( gint ) src_val ) ;
goto wrong_value ;
}
src_format = GST_FORMAT_DEFAULT ;
src_val = src - > tracks [ src_val ] . start * SAMPLES_PER_SECTOR ;
} else if ( src_format = = sector_format ) {
src_format = GST_FORMAT_DEFAULT ;
src_val = src_val * SAMPLES_PER_SECTOR ;
}
if ( src_format = = dest_format ) {
* dest_val = src_val ;
goto done ;
}
switch ( src_format ) {
case GST_FORMAT_BYTES :
/* convert to samples (4 bytes per sample) */
src_val = src_val > > 2 ;
/* fallthrough */
case GST_FORMAT_DEFAULT : {
switch ( dest_format ) {
case GST_FORMAT_BYTES : {
if ( src_val < 0 ) {
GST_DEBUG_OBJECT ( src , " sample source value negative " ) ;
goto wrong_value ;
}
* dest_val = src_val < < 2 ; /* 4 bytes per sample */
break ;
}
case GST_FORMAT_TIME : {
* dest_val = gst_util_uint64_scale_int ( src_val , GST_SECOND , 44100 ) ;
break ;
}
default : {
gint64 sector = src_val / SAMPLES_PER_SECTOR ;
if ( dest_format = = sector_format ) {
* dest_val = sector ;
} else if ( dest_format = = track_format ) {
if ( ! started )
goto not_started ;
* dest_val = gst_cdda_base_src_get_track_from_sector ( src , sector ) ;
} else {
goto unknown_format ;
}
break ;
}
}
break ;
}
case GST_FORMAT_TIME : {
gint64 sample_offset ;
if ( src_val = = GST_CLOCK_TIME_NONE ) {
GST_DEBUG_OBJECT ( src , " source time value invalid " ) ;
goto wrong_value ;
}
sample_offset = gst_util_uint64_scale_int ( src_val , 44100 , GST_SECOND ) ;
switch ( dest_format ) {
case GST_FORMAT_BYTES : {
* dest_val = sample_offset < < 2 ; /* 4 bytes per sample */
break ;
}
case GST_FORMAT_DEFAULT : {
* dest_val = sample_offset ;
break ;
}
default : {
gint64 sector = sample_offset / SAMPLES_PER_SECTOR ;
if ( dest_format = = sector_format ) {
* dest_val = sector ;
} else if ( dest_format = = track_format ) {
if ( ! started )
goto not_started ;
* dest_val = gst_cdda_base_src_get_track_from_sector ( src , sector ) ;
} else {
goto unknown_format ;
}
break ;
}
}
break ;
}
default : {
goto unknown_format ;
}
}
done :
{
GST_LOG_OBJECT ( src , " returning % " G_GINT64_FORMAT , * dest_val ) ;
return TRUE ;
}
unknown_format :
{
GST_DEBUG_OBJECT ( src , " conversion failed: %s " , " unsupported format " ) ;
return FALSE ;
}
wrong_value :
{
GST_DEBUG_OBJECT ( src , " conversion failed: %s " ,
" source value not within allowed range " ) ;
return FALSE ;
}
not_started :
{
GST_DEBUG_OBJECT ( src , " conversion failed: %s " ,
" cannot do this conversion, device not open " ) ;
return FALSE ;
}
}
static gboolean
gst_cdda_base_src_query ( GstBaseSrc * basesrc , GstQuery * query )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( basesrc ) ;
gboolean started ;
started = GST_OBJECT_FLAG_IS_SET ( basesrc , GST_BASE_SRC_STARTED ) ;
GST_LOG_OBJECT ( src , " handling %s query " ,
gst_query_type_get_name ( GST_QUERY_TYPE ( query ) ) ) ;
switch ( GST_QUERY_TYPE ( query ) ) {
case GST_QUERY_DURATION : {
GstFormat dest_format ;
gint64 dest_val ;
guint sectors ;
gst_query_parse_duration ( query , & dest_format , NULL ) ;
if ( ! started )
return FALSE ;
g_assert ( src - > tracks ! = NULL ) ;
if ( dest_format = = track_format ) {
GST_LOG_OBJECT ( src , " duration: %d tracks " , src - > num_tracks ) ;
gst_query_set_duration ( query , track_format , src - > num_tracks ) ;
return TRUE ;
}
if ( src - > cur_track < 0 | | src - > cur_track > = src - > num_tracks )
return FALSE ;
if ( src - > mode = = GST_CDDA_BASE_SRC_MODE_NORMAL ) {
sectors = src - > tracks [ src - > cur_track ] . end -
src - > tracks [ src - > cur_track ] . start + 1 ;
} else {
sectors = src - > tracks [ src - > num_tracks - 1 ] . end -
src - > tracks [ 0 ] . start + 1 ;
}
/* ... and convert into final format */
if ( ! gst_cdda_base_src_convert ( src , sector_format , sectors ,
dest_format , & dest_val ) ) {
return FALSE ;
}
gst_query_set_duration ( query , dest_format , dest_val ) ;
GST_LOG ( " duration: %u sectors, % " G_GINT64_FORMAT " in format %s " ,
sectors , dest_val , gst_format_get_name ( dest_format ) ) ;
break ;
}
case GST_QUERY_POSITION : {
GstFormat dest_format ;
gint64 pos_sector ;
gint64 dest_val ;
gst_query_parse_position ( query , & dest_format , NULL ) ;
if ( ! started )
return FALSE ;
g_assert ( src - > tracks ! = NULL ) ;
if ( dest_format = = track_format ) {
GST_LOG_OBJECT ( src , " position: track %d " , src - > cur_track ) ;
gst_query_set_position ( query , track_format , src - > cur_track ) ;
return TRUE ;
}
if ( src - > cur_track < 0 | | src - > cur_track > = src - > num_tracks )
return FALSE ;
if ( src - > mode = = GST_CDDA_BASE_SRC_MODE_NORMAL ) {
pos_sector = src - > cur_sector - src - > tracks [ src - > cur_track ] . start ;
} else {
pos_sector = src - > cur_sector - src - > tracks [ 0 ] . start ;
}
if ( ! gst_cdda_base_src_convert ( src , sector_format , pos_sector ,
dest_format , & dest_val ) ) {
return FALSE ;
}
gst_query_set_position ( query , dest_format , dest_val ) ;
GST_LOG ( " position: sector %u, % " G_GINT64_FORMAT " in format %s " ,
( guint ) pos_sector , dest_val , gst_format_get_name ( dest_format ) ) ;
break ;
}
case GST_QUERY_CONVERT : {
GstFormat src_format , dest_format ;
gint64 src_val , dest_val ;
gst_query_parse_convert ( query , & src_format , & src_val , & dest_format ,
NULL ) ;
if ( ! gst_cdda_base_src_convert ( src , src_format , src_val , dest_format ,
& dest_val ) ) {
return FALSE ;
}
gst_query_set_convert ( query , src_format , src_val , dest_format , dest_val ) ;
break ;
}
default : {
2006-02-01 11:59:47 +00:00
GST_DEBUG_OBJECT ( src , " unhandled query, chaining up to parent class " ) ;
return GST_BASE_SRC_CLASS ( parent_class ) - > query ( basesrc , query ) ;
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
}
}
return TRUE ;
}
static gboolean
gst_cdda_base_src_is_seekable ( GstBaseSrc * basesrc )
{
return TRUE ;
}
static gboolean
gst_cdda_base_src_do_seek ( GstBaseSrc * basesrc , GstSegment * segment )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( basesrc ) ;
gint64 seek_sector ;
GST_DEBUG_OBJECT ( src , " segment % " GST_TIME_FORMAT " -% " GST_TIME_FORMAT ,
GST_TIME_ARGS ( segment - > start ) , GST_TIME_ARGS ( segment - > stop ) ) ;
if ( ! gst_cdda_base_src_convert ( src , GST_FORMAT_TIME , segment - > start ,
sector_format , & seek_sector ) ) {
GST_WARNING_OBJECT ( src , " conversion failed " ) ;
return FALSE ;
}
/* we should only really be called when open */
g_assert ( src - > cur_track > = 0 & & src - > cur_track < src - > num_tracks ) ;
switch ( src - > mode ) {
case GST_CDDA_BASE_SRC_MODE_NORMAL :
seek_sector + = src - > tracks [ src - > cur_track ] . start ;
break ;
case GST_CDDA_BASE_SRC_MODE_CONTINUOUS :
seek_sector + = src - > tracks [ 0 ] . start ;
break ;
default :
g_assert_not_reached ( ) ;
}
src - > cur_sector = ( gint ) seek_sector ;
GST_DEBUG_OBJECT ( src , " seek'd to sector %d " , src - > cur_sector ) ;
return TRUE ;
}
static gboolean
gst_cdda_base_src_handle_track_seek ( GstCddaBaseSrc * src , gdouble rate ,
GstSeekFlags flags , GstSeekType start_type , gint64 start ,
GstSeekType stop_type , gint64 stop )
{
GstBaseSrc * basesrc = GST_BASE_SRC ( src ) ;
GstEvent * event ;
if ( ( flags & GST_SEEK_FLAG_SEGMENT ) = = GST_SEEK_FLAG_SEGMENT ) {
gint64 start_time = - 1 ;
gint64 stop_time = - 1 ;
if ( src - > mode ! = GST_CDDA_BASE_SRC_MODE_CONTINUOUS ) {
GST_DEBUG_OBJECT ( src , " segment seek in track format is only "
" supported in CONTINUOUS mode, not in mode %d " , src - > mode ) ;
return FALSE ;
}
switch ( start_type ) {
case GST_SEEK_TYPE_SET :
if ( ! gst_cdda_base_src_convert ( src , track_format , start ,
GST_FORMAT_TIME , & start_time ) ) {
GST_DEBUG_OBJECT ( src , " cannot convert track %d to time " ,
( gint ) start ) ;
return FALSE ;
}
break ;
case GST_SEEK_TYPE_END :
if ( ! gst_cdda_base_src_convert ( src , track_format ,
src - > num_tracks - start - 1 , GST_FORMAT_TIME , & start_time ) ) {
GST_DEBUG_OBJECT ( src , " cannot convert track %d to time " ,
( gint ) start ) ;
return FALSE ;
}
start_type = GST_SEEK_TYPE_SET ;
break ;
case GST_SEEK_TYPE_NONE :
start_time = - 1 ;
break ;
default :
g_assert_not_reached ( ) ;
}
switch ( stop_type ) {
case GST_SEEK_TYPE_SET :
if ( ! gst_cdda_base_src_convert ( src , track_format , stop ,
GST_FORMAT_TIME , & stop_time ) ) {
GST_DEBUG_OBJECT ( src , " cannot convert track %d to time " ,
( gint ) stop ) ;
return FALSE ;
}
break ;
case GST_SEEK_TYPE_END :
if ( ! gst_cdda_base_src_convert ( src , track_format ,
src - > num_tracks - stop - 1 , GST_FORMAT_TIME , & stop_time ) ) {
GST_DEBUG_OBJECT ( src , " cannot convert track %d to time " ,
( gint ) stop ) ;
return FALSE ;
}
stop_type = GST_SEEK_TYPE_SET ;
break ;
case GST_SEEK_TYPE_NONE :
stop_time = - 1 ;
break ;
default :
g_assert_not_reached ( ) ;
}
GST_LOG_OBJECT ( src , " seek segment % " GST_TIME_FORMAT " -% " GST_TIME_FORMAT ,
GST_TIME_ARGS ( start_time ) , GST_TIME_ARGS ( stop_time ) ) ;
/* send fake segment seek event in TIME format to
* base class , which will hopefully handle the rest */
event = gst_event_new_seek ( rate , GST_FORMAT_TIME , flags , start_type ,
start_time , stop_type , stop_time ) ;
return GST_BASE_SRC_CLASS ( parent_class ) - > event ( basesrc , event ) ;
}
/* not a segment seek */
if ( start_type = = GST_SEEK_TYPE_NONE ) {
GST_LOG_OBJECT ( src , " start seek type is NONE, nothing to do " ) ;
return TRUE ;
}
if ( stop_type ! = GST_SEEK_TYPE_NONE ) {
GST_WARNING_OBJECT ( src , " ignoring stop seek type (expected NONE) " ) ;
}
if ( start < 0 | | start > = src - > num_tracks ) {
GST_DEBUG_OBJECT ( src , " invalid track % " G_GINT64_FORMAT , start ) ;
return FALSE ;
}
2006-01-12 14:56:11 +00:00
GST_DEBUG_OBJECT ( src , " seeking to track %d " , start + 1 ) ;
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
2006-01-12 14:56:11 +00:00
src - > cur_sector = src - > tracks [ start ] . start ;
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
GST_DEBUG_OBJECT ( src , " starting at sector %d " , src - > cur_sector ) ;
2006-01-12 14:56:11 +00:00
if ( src - > cur_track ! = start ) {
src - > cur_track = ( gint ) start ;
src - > uri_track = - 1 ;
src - > prev_track = - 1 ;
gst_cdda_base_src_update_duration ( src ) ;
} else {
GST_DEBUG_OBJECT ( src , " is current track, just seeking back to start " ) ;
}
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
/* send fake segment seek event in TIME format to
* base class ( so we get a newsegment etc . ) */
event = gst_event_new_seek ( rate , GST_FORMAT_TIME , flags ,
GST_SEEK_TYPE_SET , 0 , GST_SEEK_TYPE_NONE , - 1 ) ;
return GST_BASE_SRC_CLASS ( parent_class ) - > event ( basesrc , event ) ;
}
static gboolean
gst_cdda_base_src_handle_event ( GstBaseSrc * basesrc , GstEvent * event )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( basesrc ) ;
gboolean ret = FALSE ;
GST_LOG_OBJECT ( src , " handling %s event " , GST_EVENT_TYPE_NAME ( event ) ) ;
switch ( GST_EVENT_TYPE ( event ) ) {
case GST_EVENT_SEEK : {
GstSeekType start_type , stop_type ;
GstSeekFlags flags ;
GstFormat format ;
gdouble rate ;
gint64 start , stop ;
if ( ! GST_OBJECT_FLAG_IS_SET ( basesrc , GST_BASE_SRC_STARTED ) ) {
GST_DEBUG_OBJECT ( src , " seek failed: device not open " ) ;
break ;
}
gst_event_parse_seek ( event , & rate , & format , & flags , & start_type , & start ,
& stop_type , & stop ) ;
if ( format = = sector_format ) {
GST_DEBUG_OBJECT ( src , " seek in sector format not supported " ) ;
break ;
}
if ( format = = track_format ) {
ret = gst_cdda_base_src_handle_track_seek ( src , rate , flags ,
start_type , start , stop_type , stop ) ;
} else {
GST_LOG_OBJECT ( src , " let base class handle seek in %s format " ,
gst_format_get_name ( format ) ) ;
2006-02-01 11:59:47 +00:00
event = gst_event_ref ( event ) ;
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
ret = GST_BASE_SRC_CLASS ( parent_class ) - > event ( basesrc , event ) ;
}
break ;
}
default : {
GST_LOG_OBJECT ( src , " let base class handle event " ) ;
2006-02-01 11:59:47 +00:00
event = gst_event_ref ( event ) ;
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
ret = GST_BASE_SRC_CLASS ( parent_class ) - > event ( basesrc , event ) ;
break ;
}
}
return ret ;
}
static guint
gst_cdda_base_src_uri_get_type ( void )
{
return GST_URI_SRC ;
}
static gchar * *
gst_cdda_base_src_uri_get_protocols ( void )
{
static gchar * protocols [ ] = { " cdda " , NULL } ;
return protocols ;
}
static const gchar *
gst_cdda_base_src_uri_get_uri ( GstURIHandler * handler )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( handler ) ;
GST_OBJECT_LOCK ( src ) ;
g_free ( src - > uri ) ;
if ( GST_OBJECT_FLAG_IS_SET ( GST_BASE_SRC ( src ) , GST_BASE_SRC_STARTED ) ) {
src - > uri = g_strdup_printf ( " cdda://%d " , src - > uri_track ) ;
} else {
src - > uri = g_strdup ( " cdda://1 " ) ;
}
GST_OBJECT_UNLOCK ( src ) ;
return src - > uri ;
}
/* Note: gst_element_make_from_uri() might call us with just 'cdda://' as
* URI and expects us to return TRUE then ( and this might be in any state ) */
static gboolean
gst_cdda_base_src_uri_set_uri ( GstURIHandler * handler , const gchar * uri )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( handler ) ;
gchar * protocol , * location ;
GST_OBJECT_LOCK ( src ) ;
protocol = gst_uri_get_protocol ( uri ) ;
if ( ! protocol | | strcmp ( protocol , " cdda " ) ! = 0 ) {
g_free ( protocol ) ;
goto failed ;
}
g_free ( protocol ) ;
location = gst_uri_get_location ( uri ) ;
if ( location = = NULL | | * location = = ' \0 ' ) {
g_free ( location ) ;
location = g_strdup ( " 1 " ) ;
}
src - > uri_track = strtol ( location , NULL , 10 ) ;
g_free ( location ) ;
if ( src - > uri_track = = 0 )
goto failed ;
if ( src - > num_tracks > 0
& & src - > tracks ! = NULL & & src - > uri_track > src - > num_tracks )
goto failed ;
if ( src - > uri_track > 0 & & src - > tracks ! = NULL ) {
GST_OBJECT_UNLOCK ( src ) ;
gst_pad_send_event ( GST_BASE_SRC_PAD ( src ) ,
gst_event_new_seek ( 1.0 , track_format , GST_SEEK_FLAG_FLUSH ,
GST_SEEK_TYPE_SET , src - > uri_track - 1 , GST_SEEK_TYPE_NONE , - 1 ) ) ;
} else {
/* seek will be done in start() */
GST_OBJECT_UNLOCK ( src ) ;
}
GST_LOG_OBJECT ( handler , " successfully handled uri '%s' " , uri ) ;
return TRUE ;
failed :
{
GST_OBJECT_UNLOCK ( src ) ;
GST_DEBUG_OBJECT ( src , " cannot handle URI '%s' " , uri ) ;
return FALSE ;
}
}
static void
gst_cdda_base_src_uri_handler_init ( gpointer g_iface , gpointer iface_data )
{
GstURIHandlerInterface * iface = ( GstURIHandlerInterface * ) g_iface ;
iface - > get_type = gst_cdda_base_src_uri_get_type ;
iface - > get_uri = gst_cdda_base_src_uri_get_uri ;
iface - > set_uri = gst_cdda_base_src_uri_set_uri ;
iface - > get_protocols = gst_cdda_base_src_uri_get_protocols ;
}
static void
gst_cdda_base_src_setup_interfaces ( GType type )
{
static const GInterfaceInfo urihandler_info = {
gst_cdda_base_src_uri_handler_init ,
NULL ,
NULL ,
} ;
g_type_add_interface_static ( type , GST_TYPE_URI_HANDLER , & urihandler_info ) ;
}
/**
* gst_cdda_base_src_add_track :
* @ src : a # GstCddaBaseSrc
* @ track : address of # GstCddaBaseSrcTrack to add
*
* CDDA sources use this function from their start vfunc to announce the
* available data and audio tracks to the base source class . The caller
* should allocate @ track on the stack , the base source will do a shallow
* copy of the structure ( and take ownership of the taglist if there is one ) .
*
* Returns : FALSE on error , otherwise TRUE .
*/
gboolean
gst_cdda_base_src_add_track ( GstCddaBaseSrc * src , GstCddaBaseSrcTrack * track )
{
g_return_val_if_fail ( GST_IS_CDDA_BASE_SRC ( src ) , FALSE ) ;
g_return_val_if_fail ( track ! = NULL , FALSE ) ;
g_return_val_if_fail ( track - > num > 0 , FALSE ) ;
GST_DEBUG_OBJECT ( src , " adding track %2u (%2u) [%6u-%6u] [%5s], tags: % "
GST_PTR_FORMAT , src - > num_tracks + 1 , track - > num , track - > start ,
track - > end , ( track - > is_audio ) ? " AUDIO " : " DATA " , track - > tags ) ;
if ( src - > num_tracks > 0 ) {
guint end_of_previous_track = src - > tracks [ src - > num_tracks - 1 ] . end ;
g_return_val_if_fail ( track - > start > = end_of_previous_track , FALSE ) ;
}
GST_OBJECT_LOCK ( src ) ;
+ + src - > num_tracks ;
src - > tracks = g_renew ( GstCddaBaseSrcTrack , src - > tracks , src - > num_tracks ) ;
src - > tracks [ src - > num_tracks - 1 ] = * track ;
GST_OBJECT_UNLOCK ( src ) ;
return TRUE ;
}
static void
gst_cdda_base_src_update_duration ( GstCddaBaseSrc * src )
{
GstBaseSrc * basesrc ;
GstFormat format ;
gint64 duration ;
basesrc = GST_BASE_SRC ( src ) ;
format = GST_FORMAT_TIME ;
if ( gst_pad_query_duration ( GST_BASE_SRC_PAD ( src ) , & format , & duration ) ) {
gst_segment_set_duration ( & basesrc - > segment , GST_FORMAT_TIME , duration ) ;
} else {
gst_segment_set_duration ( & basesrc - > segment , GST_FORMAT_TIME , - 1 ) ;
2005-12-29 11:49:11 +00:00
duration = GST_CLOCK_TIME_NONE ;
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
}
gst_element_post_message ( GST_ELEMENT ( src ) ,
gst_message_new_duration ( GST_OBJECT ( src ) , GST_FORMAT_TIME , - 1 ) ) ;
GST_LOG_OBJECT ( src , " duration updated to % " GST_TIME_FORMAT ,
GST_TIME_ARGS ( duration ) ) ;
}
# define CD_MSF_OFFSET 150
/* the cddb hash function */
static guint
cddb_sum ( gint n )
{
guint ret ;
ret = 0 ;
while ( n > 0 ) {
ret + = ( n % 10 ) ;
n / = 10 ;
}
return ret ;
}
# include "base64.h"
# include "sha1.h"
static void
gst_cddabasesrc_calculate_musicbrainz_discid ( GstCddaBaseSrc * src )
{
GString * s ;
SHA_INFO sha ;
guchar digest [ 20 ] , * ptr ;
gchar tmp [ 9 ] ;
gulong i ;
guint leadout_sector ;
s = g_string_new ( NULL ) ;
leadout_sector = src - > tracks [ src - > num_tracks - 1 ] . end + 1 + CD_MSF_OFFSET ;
/* generate SHA digest */
sha_init ( & sha ) ;
g_snprintf ( tmp , sizeof ( tmp ) , " %02X " , src - > tracks [ 0 ] . num ) ;
g_string_append_printf ( s , " %02X " , src - > tracks [ 0 ] . num ) ;
sha_update ( & sha , ( SHA_BYTE * ) tmp , 2 ) ;
g_snprintf ( tmp , sizeof ( tmp ) , " %02X " , src - > tracks [ src - > num_tracks - 1 ] . num ) ;
g_string_append_printf ( s , " %02X " , src - > tracks [ src - > num_tracks - 1 ] . num ) ;
sha_update ( & sha , ( SHA_BYTE * ) tmp , 2 ) ;
g_snprintf ( tmp , sizeof ( tmp ) , " %08X " , leadout_sector ) ;
g_string_append_printf ( s , " %08X " , leadout_sector ) ;
sha_update ( & sha , ( SHA_BYTE * ) tmp , 8 ) ;
for ( i = 0 ; i < 99 ; i + + ) {
if ( i < src - > num_tracks ) {
guint frame_offset = src - > tracks [ i ] . start + CD_MSF_OFFSET ;
g_snprintf ( tmp , sizeof ( tmp ) , " %08X " , frame_offset ) ;
g_string_append_printf ( s , " %08X " , frame_offset ) ;
sha_update ( & sha , ( SHA_BYTE * ) tmp , 8 ) ;
} else {
sha_update ( & sha , ( SHA_BYTE * ) " 00000000 " , 8 ) ;
}
}
sha_final ( digest , & sha ) ;
/* re-encode to base64 */
ptr = rfc822_binary ( digest , 20 , & i ) ;
g_assert ( i < sizeof ( src - > mb_discid ) + 1 ) ;
memcpy ( src - > mb_discid , ptr , i ) ;
src - > mb_discid [ i ] = ' \0 ' ;
free ( ptr ) ;
GST_DEBUG_OBJECT ( src , " musicbrainz-discid = %s " , src - > mb_discid ) ;
GST_DEBUG_OBJECT ( src , " musicbrainz-discid-full = %s " , s - > str ) ;
gst_tag_list_add ( src - > tags , GST_TAG_MERGE_REPLACE ,
GST_TAG_CDDA_MUSICBRAINZ_DISCID , src - > mb_discid ,
GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL , s - > str , NULL ) ;
g_string_free ( s , TRUE ) ;
}
static void
lba_to_msf ( guint sector , guint * p_m , guint * p_s , guint * p_f , guint * p_secs )
{
guint m , s , f ;
m = sector / SECTORS_PER_MINUTE ;
sector = sector % SECTORS_PER_MINUTE ;
s = sector / SECTORS_PER_SECOND ;
f = sector % SECTORS_PER_SECOND ;
if ( p_m )
* p_m = m ;
if ( p_s )
* p_s = s ;
if ( p_f )
* p_f = f ;
if ( p_secs )
* p_secs = s + ( m * 60 ) ;
}
static void
gst_cdda_base_src_calculate_cddb_id ( GstCddaBaseSrc * src )
{
GString * s ;
guint first_sector = 0 , last_sector = 0 ;
guint start_secs , end_secs , secs , len_secs ;
guint total_secs , num_audio_tracks ;
guint id , t , i ;
id = 0 ;
total_secs = 0 ;
num_audio_tracks = 0 ;
/* FIXME: do we use offsets and duration of ALL tracks (data + audio)
* for the CDDB ID calculation , or only audio tracks ? */
for ( i = 0 ; i < src - > num_tracks ; + + i ) {
if ( 1 ) { /* src->tracks[i].is_audio) { */
if ( num_audio_tracks = = 0 ) {
first_sector = src - > tracks [ i ] . start + CD_MSF_OFFSET ;
}
last_sector = src - > tracks [ i ] . end + CD_MSF_OFFSET + 1 ;
+ + num_audio_tracks ;
lba_to_msf ( src - > tracks [ i ] . start + CD_MSF_OFFSET , NULL , NULL , NULL ,
& secs ) ;
len_secs = ( src - > tracks [ i ] . end - src - > tracks [ i ] . start + 1 ) / 75 ;
GST_DEBUG_OBJECT ( src , " track %02u: lsn %6u (%02u:%02u), "
" length: %u seconds (%02u:%02u) " ,
num_audio_tracks , src - > tracks [ i ] . start + CD_MSF_OFFSET ,
secs / 60 , secs % 60 , len_secs , len_secs / 60 , len_secs % 60 ) ;
id + = cddb_sum ( secs ) ;
total_secs + = len_secs ;
}
}
/* first_sector = src->tracks[0].start + CD_MSF_OFFSET; */
lba_to_msf ( first_sector , NULL , NULL , NULL , & start_secs ) ;
/* last_sector = src->tracks[src->num_tracks-1].end + CD_MSF_OFFSET; */
lba_to_msf ( last_sector , NULL , NULL , NULL , & end_secs ) ;
GST_DEBUG_OBJECT ( src , " first_sector = %u = %u secs (%02u:%02u) " ,
first_sector , start_secs , start_secs / 60 , start_secs % 60 ) ;
GST_DEBUG_OBJECT ( src , " last_sector = %u = %u secs (%02u:%02u) " ,
last_sector , end_secs , end_secs / 60 , end_secs % 60 ) ;
t = end_secs - start_secs ;
GST_DEBUG_OBJECT ( src , " total length = %u secs (%02u:%02u), added title "
" lengths = %u seconds (%02u:%02u) " , t , t / 60 , t % 60 , total_secs ,
total_secs / 60 , total_secs % 60 ) ;
src - > discid = ( ( id % 0xff ) < < 24 | t < < 8 | num_audio_tracks ) ;
s = g_string_new ( NULL ) ;
g_string_append_printf ( s , " %08x " , src - > discid ) ;
gst_tag_list_add ( src - > tags , GST_TAG_MERGE_REPLACE ,
2005-12-29 11:49:11 +00:00
GST_TAG_CDDA_CDDB_DISCID , s - > str , NULL ) ;
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
g_string_append_printf ( s , " %u " , src - > num_tracks ) ;
for ( i = 0 ; i < src - > num_tracks ; + + i ) {
g_string_append_printf ( s , " %u " , src - > tracks [ i ] . start + CD_MSF_OFFSET ) ;
}
g_string_append_printf ( s , " %u " , t ) ;
gst_tag_list_add ( src - > tags , GST_TAG_MERGE_REPLACE ,
GST_TAG_CDDA_CDDB_DISCID_FULL , s - > str , NULL ) ;
GST_DEBUG_OBJECT ( src , " cddb discid = %s " , s - > str ) ;
g_string_free ( s , TRUE ) ;
}
static void
gst_cdda_base_src_add_tags ( GstCddaBaseSrc * src )
{
gint i ;
/* fill in details for each track */
for ( i = 0 ; i < src - > num_tracks ; + + i ) {
gint64 duration ;
guint num_sectors ;
if ( src - > tracks [ i ] . tags = = NULL )
src - > tracks [ i ] . tags = gst_tag_list_new ( ) ;
num_sectors = src - > tracks [ i ] . end - src - > tracks [ i ] . start + 1 ;
gst_cdda_base_src_convert ( src , sector_format , num_sectors ,
GST_FORMAT_TIME , & duration ) ;
gst_tag_list_add ( src - > tracks [ i ] . tags ,
GST_TAG_MERGE_REPLACE_ALL ,
GST_TAG_TRACK_NUMBER , i + 1 ,
GST_TAG_TRACK_COUNT , src - > num_tracks , GST_TAG_DURATION , duration , NULL ) ;
}
/* now fill in per-album tags and include each track's tags
* in the album tags , so that interested parties can retrieve
* the relevant details for each track in one go */
/* /////////////////////////////// FIXME should we rather insert num_tracks
* tags by the name of ' track - tags ' and have the caller use
* gst_tag_list_get_value_index ( ) rather than use tag names incl .
* the track number ? ? */ ///////////////////////////////////////
gst_tag_list_add ( src - > tags , GST_TAG_MERGE_REPLACE_ALL ,
GST_TAG_TRACK_COUNT , src - > num_tracks , NULL ) ;
#if 0
for ( i = 0 ; i < src - > num_tracks ; + + i ) {
gst_tag_list_add ( src - > tags , GST_TAG_MERGE_APPEND ,
GST_TAG_CDDA_TRACK_TAGS , src - > tracks [ i ] . tags , NULL ) ;
}
# endif
GST_DEBUG ( " src->tags = % " GST_PTR_FORMAT , src - > tags ) ;
}
static void
gst_cdda_base_src_add_index_associations ( GstCddaBaseSrc * src )
{
gint i ;
for ( i = 0 ; i < src - > num_tracks ; i + + ) {
gint64 sector ;
sector = src - > tracks [ i ] . start ;
gst_index_add_association ( src - > index , src - > index_id , GST_ASSOCIATION_FLAG_KEY_UNIT , track_format , i , /* here we count from 0 */
sector_format , sector ,
GST_FORMAT_TIME ,
( gint64 ) ( ( ( CD_FRAMESIZE_RAW > > 2 ) * sector * GST_SECOND ) / 44100 ) ,
GST_FORMAT_BYTES , ( gint64 ) ( sector < < 2 ) , GST_FORMAT_DEFAULT ,
( gint64 ) ( ( CD_FRAMESIZE_RAW > > 2 ) * sector ) , NULL ) ;
}
}
static void
gst_cdda_base_src_set_index ( GstElement * element , GstIndex * index )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( element ) ;
src - > index = index ;
gst_index_get_writer_id ( index , GST_OBJECT ( src ) , & src - > index_id ) ;
gst_index_add_format ( index , src - > index_id , track_format ) ;
gst_index_add_format ( index , src - > index_id , sector_format ) ;
}
static GstIndex *
gst_cdda_base_src_get_index ( GstElement * element )
{
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( element ) ;
return src - > index ;
}
static gint
gst_cdda_base_src_track_sort_func ( gconstpointer a , gconstpointer b ,
gpointer foo )
{
GstCddaBaseSrcTrack * track_a = ( ( GstCddaBaseSrcTrack * ) a ) ;
GstCddaBaseSrcTrack * track_b = ( ( GstCddaBaseSrcTrack * ) b ) ;
/* sort data tracks to the end, and audio tracks by track number */
if ( track_a - > is_audio = = track_b - > is_audio )
return ( gint ) track_a - > num - ( gint ) track_b - > num ;
if ( track_a - > is_audio ) {
return - 1 ;
} else {
return 1 ;
}
}
static gboolean
gst_cdda_base_src_start ( GstBaseSrc * basesrc )
{
GstCddaBaseSrcClass * klass = GST_CDDA_BASE_SRC_GET_CLASS ( basesrc ) ;
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( basesrc ) ;
gboolean ret ;
gchar * device = NULL ;
src - > discid = 0 ;
src - > mb_discid [ 0 ] = ' \0 ' ;
g_assert ( klass - > open ! = NULL ) ;
if ( src - > device ! = NULL ) {
device = g_strdup ( src - > device ) ;
} else if ( klass - > get_default_device ! = NULL ) {
device = klass - > get_default_device ( src ) ;
}
if ( device = = NULL )
device = g_strdup ( DEFAULT_DEVICE ) ;
GST_LOG_OBJECT ( basesrc , " opening device %s " , device ) ;
src - > tags = gst_tag_list_new ( ) ;
ret = klass - > open ( src , device ) ;
g_free ( device ) ;
device = NULL ;
if ( ! ret ) {
GST_DEBUG_OBJECT ( basesrc , " failed to open device " ) ;
/* subclass (should have) posted an error message with the details */
gst_cdda_base_src_stop ( basesrc ) ;
return FALSE ;
}
if ( src - > num_tracks = = 0 | | src - > tracks = = NULL ) {
GST_DEBUG_OBJECT ( src , " no tracks " ) ;
GST_ELEMENT_ERROR ( src , RESOURCE , OPEN_READ ,
( _ ( " This CD has no audio tracks " ) ) , ( NULL ) ) ;
gst_cdda_base_src_stop ( basesrc ) ;
return FALSE ;
}
/* need to calculate disc IDs before we ditch the data tracks */
gst_cdda_base_src_calculate_cddb_id ( src ) ;
gst_cddabasesrc_calculate_musicbrainz_discid ( src ) ;
#if 0
/* adjust sector offsets if necessary */
if ( src - > toc_bias ) {
src - > toc_offset - = src - > tracks [ 0 ] . start ;
}
for ( i = 0 ; i < src - > num_tracks ; + + i ) {
src - > tracks [ i ] . start + = src - > toc_offset ;
src - > tracks [ i ] . end + = src - > toc_offset ;
}
# endif
/* now that we calculated the various disc IDs,
* sort the data tracks to end and ignore them */
src - > num_all_tracks = src - > num_tracks ;
g_qsort_with_data ( src - > tracks , src - > num_tracks ,
sizeof ( GstCddaBaseSrcTrack ) , gst_cdda_base_src_track_sort_func , NULL ) ;
while ( src - > num_tracks > 0 & & ! src - > tracks [ src - > num_tracks - 1 ] . is_audio )
- - src - > num_tracks ;
if ( src - > num_tracks = = 0 ) {
GST_DEBUG_OBJECT ( src , " no audio tracks " ) ;
GST_ELEMENT_ERROR ( src , RESOURCE , OPEN_READ ,
( _ ( " This CD has no audio tracks " ) ) , ( NULL ) ) ;
gst_cdda_base_src_stop ( basesrc ) ;
return FALSE ;
}
gst_cdda_base_src_add_tags ( src ) ;
if ( src - > index & & GST_INDEX_IS_WRITABLE ( src - > index ) )
gst_cdda_base_src_add_index_associations ( src ) ;
src - > cur_track = 0 ;
src - > prev_track = - 1 ;
if ( src - > uri_track > 0 & & src - > uri_track < = src - > num_tracks ) {
GST_LOG_OBJECT ( src , " seek to track %d " , src - > uri_track ) ;
src - > cur_track = src - > uri_track - 1 ;
src - > uri_track = - 1 ;
src - > mode = GST_CDDA_BASE_SRC_MODE_NORMAL ;
}
src - > cur_sector = src - > tracks [ src - > cur_track ] . start ;
GST_LOG_OBJECT ( src , " starting at sector %d " , src - > cur_sector ) ;
gst_cdda_base_src_update_duration ( src ) ;
return TRUE ;
}
static void
gst_cdda_base_src_clear_tracks ( GstCddaBaseSrc * src )
{
if ( src - > tracks ! = NULL ) {
gint i ;
for ( i = 0 ; i < src - > num_all_tracks ; + + i ) {
if ( src - > tracks [ i ] . tags )
gst_tag_list_free ( src - > tracks [ i ] . tags ) ;
}
g_free ( src - > tracks ) ;
src - > tracks = NULL ;
}
src - > num_tracks = 0 ;
src - > num_all_tracks = 0 ;
}
static gboolean
gst_cdda_base_src_stop ( GstBaseSrc * basesrc )
{
GstCddaBaseSrcClass * klass = GST_CDDA_BASE_SRC_GET_CLASS ( basesrc ) ;
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( basesrc ) ;
g_assert ( klass - > close ! = NULL ) ;
klass - > close ( src ) ;
gst_cdda_base_src_clear_tracks ( src ) ;
if ( src - > tags ) {
gst_tag_list_free ( src - > tags ) ;
src - > tags = NULL ;
}
src - > prev_track = - 1 ;
src - > cur_track = - 1 ;
return TRUE ;
}
static GstFlowReturn
gst_cdda_base_src_create ( GstPushSrc * pushsrc , GstBuffer * * buffer )
{
GstCddaBaseSrcClass * klass = GST_CDDA_BASE_SRC_GET_CLASS ( pushsrc ) ;
GstCddaBaseSrc * src = GST_CDDA_BASE_SRC ( pushsrc ) ;
GstBuffer * buf ;
GstFormat format ;
gboolean eos ;
gint64 position ;
gint64 duration ;
g_assert ( klass - > read_sector ! = NULL ) ;
switch ( src - > mode ) {
case GST_CDDA_BASE_SRC_MODE_NORMAL :
eos = ( src - > cur_sector > = src - > tracks [ src - > cur_track ] . end ) ;
break ;
case GST_CDDA_BASE_SRC_MODE_CONTINUOUS :
eos = ( src - > cur_sector > = src - > tracks [ src - > num_tracks - 1 ] . end ) ;
src - > cur_track = gst_cdda_base_src_get_track_from_sector ( src ,
src - > cur_sector ) ;
break ;
default :
g_assert_not_reached ( ) ;
}
if ( eos ) {
src - > prev_track = - 1 ;
GST_DEBUG_OBJECT ( src , " EOS at sector %d, cur_track=%d, mode=%d " ,
src - > cur_sector , src - > cur_track , src - > mode ) ;
2006-02-13 15:17:34 +00:00
/* base class will send EOS for us */
Add new libgstcdda with GstCddaBaseSrc class.
Original commit message from CVS:
* configure.ac:
* gst-libs/gst/Makefile.am:
* gst-libs/gst/cdda/Makefile.am:
* gst-libs/gst/cdda/base64.c:
* gst-libs/gst/cdda/base64.h:
* gst-libs/gst/cdda/gstcddabasesrc.c:
(gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init),
(gst_cdda_base_src_class_init), (gst_cdda_base_src_init),
(gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property),
(gst_cdda_base_src_get_property),
(gst_cdda_base_src_get_track_from_sector),
(gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert),
(gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable),
(gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek),
(gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type),
(gst_cdda_base_src_uri_get_protocols),
(gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri),
(gst_cdda_base_src_uri_handler_init),
(gst_cdda_base_src_setup_interfaces),
(gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration),
(cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid),
(lba_to_msf), (gst_cdda_base_src_calculate_cddb_id),
(gst_cdda_base_src_add_tags),
(gst_cdda_base_src_add_index_associations),
(gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index),
(gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start),
(gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop),
(gst_cdda_base_src_create):
* gst-libs/gst/cdda/gstcddabasesrc.h:
* gst-libs/gst/cdda/sha1.c:
* gst-libs/gst/cdda/sha1.h:
Add new libgstcdda with GstCddaBaseSrc class.
2005-12-28 18:06:50 +00:00
return GST_FLOW_UNEXPECTED ;
}
if ( src - > prev_track ! = src - > cur_track ) {
GstTagList * tags ;
tags = gst_tag_list_merge ( src - > tags , src - > tracks [ src - > cur_track ] . tags ,
GST_TAG_MERGE_REPLACE ) ;
GST_LOG_OBJECT ( src , " announcing tags: % " GST_PTR_FORMAT , tags ) ;
gst_element_found_tags_for_pad ( GST_ELEMENT ( src ) ,
GST_BASE_SRC_PAD ( src ) , tags ) ;
src - > prev_track = src - > cur_track ;
gst_cdda_base_src_update_duration ( src ) ;
g_object_notify ( G_OBJECT ( src ) , " track " ) ;
}
GST_LOG_OBJECT ( src , " asking for sector %u " , src - > cur_sector ) ;
buf = klass - > read_sector ( src , src - > cur_sector ) ;
if ( buf = = NULL ) {
GST_WARNING_OBJECT ( src , " failed to read sector %u " , src - > cur_sector ) ;
return GST_FLOW_ERROR ;
}
if ( GST_BUFFER_CAPS ( buf ) = = NULL ) {
gst_buffer_set_caps ( buf , GST_PAD_CAPS ( GST_BASE_SRC_PAD ( src ) ) ) ;
}
format = GST_FORMAT_TIME ;
if ( ! gst_pad_query_position ( GST_BASE_SRC_PAD ( src ) , & format , & position ) ) {
position = GST_CLOCK_TIME_NONE ;
}
/* 4 bytes per sample, 44100 samples per second */
duration = gst_util_uint64_scale_int ( GST_BUFFER_SIZE ( buf ) > > 2 , GST_SECOND ,
44100 ) ;
GST_BUFFER_TIMESTAMP ( buf ) = position ;
GST_BUFFER_DURATION ( buf ) = duration ;
GST_LOG_OBJECT ( src , " pushing sector %d with timestamp % " GST_TIME_FORMAT ,
src - > cur_sector , GST_TIME_ARGS ( position ) ) ;
+ + src - > cur_sector ;
* buffer = buf ;
return GST_FLOW_OK ;
}