From 7fa0f0692db43d238700950c62404d0e546883d1 Mon Sep 17 00:00:00 2001 From: Arnold Metselaar Date: Wed, 13 Aug 2008 17:33:05 +0100 Subject: add cdda_class_get_dir method to cdda plugin Date: Thu, 1 May 2008 21:05:55 +0200 This patch adds a cdda_class_get_dir method to the cdda input plugin. I can now add an audio cd to a play-list in Amarok. There may be small interruptions if another cd is playing though, so it would be desirable to lower the priority for access to the cd-drive by the get_dir function. --- src/input/input_cdda.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-) (limited to 'src/input/input_cdda.c') diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index 7b2ebf660..eed7b1593 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -2493,6 +2493,134 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { return 1; } +static xine_mrl_t** cdda_class_get_dir(input_class_t *this_gen, + const char *filename, + int *num_files) { + cdda_input_class_t *this = (cdda_input_class_t *) this_gen; + cdda_input_plugin_t *ip; + cdrom_toc *toc; + char *base_mrl; + int len, frame; + const char * device; + int fd, i, err = -1; + int num_tracks; + + if (filename && *filename) { + device = filename; + if (strncasecmp(device,"cdda:/",6) == 0) { + device += 6; + while ('/' == *device) + device++; + device--; + } + } + else { + device = this->cdda_device; + } + lprintf("cdda_class_get_dir for >%s<\n", device); + + /* get the CD TOC */ + toc = init_cdrom_toc(); + + fd = -1; + + /* we create a new instance because getting a directory of a cd + * should not affect another cd that might be playing. */ + ip = (cdda_input_plugin_t *)xine_xmalloc(sizeof(cdda_input_plugin_t)); + ip->stream = NULL; + ip->fd = -1; + ip->net_fd = -1; + +#ifndef WIN32 + if( strchr(device,':') ) { + fd = network_connect(ip->stream, device); + if( fd != -1 ) { + err = network_read_cdrom_toc(ip->stream, fd, toc); + } + } +#endif + + if (fd == -1) { + if (cdda_open(ip, device, toc, &fd) == -1) { + lprintf("cdda_class_get_dir: opening >%s< failed %s\n", + device, strerror(errno)); + free(ip); + return NULL; + } + +#ifndef WIN32 + err = read_cdrom_toc(fd, toc); +#else + err = read_cdrom_toc(ip, toc); +#endif /* WIN32 */ + } + +#ifdef LOG + print_cdrom_toc(toc); +#endif + + cdda_close(ip); + + if ( err < 0 ) { + free(ip); + return NULL; + } + + num_tracks = toc->last_track - toc->first_track + 1; + + /* this could be done in read_cdrom_toc, but it seems other code doesn't use it */ + frame = toc->leadout_track.first_frame; + for ( i = num_tracks-1 ; i >= 0 ; i--) { + toc->toc_entries[i].total_frames = frame - toc->toc_entries[i].first_frame; + frame = toc->toc_entries[i].first_frame; + } + + if (toc->ignore_last_track) + num_tracks--; + + len = strlen(device) + 5; + base_mrl = xine_xmalloc(len+1); + sprintf(base_mrl, "cdda:%s", device); + + /* allocate space for the mrls's if needed. */ + if (num_tracks+1 > this->mrls_allocated_entries) { + this->mrls = realloc(this->mrls, (num_tracks+1) * sizeof(xine_mrl_t*)); + } + for (i = 0 ; i < num_tracks ; i++) { + if (i < this->mrls_allocated_entries) { + if (this->mrls[i]->origin) + free(this->mrls[i]->origin); + if (this->mrls[i]->mrl) + free(this->mrls[i]->mrl); + if (this->mrls[i]->link) { + free(this->mrls[i]->link); + this->mrls[i]->link = NULL; + } + } + else { + this->mrls[i] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[i]->link = NULL; + this->mrls_allocated_entries++; + } + this->mrls[i]->origin = strdup(base_mrl); + this->mrls[i]->mrl = xine_xmalloc(len+4); + sprintf( this->mrls[i]->mrl, "%s/%d", base_mrl, i+toc->first_track); + this->mrls[i]->type = mrl_cda | mrl_file_blockdev; + this->mrls[i]->size = toc->toc_entries[i].total_frames * CD_RAW_FRAME_SIZE; + } + /* Clean up */ + while(this->mrls_allocated_entries > num_tracks) { + MRL_ZERO(this->mrls[this->mrls_allocated_entries - 1]); + free(this->mrls[this->mrls_allocated_entries--]); + } + free_cdrom_toc(toc); + free(ip); + + this->mrls[num_tracks] = NULL; + *num_files = num_tracks; + return this->mrls; +} + static char ** cdda_class_get_autoplay_list (input_class_t *this_gen, int *num_files) { @@ -2717,8 +2845,7 @@ static void *init_plugin (xine_t *xine, void *data) { this->input_class.get_instance = cdda_class_get_instance; this->input_class.get_identifier = cdda_class_get_identifier; this->input_class.get_description = cdda_class_get_description; - /* this->input_class.get_dir = cdda_class_get_dir; */ - this->input_class.get_dir = NULL; + this->input_class.get_dir = cdda_class_get_dir; this->input_class.get_autoplay_list = cdda_class_get_autoplay_list; this->input_class.dispose = cdda_class_dispose; this->input_class.eject_media = cdda_class_eject_media; -- cgit v1.2.3 From 2c0dd5e118628a7cb2130ee89f78fe6e85240916 Mon Sep 17 00:00:00 2001 From: Arnold Metselaar Date: Wed, 13 Aug 2008 17:33:05 +0100 Subject: Improve parsing of cddb information Date: Thu, 1 May 2008 21:09:25 +0200 This patch improves the parsing of cddb information: * Disc and track titles can now contain '='. * If a track title is of the form / the meta-info will contain the track-artist rather than the disc-artist. I have tested these changes together with my get_dir patch with the sources from debian testing/security and both Amarok and gxine now show the right artists for tracks on a compilation album. --- src/input/input_cdda.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'src/input/input_cdda.c') diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index eed7b1593..305ef6381 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -1475,7 +1475,7 @@ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { if (sscanf(buffer, "DTITLE=%s", &buf[0]) == 1) { char *pt, *artist, *title; - pt = strrchr(buffer, '='); + pt = strchr(buffer, '='); if (pt) { pt++; @@ -1515,7 +1515,7 @@ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { else if (sscanf(buffer, "TTITLE%d=%s", &tnum, &buf[0]) == 2) { char *pt; - pt = strrchr(buffer, '='); + pt = strchr(buffer, '='); if (pt) pt++; if (this->cddb.track[tnum].title == NULL) @@ -2465,15 +2465,31 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { } if(this->cddb.track[this->track].title) { - lprintf("Track %d Title: %s\n", this->track+1, this->cddb.track[this->track].title); - - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->cddb.track[this->track].title); - } + /* Check for track 'titles' of the form / . */ + char *pt; + pt = strstr(this->cddb.track[this->track].title, " / "); + if (pt != NULL) { + char *track_artist; + track_artist = strdup(this->cddb.track[this->track].title); + track_artist[pt - this->cddb.track[this->track].title] = 0; + lprintf("Track %d Artist: %s\n", this->track+1, track_artist); + + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_ARTIST, track_artist); + free(track_artist); + pt += 3; + } + else { + if(this->cddb.disc_artist) { + lprintf("Disc Artist: %s\n", this->cddb.disc_artist); + + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_ARTIST, this->cddb.disc_artist); + } - if(this->cddb.disc_artist) { - lprintf("Disc Artist: %s\n", this->cddb.disc_artist); + pt = this->cddb.track[this->track].title; + } + lprintf("Track %d Title: %s\n", this->track+1, pt); - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_ARTIST, this->cddb.disc_artist); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, pt); } if(this->cddb.disc_category) { -- cgit v1.2.3