/** * Adds a source. */ static int AddSource (services_discovery_t *sd, const pa_source_info *info) { services_discovery_sys_t *sys = sd->p_sys; msg_Dbg (sd, "adding %s (%s)", info->name, info->description); char *mrl; if (unlikely(asprintf (&mrl, "pulse://%s", info->name) == -1)) return -1; input_item_t *item = input_item_NewCard (mrl, info->description); free (mrl); if (unlikely(item == NULL)) return -1; struct device *d = malloc (sizeof (*d)); if (unlikely(d == NULL)) { input_item_Release (item); return -1; } d->index = info->index; d->item = item; struct device **dp = tsearch (d, &sys->root, cmpsrc); if (dp == NULL) /* Out-of-memory */ { free (d); input_item_Release (item); return -1; } if (*dp != d) /* Update existing source */ { free (d); d = *dp; input_item_SetURI (d->item, item->psz_uri); input_item_SetName (d->item, item->psz_name); input_item_Release (item); return 0; } const char *card = pa_proplist_gets(info->proplist, "device.product.name"); services_discovery_AddItemCat(sd, item, (card != NULL) ? card : N_("Generic")); d->sd = sd; return 0; }
input_item_t *input_item_NewWithType( vlc_object_t *p_obj, const char *psz_uri, const char *psz_name, int i_options, const char *const *ppsz_options, unsigned i_option_flags, mtime_t i_duration, int i_type ) { libvlc_priv_t *priv = libvlc_priv (p_obj->p_libvlc); static vlc_mutex_t input_id_lock = VLC_STATIC_MUTEX; input_item_t* p_input = malloc( sizeof(input_item_t ) ); if( !p_input ) return NULL; input_item_Init( p_obj, p_input ); vlc_gc_init( p_input, input_item_Destroy ); vlc_mutex_lock( &input_id_lock ); p_input->i_id = ++priv->i_last_input_id; vlc_mutex_unlock( &input_id_lock ); p_input->b_fixed_name = false; p_input->i_type = i_type; p_input->b_prefers_tree = false; if( psz_uri ) input_item_SetURI( p_input, psz_uri ); if( i_type != ITEM_TYPE_UNKNOWN ) p_input->i_type = i_type; if( psz_name ) input_item_SetName( p_input, psz_name ); p_input->i_duration = i_duration; for( int i = 0; i < i_options; i++ ) input_item_AddOption( p_input, ppsz_options[i], i_option_flags ); return p_input; }
static int Demux( demux_t *p_demux ) { int i_ret = -1; xml_reader_t *p_xml_reader = NULL; char *psz_elname = NULL; input_item_t *p_input; char *psz_mrl = NULL, *psz_title = NULL, *psz_genre = NULL; char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL; input_item_node_t *p_subitems = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); psz_elname = stream_ReadLine( p_demux->s ); free( psz_elname ); psz_elname = NULL; p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto end; /* xml */ /* check root node */ if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "invalid file (no root node)" ); goto end; } if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM || ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL || strcmp( psz_elname, "WinampXML" ) ) { msg_Err( p_demux, "invalid root node %i, %s", xml_ReaderNodeType( p_xml_reader ), psz_elname ); goto end; } FREENULL( psz_elname ); /* root node should not have any attributes, and should only * contain the "playlist node */ /* Skip until 1st child node */ while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 && xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ); if( i_ret != 1 ) { msg_Err( p_demux, "invalid file (no child node)" ); goto end; } if( ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL || strcmp( psz_elname, "playlist" ) ) { msg_Err( p_demux, "invalid child node %s", psz_elname ); goto end; } FREENULL( psz_elname ); // Read the attributes while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { char *psz_name = xml_ReaderName( p_xml_reader ); char *psz_value = xml_ReaderValue( p_xml_reader ); if( !psz_name || !psz_value ) { free( psz_name ); free( psz_value ); goto end; } if( !strcmp( psz_name, "num_entries" ) ) { msg_Dbg( p_demux, "playlist has %d entries", atoi(psz_value) ); } else if( !strcmp( psz_name, "label" ) ) { input_item_SetName( p_current_input, psz_value ); } else { msg_Warn( p_demux, "stray attribute %s with value %s in element" " 'playlist'", psz_name, psz_value ); } free( psz_name ); free( psz_value ); } p_subitems = input_item_node_Create( p_current_input ); while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 ) { // Get the node type switch( xml_ReaderNodeType( p_xml_reader ) ) { // Error case -1: goto end; case XML_READER_STARTELEM: { // Read the element name free( psz_elname ); psz_elname = xml_ReaderName( p_xml_reader ); if( !psz_elname ) goto end; // Read the attributes while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { char *psz_name = xml_ReaderName( p_xml_reader ); char *psz_value = xml_ReaderValue( p_xml_reader ); if( !psz_name || !psz_value ) { free( psz_name ); free( psz_value ); goto end; } if( !strcmp( psz_elname, "entry" ) && !strcmp( psz_name, "Playstring" ) ) { psz_mrl = psz_value; } else { msg_Warn( p_demux, "unexpected attribute %s in element %s", psz_name, psz_elname ); free( psz_value ); } free( psz_name ); } break; } case XML_READER_TEXT: { char *psz_text = xml_ReaderValue( p_xml_reader ); if( IsWhitespace( psz_text ) ) { free( psz_text ); break; } if( !strcmp( psz_elname, "Name" ) ) { psz_title = psz_text; } else if( !strcmp( psz_elname, "Genre" ) ) { psz_genre = psz_text; } else if( !strcmp( psz_elname, "Nowplaying" ) ) { psz_now = psz_text; } else if( !strcmp( psz_elname, "Listeners" ) ) { psz_listeners = psz_text; } else if( !strcmp( psz_elname, "Bitrate" ) ) { psz_bitrate = psz_text; } else if( !strcmp( psz_elname, "" ) ) { free( psz_text ); } else { msg_Warn( p_demux, "unexpected text in element '%s'", psz_elname ); free( psz_text ); } break; } // End element case XML_READER_ENDELEM: { // Read the element name free( psz_elname ); psz_elname = xml_ReaderName( p_xml_reader ); if( !psz_elname ) goto end; if( !strcmp( psz_elname, "entry" ) ) { p_input = input_item_New( p_demux, psz_mrl, psz_title ); if( psz_now ) input_item_SetNowPlaying( p_input, psz_now ); if( psz_genre ) input_item_SetGenre( p_input, psz_genre ); if( psz_listeners ) msg_Err( p_demux, "Unsupported meta listeners" ); if( psz_bitrate ) msg_Err( p_demux, "Unsupported meta bitrate" ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); FREENULL( psz_title ); FREENULL( psz_mrl ); FREENULL( psz_genre ); FREENULL( psz_bitrate ); FREENULL( psz_listeners ); FREENULL( psz_now ); } free( psz_elname ); psz_elname = strdup( "" ); break; } } } if( i_ret != 0 ) { msg_Warn( p_demux, "error while parsing data" ); i_ret = 0; /* Needed for correct operation of go back */ } end: free( psz_elname ); if( p_subitems ) input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref( p_current_input ); if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); return i_ret; }
/* "specs" : http://phobos.apple.com/static/iTunesRSS.html */ static int ReadDir( stream_t *p_demux, input_item_node_t *p_subitems ) { bool b_item = false; bool b_image = false; xml_reader_t *p_xml_reader; char *psz_elname = NULL; char *psz_item_mrl = NULL; char *psz_item_size = NULL; char *psz_item_type = NULL; char *psz_item_name = NULL; char *psz_item_date = NULL; char *psz_item_author = NULL; char *psz_item_category = NULL; char *psz_item_duration = NULL; char *psz_item_keywords = NULL; char *psz_item_subtitle = NULL; char *psz_item_summary = NULL; char *psz_art_url = NULL; const char *node; int i_type; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto error; /* xml */ /* check root node */ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "invalid file (no root node)" ); goto error; } if( strcmp( node, "rss" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); goto error; } while( (i_type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( i_type ) { case XML_READER_STARTELEM: { free( psz_elname ); psz_elname = strdup( node ); if( unlikely(!psz_elname) ) goto error; if( !strcmp( node, "item" ) ) b_item = true; else if( !strcmp( node, "image" ) ) b_image = true; // Read the attributes const char *attr, *value; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( node, "enclosure" ) ) { char **p = NULL; if( !strcmp( attr, "url" ) ) p = &psz_item_mrl; else if( !strcmp( attr, "length" ) ) p = &psz_item_size; else if( !strcmp( attr, "type" ) ) p = &psz_item_type; if( p != NULL ) { free( *p ); *p = strdup( value ); } else msg_Dbg( p_demux,"unhandled attribute %s in <%s>", attr, node ); } else msg_Dbg( p_demux,"unhandled attribute %s in <%s>", attr, node ); } break; } case XML_READER_TEXT: { if(!psz_elname) break; /* item specific meta data */ if( b_item ) { char **p; if( !strcmp( psz_elname, "title" ) ) p = &psz_item_name; else if( !strcmp( psz_elname, "itunes:author" ) || !strcmp( psz_elname, "author" ) ) /* <author> isn't standard iTunes podcast stuff */ p = &psz_item_author; else if( !strcmp( psz_elname, "itunes:summary" ) || !strcmp( psz_elname, "description" ) ) /* <description> isn't standard iTunes podcast stuff */ p = &psz_item_summary; else if( !strcmp( psz_elname, "pubDate" ) ) p = &psz_item_date; else if( !strcmp( psz_elname, "itunes:category" ) ) p = &psz_item_category; else if( !strcmp( psz_elname, "itunes:duration" ) ) p = &psz_item_duration; else if( !strcmp( psz_elname, "itunes:keywords" ) ) p = &psz_item_keywords; else if( !strcmp( psz_elname, "itunes:subtitle" ) ) p = &psz_item_subtitle; else break; free( *p ); *p = strdup( node ); } /* toplevel meta data */ else if( !b_image ) { if( !strcmp( psz_elname, "title" ) ) input_item_SetName( p_current_input, node ); #define ADD_GINFO( info, name ) \ else if( !strcmp( psz_elname, name ) ) \ input_item_AddInfo( p_current_input, _("Podcast Info"), \ info, "%s", node ); ADD_GINFO( _("Podcast Link"), "link" ) ADD_GINFO( _("Podcast Copyright"), "copyright" ) ADD_GINFO( _("Podcast Category"), "itunes:category" ) ADD_GINFO( _("Podcast Keywords"), "itunes:keywords" ) ADD_GINFO( _("Podcast Subtitle"), "itunes:subtitle" ) #undef ADD_GINFO else if( !strcmp( psz_elname, "itunes:summary" ) || !strcmp( psz_elname, "description" ) ) { /* <description> isn't standard iTunes podcast stuff */ input_item_AddInfo( p_current_input, _( "Podcast Info" ), _( "Podcast Summary" ), "%s", node ); } } else { if( !strcmp( psz_elname, "url" ) && *node ) { free( psz_art_url ); psz_art_url = strdup( node ); } else msg_Dbg( p_demux, "unhandled text in element <%s>", psz_elname ); } break; } // End element case XML_READER_ENDELEM: { FREENULL( psz_elname ); if( !strcmp( node, "item" ) ) { if( psz_item_mrl == NULL ) { if (psz_item_name) msg_Warn( p_demux, "invalid XML item, skipping %s", psz_item_name ); else msg_Warn( p_demux, "invalid XML item, skipped" ); FREENULL( psz_item_name ); FREENULL( psz_item_size ); FREENULL( psz_item_type ); FREENULL( psz_item_date ); FREENULL( psz_item_author ); FREENULL( psz_item_category ); FREENULL( psz_item_duration ); FREENULL( psz_item_keywords ); FREENULL( psz_item_subtitle ); FREENULL( psz_item_summary ); FREENULL( psz_art_url ); FREENULL( psz_elname ); continue; } vlc_xml_decode( psz_item_mrl ); vlc_xml_decode( psz_item_name ); p_input = input_item_New( psz_item_mrl, psz_item_name ); FREENULL( psz_item_mrl ); FREENULL( psz_item_name ); if( p_input == NULL ) break; /* FIXME: meta data memory leaks? */ /* Set the duration if available */ if( psz_item_duration ) p_input->i_duration = strTimeToMTime( psz_item_duration ); #define ADD_INFO( info, field ) \ if( field ) { \ input_item_AddInfo( p_input, _( "Podcast Info" ), (info), "%s", \ (field) ); \ FREENULL( field ); } ADD_INFO( _("Podcast Publication Date"), psz_item_date ); ADD_INFO( _("Podcast Author"), psz_item_author ); ADD_INFO( _("Podcast Subcategory"), psz_item_category ); ADD_INFO( _("Podcast Duration"), psz_item_duration ); ADD_INFO( _("Podcast Keywords"), psz_item_keywords ); ADD_INFO( _("Podcast Subtitle"), psz_item_subtitle ); ADD_INFO( _("Podcast Summary"), psz_item_summary ); ADD_INFO( _("Podcast Type"), psz_item_type ); #undef ADD_INFO /* Add the global art url to this item, if any */ if( psz_art_url ) { vlc_xml_decode( psz_art_url ); input_item_SetArtURL( p_input, psz_art_url ); } if( psz_item_size ) { input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Size" ), _("%s bytes"), psz_item_size ); FREENULL( psz_item_size ); } input_item_node_AppendItem( p_subitems, p_input ); input_item_Release( p_input ); b_item = false; } else if( !strcmp( node, "image" ) ) { b_image = false; } break; } } }
static int Demux( demux_t *p_demux ) { int i_ret = -1; xml_reader_t *p_xml_reader = NULL; char *psz_elname = NULL; const char *node; input_item_t *p_input; char *psz_mrl = NULL, *psz_title = NULL, *psz_genre = NULL; char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL; input_item_node_t *p_subitems = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); free( stream_ReadLine( p_demux->s ) ); p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) return -1; /* xml */ /* check root node */ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "invalid file (no root node)" ); goto end; } if( strcmp( node, "WinampXML" ) ) { msg_Err( p_demux, "invalid root node: %s", node ); goto end; } /* root node should not have any attributes, and should only * contain the "playlist node */ /* Skip until 1st child node */ while( (i_ret = xml_ReaderNextNode( p_xml_reader, &node )) != XML_READER_STARTELEM ) if( i_ret <= 0 ) { msg_Err( p_demux, "invalid file (no child node)" ); goto end; } if( strcmp( node, "playlist" ) ) { msg_Err( p_demux, "invalid child node %s", node ); goto end; } // Read the attributes const char *attr, *value; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL ) { if( !strcmp( attr, "num_entries" ) ) msg_Dbg( p_demux, "playlist has %d entries", atoi(value) ); else if( !strcmp( attr, "label" ) ) input_item_SetName( p_current_input, value ); else msg_Warn( p_demux, "stray attribute %s with value %s in element" " <playlist>", attr, value ); } p_subitems = input_item_node_Create( p_current_input ); while( (i_ret = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { // Get the node type switch( i_ret ) { case XML_READER_STARTELEM: { // Read the element name free( psz_elname ); psz_elname = strdup( node ); if( unlikely(!psz_elname) ) goto end; // Read the attributes while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( psz_elname, "entry" ) && !strcmp( attr, "Playstring" ) ) { free( psz_mrl ); psz_mrl = strdup( value ); } else { msg_Warn( p_demux, "unexpected attribute %s in <%s>", attr, psz_elname ); } } break; } case XML_READER_TEXT: { char **p; if( psz_elname == NULL ) break; if( IsWhitespace( node ) ) break; if( !strcmp( psz_elname, "Name" ) ) p = &psz_title; else if( !strcmp( psz_elname, "Genre" ) ) p = &psz_genre; else if( !strcmp( psz_elname, "Nowplaying" ) ) p = &psz_now; else if( !strcmp( psz_elname, "Listeners" ) ) p = &psz_listeners; else if( !strcmp( psz_elname, "Bitrate" ) ) p = &psz_bitrate; else { msg_Warn( p_demux, "unexpected text in element <%s>", psz_elname ); break; } free( *p ); *p = strdup( node ); break; } // End element case XML_READER_ENDELEM: { // Read the element name if( !strcmp( node, "entry" ) ) { p_input = input_item_New( p_demux, psz_mrl, psz_title ); if( psz_now ) input_item_SetNowPlaying( p_input, psz_now ); if( psz_genre ) input_item_SetGenre( p_input, psz_genre ); if( psz_listeners ) msg_Err( p_demux, "Unsupported meta listeners" ); if( psz_bitrate ) msg_Err( p_demux, "Unsupported meta bitrate" ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); FREENULL( psz_title ); FREENULL( psz_mrl ); FREENULL( psz_genre ); FREENULL( psz_bitrate ); FREENULL( psz_listeners ); FREENULL( psz_now ); } FREENULL( psz_elname ); break; } } } if( i_ret < 0 ) { msg_Warn( p_demux, "error while parsing data" ); i_ret = 0; /* Needed for correct operation of go back */ } end: free( psz_elname ); if( p_subitems ) input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref( p_current_input ); if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); return i_ret; }
static int GetTracks( access_t *p_access, input_item_t *p_current ) { access_sys_t *p_sys = p_access->p_sys; const int i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access), p_sys->vcddev, &p_sys->p_sectors ); if( i_titles <= 0 ) { if( i_titles < 0 ) msg_Err( p_access, "unable to count tracks" ); else if( i_titles <= 0 ) msg_Err( p_access, "no audio tracks found" ); return VLC_EGENERIC;; } /* */ input_item_SetName( p_current, "Audio CD" ); const char *psz_album = NULL; const char *psz_year = NULL; const char *psz_genre = NULL; const char *psz_artist = NULL; const char *psz_description = NULL; /* Return true if the given string is not NULL and not empty */ #define NONEMPTY( psz ) ( (psz) && *(psz) ) /* If the given string is NULL or empty, fill it by the return value of 'code' */ #define ON_EMPTY( psz, code ) do { if( !NONEMPTY( psz) ) { (psz) = code; } } while(0) /* Retreive CDDB information */ #ifdef HAVE_LIBCDDB char psz_year_buffer[4+1]; msg_Dbg( p_access, "fetching infos with CDDB" ); cddb_disc_t *p_disc = GetCDDBInfo( p_access, i_titles, p_sys->p_sectors ); if( p_disc ) { psz_album = cddb_disc_get_title( p_disc ); psz_genre = cddb_disc_get_genre( p_disc ); /* */ const unsigned i_year = cddb_disc_get_year( p_disc ); if( i_year > 0 ) { psz_year = psz_year_buffer; snprintf( psz_year_buffer, sizeof(psz_year_buffer), "%u", i_year ); } /* Set artist only if unique */ for( int i = 0; i < i_titles; i++ ) { cddb_track_t *t = cddb_disc_get_track( p_disc, i ); if( !t ) continue; const char *psz_track_artist = cddb_track_get_artist( t ); if( psz_artist && psz_track_artist && strcmp( psz_artist, psz_track_artist ) ) { psz_artist = NULL; break; } psz_artist = psz_track_artist; } } #endif /* CD-Text */ vlc_meta_t **pp_cd_text; int i_cd_text; if( ioctl_GetCdText( VLC_OBJECT(p_access), p_sys->vcddev, &pp_cd_text, &i_cd_text ) ) { msg_Dbg( p_access, "CD-TEXT information missing" ); i_cd_text = 0; pp_cd_text = NULL; } /* Retrieve CD-TEXT information but prefer CDDB */ if( i_cd_text > 0 && pp_cd_text[0] ) { const vlc_meta_t *p_disc = pp_cd_text[0]; ON_EMPTY( psz_album, vlc_meta_Get( p_disc, vlc_meta_Album ) ); ON_EMPTY( psz_genre, vlc_meta_Get( p_disc, vlc_meta_Genre ) ); ON_EMPTY( psz_artist, vlc_meta_Get( p_disc, vlc_meta_Artist ) ); ON_EMPTY( psz_description, vlc_meta_Get( p_disc, vlc_meta_Description ) ); } if( NONEMPTY( psz_album ) ) { input_item_SetName( p_current, psz_album ); input_item_SetAlbum( p_current, psz_album ); } if( NONEMPTY( psz_genre ) ) input_item_SetGenre( p_current, psz_genre ); if( NONEMPTY( psz_artist ) ) input_item_SetArtist( p_current, psz_artist ); if( NONEMPTY( psz_year ) ) input_item_SetDate( p_current, psz_year ); if( NONEMPTY( psz_description ) ) input_item_SetDescription( p_current, psz_description ); const mtime_t i_duration = (int64_t)( p_sys->p_sectors[i_titles] - p_sys->p_sectors[0] ) * CDDA_DATA_SIZE * 1000000 / 44100 / 2 / 2; input_item_SetDuration( p_current, i_duration ); input_item_node_t *p_root = input_item_node_Create( p_current ); /* Build title table */ for( int i = 0; i < i_titles; i++ ) { input_item_t *p_input_item; char *psz_uri, *psz_opt, *psz_first, *psz_last; char *psz_name; msg_Dbg( p_access, "track[%d] start=%d", i, p_sys->p_sectors[i] ); /* */ if( asprintf( &psz_uri, "cdda://%s", p_access->psz_location ) == -1 ) psz_uri = NULL; if( asprintf( &psz_opt, "cdda-track=%i", i+1 ) == -1 ) psz_opt = NULL; if( asprintf( &psz_first, "cdda-first-sector=%i",p_sys->p_sectors[i] ) == -1 ) psz_first = NULL; if( asprintf( &psz_last, "cdda-last-sector=%i", p_sys->p_sectors[i+1] ) == -1 ) psz_last = NULL; /* Define a "default name" */ if( asprintf( &psz_name, _("Audio CD - Track %02i"), (i+1) ) == -1 ) psz_name = NULL; /* Create playlist items */ const mtime_t i_duration = (int64_t)( p_sys->p_sectors[i+1] - p_sys->p_sectors[i] ) * CDDA_DATA_SIZE * 1000000 / 44100 / 2 / 2; p_input_item = input_item_NewWithType( psz_uri, psz_name, 0, NULL, 0, i_duration, ITEM_TYPE_DISC ); input_item_CopyOptions( p_current, p_input_item ); input_item_AddOption( p_input_item, psz_first, VLC_INPUT_OPTION_TRUSTED ); input_item_AddOption( p_input_item, psz_last, VLC_INPUT_OPTION_TRUSTED ); input_item_AddOption( p_input_item, psz_opt, VLC_INPUT_OPTION_TRUSTED ); const char *psz_track_title = NULL; const char *psz_track_artist = NULL; const char *psz_track_genre = NULL; const char *psz_track_description = NULL; #ifdef HAVE_LIBCDDB /* Retreive CDDB information */ if( p_disc ) { cddb_track_t *t = cddb_disc_get_track( p_disc, i ); if( t != NULL ) { psz_track_title = cddb_track_get_title( t ); psz_track_artist = cddb_track_get_artist( t ); } } #endif /* Retreive CD-TEXT information but prefer CDDB */ if( i+1 < i_cd_text && pp_cd_text[i+1] ) { const vlc_meta_t *t = pp_cd_text[i+1]; ON_EMPTY( psz_track_title, vlc_meta_Get( t, vlc_meta_Title ) ); ON_EMPTY( psz_track_artist, vlc_meta_Get( t, vlc_meta_Artist ) ); ON_EMPTY( psz_track_genre, vlc_meta_Get( t, vlc_meta_Genre ) ); ON_EMPTY( psz_track_description, vlc_meta_Get( t, vlc_meta_Description ) ); } /* */ ON_EMPTY( psz_track_artist, psz_artist ); ON_EMPTY( psz_track_genre, psz_genre ); ON_EMPTY( psz_track_description, psz_description ); /* */ if( NONEMPTY( psz_track_title ) ) { input_item_SetName( p_input_item, psz_track_title ); input_item_SetTitle( p_input_item, psz_track_title ); } if( NONEMPTY( psz_track_artist ) ) input_item_SetArtist( p_input_item, psz_track_artist ); if( NONEMPTY( psz_track_genre ) ) input_item_SetGenre( p_input_item, psz_track_genre ); if( NONEMPTY( psz_track_description ) ) input_item_SetDescription( p_input_item, psz_track_description ); if( NONEMPTY( psz_album ) ) input_item_SetAlbum( p_input_item, psz_album ); if( NONEMPTY( psz_year ) ) input_item_SetDate( p_input_item, psz_year ); char psz_num[3+1]; snprintf( psz_num, sizeof(psz_num), "%d", 1+i ); input_item_SetTrackNum( p_input_item, psz_num ); input_item_node_AppendItem( p_root, p_input_item ); vlc_gc_decref( p_input_item ); free( psz_uri ); free( psz_opt ); free( psz_name ); free( psz_first ); free( psz_last ); } #undef ON_EMPTY #undef NONEMPTY input_item_node_PostAndDelete( p_root ); /* */ for( int i = 0; i < i_cd_text; i++ ) { vlc_meta_t *p_meta = pp_cd_text[i]; if( !p_meta ) continue; vlc_meta_Delete( p_meta ); } free( pp_cd_text ); #ifdef HAVE_LIBCDDB if( p_disc ) cddb_disc_destroy( p_disc ); #endif return VLC_SUCCESS; }