diff --git a/THANKS b/THANKS index ba8c5930..39eaa3d0 100644 --- a/THANKS +++ b/THANKS @@ -35,6 +35,9 @@ Justin F. Hallett KO Myung-Hun OS2 Driver +Leon Merten Lohse + Redo CD-Text handling + Kris Verbeeck : CDDB library support from libcddb http://libcddb.sourceforge.net Gentoo ebuild-file diff --git a/example/cdtext.c b/example/cdtext.c index 1d50f89d..7e99ad0b 100644 --- a/example/cdtext.c +++ b/example/cdtext.c @@ -31,34 +31,39 @@ static void -print_cdtext_track_info(CdIo_t *p_cdio, track_t i_track, const char *psz_msg) { - const cdtext_t *cdtext = cdio_get_cdtext(p_cdio, i_track); - if (NULL != cdtext) { - cdtext_field_t i; - - printf("%s\n", psz_msg); - - for (i=0; i < MAX_CDTEXT_FIELDS; i++) { - if (cdtext->field[i]) { - printf("\t%s: %s\n", cdtext_field2str(i), cdtext->field[i]); - } +print_cdtext_track_info(cdtext_t *cdtext, track_t i_track, const char *psz_msg) { + cdtext_field_t i; + + printf("%s\n", psz_msg); + + for (i=0; i < MAX_CDTEXT_FIELDS; i++) { + if (cdtext_get_const(i, i_track, cdtext)) { + printf("\t%s: %s\n", cdtext_field2str(i), cdtext_get_const(i, i_track, cdtext)); } } - + } static void print_disc_info(CdIo_t *p_cdio, track_t i_tracks, track_t i_first_track) { track_t i_last_track = i_first_track+i_tracks; discmode_t cd_discmode = cdio_get_discmode(p_cdio); + cdtext_t *cdtext = cdio_get_cdtext(p_cdio); printf("%s\n", discmode2str[cd_discmode]); - - print_cdtext_track_info(p_cdio, 0, "\nCD-Text for Disc:"); + + if (NULL == cdtext) + { + printf("\nNo CD-Text found on Disc."); + return; + } + + printf("Encoding: %s; Language: %s\n", cdtext->encoding, cdtext->language); + print_cdtext_track_info(cdtext, 0, "\nCD-Text for Disc:"); for ( ; i_first_track < i_last_track; i_first_track++ ) { char psz_msg[50]; snprintf(psz_msg, sizeof(psz_msg), "CD-Text for Track %d:", i_first_track); - print_cdtext_track_info(p_cdio, i_first_track, psz_msg); + print_cdtext_track_info(cdtext, i_first_track, psz_msg); } } diff --git a/include/cdio++/cdtext.hpp b/include/cdio++/cdtext.hpp index 2aeb4b44..21542575 100644 --- a/include/cdio++/cdtext.hpp +++ b/include/cdio++/cdtext.hpp @@ -37,9 +37,9 @@ const char *field2str (cdtext_field_t i) have to be freed. */ -char *get (cdtext_field_t key) +char *get (cdtext_field_t key, track_t i_track) { - return cdtext_get (key, p_cdtext); + return cdtext_get (key, i_track, p_cdtext); } /*! returns the C cdtext_t pointer associated with this object. */ @@ -58,9 +58,9 @@ cdtext_t *get () cdtext object. */ -const char *getConst (cdtext_field_t key) +const char *getConst (cdtext_field_t key, track_t i_track) { - return cdtext_get_const (key, p_cdtext); + return cdtext_get_const (key, i_track, p_cdtext); } /*! @@ -75,9 +75,9 @@ cdtext_field_t isKeyword (const char *key) /*! sets cdtext's keyword entry to field */ -void set (cdtext_field_t key, const char *value) +void set (cdtext_field_t key, track_t i_track, const char *value) { - cdtext_set (key, value, p_cdtext); + cdtext_set (key, i_track, value, p_cdtext); } diff --git a/include/cdio++/device.hpp b/include/cdio++/device.hpp index cbb75ca2..324b5600 100644 --- a/include/cdio++/device.hpp +++ b/include/cdio++/device.hpp @@ -82,14 +82,6 @@ CdIo_t *getCdIo() return p_cdio; } -/*! - Return an opaque CdIo_t pointer for the given track object. -*/ -cdtext_t *getCdtext(track_t i_track) -{ - return cdio_get_cdtext (p_cdio, i_track); -} - /*! Get the CD device name for the object. diff --git a/include/cdio++/disc.hpp b/include/cdio++/disc.hpp index 63223874..b6c8292b 100644 --- a/include/cdio++/disc.hpp +++ b/include/cdio++/disc.hpp @@ -171,4 +171,14 @@ bool isDiscmodeDvd (discmode_t discmode) return cdio_is_discmode_dvd (discmode) ; } +/*! + * Get CD-Text information for a CdIo_t object. + * + * @return the CD-Text object or NULL if obj is NULL + * or CD-Text information does not exist. + * */ +cdtext_t *getCdtext () +{ + return cdio_get_cdtext (p_cdio); +} diff --git a/include/cdio++/track.hpp b/include/cdio++/track.hpp index 3e7942fd..cf7b2b45 100644 --- a/include/cdio++/track.hpp +++ b/include/cdio++/track.hpp @@ -30,17 +30,6 @@ CdIo_t *getCdIo() return p_cdio; } -/*! - Get CD-Text information for a CdIo_t object. - - @return the CD-Text object or NULL if obj is NULL - or CD-Text information does not exist. -*/ -cdtext_t *getCdtext () -{ - return cdio_get_cdtext (p_cdio, i_track); -} - /*! Return number of channels in track: 2 or 4; -2 if not implemented or -1 for error. Not meaningful if track is not an audio track. diff --git a/include/cdio/cdio.h b/include/cdio/cdio.h index 5d8755fd..16ca9131 100644 --- a/include/cdio/cdio.h +++ b/include/cdio/cdio.h @@ -52,8 +52,7 @@ extern "C" { /** This is an opaque structure for the CD object. */ typedef struct _CdIo CdIo_t; - /** This is an opaque structure for the CD-Text object. */ - typedef struct cdtext cdtext_t; + typedef struct cdtext_s cdtext_t; #ifdef __cplusplus } diff --git a/include/cdio/cdtext.h b/include/cdio/cdtext.h index daac733f..43ace908 100644 --- a/include/cdio/cdtext.h +++ b/include/cdio/cdtext.h @@ -37,6 +37,9 @@ extern "C" { #define MAX_CDTEXT_FIELDS 13 #define MIN_CDTEXT_FIELD 0 +#define MAX_CDTEXT_DATA_LENGTH 5000 +#define MAX_CDTEXT_GENRE_CODE 28 + /*! \brief structure for holding CD-Text information @@ -45,6 +48,15 @@ extern "C" { struct cdtext { char *field[MAX_CDTEXT_FIELDS]; }; + typedef struct cdtext cdtext_track_t; + + struct cdtext_s { + cdtext_track_t track[100]; /* cdtext for track 1..99. 0 represents cd-text of disc */ + uint16_t genre_code; /* genre code */ + uint8_t block; + char encoding[16]; /* encoding of character strings */ + char language[3]; /* ISO 639-1 (2 letter) language code */ + }; /*! \brief A list of all of the CD-Text fields. Because the interval has no gaps, we can use ++ to iterate over fields. @@ -68,12 +80,51 @@ extern "C" { /*! Return string representation of the enum values above */ const char *cdtext_field2str (cdtext_field_t i); + + /*! CD-Text genre codes */ + typedef enum { + CDIO_CDTEXT_GENRE_UNUSED = 0, /**< not used */ + CDIO_CDTEXT_GENRE_UNDEFINED = 1, /**< not defined */ + CDIO_CDTEXT_GENRE_ADULT_CONTEMP = 2, /**< Adult Contemporary */ + CDIO_CDTEXT_GENRE_ALT_ROCK = 3, /**< Alternative Rock */ + CDIO_CDTEXT_GENRE_CHILDRENS = 4, /**< Childrens Music */ + CDIO_CDTEXT_GENRE_CLASSIC = 5, /**< Classical */ + CDIO_CDTEXT_GENRE_CHRIST_CONTEMP = 6, /**< Contemporary Christian */ + CDIO_CDTEXT_GENRE_COUNTRY = 7, /**< Country */ + CDIO_CDTEXT_GENRE_DANCE = 8, /**< Dance */ + CDIO_CDTEXT_GENRE_EASY_LISTENING = 9, /**< Easy Listening */ + CDIO_CDTEXT_GENRE_EROTIC = 10, /**< Erotic */ + CDIO_CDTEXT_GENRE_FOLK = 11, /**< Folk */ + CDIO_CDTEXT_GENRE_GOSPEL = 12, /**< Gospel */ + CDIO_CDTEXT_GENRE_HIPHOP = 13, /**< Hip Hop */ + CDIO_CDTEXT_GENRE_JAZZ = 14, /**< Jazz */ + CDIO_CDTEXT_GENRE_LATIN = 15, /**< Latin */ + CDIO_CDTEXT_GENRE_MUSICAL = 16, /**< Musical */ + CDIO_CDTEXT_GENRE_NEWAGE = 17, /**< New Age */ + CDIO_CDTEXT_GENRE_OPERA = 18, /**< Opera */ + CDIO_CDTEXT_GENRE_OPERETTA = 19, /**< Operetta */ + CDIO_CDTEXT_GENRE_POP = 20, /**< Pop Music */ + CDIO_CDTEXT_GENRE_RAP = 21, /**< RAP */ + CDIO_CDTEXT_GENRE_REGGAE = 22, /**< Reggae */ + CDIO_CDTEXT_GENRE_ROCK = 23, /**< Rock Music */ + CDIO_CDTEXT_GENRE_RYTHMANDBLUES = 24, /**< Rhythm & Blues */ + CDIO_CDTEXT_GENRE_SOUNDEFFECTS = 25, /**< Sound Effects */ + CDIO_CDTEXT_GENRE_SOUNDTRACK = 26, /**< Soundtrack */ + CDIO_CDTEXT_GENRE_SPOKEN_WORD = 27, /**< Spoken Word */ + CDIO_CDTEXT_GENRE_WORLD_MUSIC = 28 /**< World Music */ + } cdtext_genre_t; + + /*! Return string representation of the given genre code */ + const char *cdtext_genre2str (cdtext_genre_t i); /*! Initialize a new cdtext structure. When the structure is no longer needed, release the resources using cdtext_delete. */ void cdtext_init (cdtext_t *cdtext); + + /*! Parse raw CD-Text data into cdtext structure */ + bool cdtext_data_init(cdtext_t *cdtext, uint8_t *wdata); /*! Free memory assocated with cdtext*/ void cdtext_destroy (cdtext_t *cdtext); @@ -86,7 +137,8 @@ extern "C" { @see cdio_get_const to retrieve a constant string that doesn't have to be freed. */ - char *cdtext_get (cdtext_field_t key, const cdtext_t *cdtext); + char *cdtext_get (cdtext_field_t key, track_t track, const cdtext_t *cdtext); + /*! returns a const string associated with the given field. NULL is returned if key is CDTEXT_INVALID or the field is not set. @@ -97,7 +149,7 @@ extern "C" { @see cdio_get to retrieve an allocated string that persists past the cdtext object. */ - const char *cdtext_get_const (cdtext_field_t key, const cdtext_t *cdtext); + const char *cdtext_get_const (cdtext_field_t key, track_t track, const cdtext_t *cdtext); /*! returns enum of keyword if key is a CD-Text keyword, @@ -108,7 +160,7 @@ extern "C" { /*! sets cdtext's keyword entry to field */ - void cdtext_set (cdtext_field_t key, const char *value, cdtext_t *cdtext); + void cdtext_set (cdtext_field_t key, track_t track, const char *value, cdtext_t *cdtext); #ifdef __cplusplus } diff --git a/include/cdio/disc.h b/include/cdio/disc.h index 82373c65..638c0320 100644 --- a/include/cdio/disc.h +++ b/include/cdio/disc.h @@ -56,7 +56,25 @@ extern "C" { } discmode_t; extern const char *discmode2str[]; - + /** + Get binary CD-Text information for a CdIo_t object. + + @param p_cdio the CD object that may contain CD-Text information. + @return malloc'd pointer to raw CD-Text data as stored on the disc + or NULL if p_cdio is NULL or CD-Text information does not exist. + Return value should be freed when done with it and not NULL. + */ + uint8_t * cdio_get_cdtext_raw (CdIo_t *p_cdio); + + /** + Get CD-Text information for a CdIo_t object. + + @param p_cdio the CD object that may contain CD-Text information. + @return the CD-Text object or NULL if p_cdio is NULL + or CD-Text information does not exist. + */ + cdtext_t *cdio_get_cdtext (CdIo_t *p_cdio); + /** Get disc mode - the kind of CD (CD-DA, CD-ROM mode 1, CD-MIXED, etc. that we've got. The notion of "CD" is extended a little to include diff --git a/include/cdio/track.h b/include/cdio/track.h index 9deb942b..8eccfdd8 100644 --- a/include/cdio/track.h +++ b/include/cdio/track.h @@ -98,19 +98,6 @@ extern "C" { MODE2_RAW /**< 2352 byte block length */ } trackmode_t; - /*! - Get CD-Text information for a CdIo_t object. - - @param p_cdio the CD object that may contain CD-Text information. - @param i_track track for which we are requesting CD-Text information. - @return the CD-Text object or NULL if obj is NULL - or CD-Text information does not exist. - - If i_track is 0 or CDIO_CDROM_LEADOUT_TRACK the track returned - is the information assocated with the CD. - */ - cdtext_t *cdio_get_cdtext (CdIo_t *p_cdio, track_t i_track); - /*! Get the number of the first track. diff --git a/lib/driver/FreeBSD/freebsd.c b/lib/driver/FreeBSD/freebsd.c index e6ae2f5e..9cb1a2cd 100644 --- a/lib/driver/FreeBSD/freebsd.c +++ b/lib/driver/FreeBSD/freebsd.c @@ -1111,6 +1111,7 @@ cdio_open_am_freebsd (const char *psz_orig_source_name, .get_arg = get_arg_freebsd, .get_blocksize = get_blocksize_mmc, .get_cdtext = get_cdtext_generic, + .get_cdtext_raw = read_cdtext_generic, .get_default_device = cdio_get_default_device_freebsd, .get_devices = cdio_get_devices_freebsd, .get_disc_last_lsn = get_disc_last_lsn_freebsd, @@ -1145,7 +1146,6 @@ cdio_open_am_freebsd (const char *psz_orig_source_name, _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; - _data->gen.b_cdtext_init = false; _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source_name) { diff --git a/lib/driver/MSWindows/win32.c b/lib/driver/MSWindows/win32.c index 6e2cb859..d2c40fb3 100644 --- a/lib/driver/MSWindows/win32.c +++ b/lib/driver/MSWindows/win32.c @@ -306,7 +306,6 @@ init_win32 (void *p_user_data) p_env->gen.init = true; p_env->gen.toc_init = false; - p_env->gen.b_cdtext_init = false; p_env->gen.b_cdtext_error = false; p_env->gen.fd = open (p_env->gen.source_name, O_RDONLY, 0); @@ -962,6 +961,7 @@ cdio_open_am_win32 (const char *psz_orig_source, const char *psz_access_mode) _funcs.free = free_win32; _funcs.get_arg = get_arg_win32; _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_cdtext_raw = read_cdtext_generic; _funcs.get_default_device = cdio_get_default_device_win32; _funcs.get_devices = cdio_get_devices_win32; _funcs.get_disc_last_lsn = get_disc_last_lsn_win32; diff --git a/lib/driver/_cdio_generic.c b/lib/driver/_cdio_generic.c index c7e811d8..7ef14435 100644 --- a/lib/driver/_cdio_generic.c +++ b/lib/driver/_cdio_generic.c @@ -88,15 +88,14 @@ void cdio_generic_free (void *p_user_data) { generic_img_private_t *p_env = p_user_data; - track_t i_track; if (NULL == p_env) return; if (p_env->source_name) free (p_env->source_name); - if (p_env->b_cdtext_init) { - for (i_track=0; i_track < p_env->i_tracks; i_track++) { - cdtext_destroy(&(p_env->cdtext_track[i_track])); - } + if (NULL != p_env->cdtext) { + cdtext_destroy(p_env->cdtext); + free(p_env->cdtext); + p_env->cdtext = NULL; } if (p_env->fd >= 0) @@ -130,7 +129,7 @@ cdio_generic_init (void *user_data, int open_flags) p_env->init = true; p_env->toc_init = false; - p_env->b_cdtext_init = false; + p_env->cdtext = NULL; p_env->b_cdtext_error = false; p_env->i_joliet_level = 0; /* Assume no Joliet extensions initally */ return true; @@ -262,27 +261,31 @@ cdio_add_device_list(char **device_list[], const char *drive, not exist, or we don't know how to get this implemented. */ cdtext_t * -get_cdtext_generic (void *p_user_data, track_t i_track) +get_cdtext_generic (void *p_user_data) { generic_img_private_t *p_env = p_user_data; + uint8_t *p_cdtext_data = NULL; if (!p_env) return NULL; - if (!p_env->toc_init) - p_env->cdio->op.read_toc (p_user_data); - if ( (0 != i_track - && i_track >= p_env->i_tracks+p_env->i_first_track ) ) - return NULL; + if (NULL == p_env->cdtext) { + p_cdtext_data = read_cdtext_generic (p_env); + if (NULL != p_cdtext_data) { + p_env->cdtext = malloc (sizeof(cdtext_t)); + cdtext_init(p_env->cdtext); - if (!p_env->b_cdtext_init) - init_cdtext_generic(p_env); - if (!p_env->b_cdtext_init) return NULL; + if(!cdtext_data_init (p_env->cdtext, p_cdtext_data)) { + p_env->b_cdtext_error = true; + cdtext_destroy (p_env->cdtext); + free(p_env->cdtext); + p_env->cdtext = NULL; + } - if (0 == i_track) - return &(p_env->cdtext); - else - return &(p_env->cdtext_track[i_track-p_env->i_first_track]); + free(p_cdtext_data); + } + } + return p_env->cdtext; } /*! @@ -422,36 +425,20 @@ get_num_tracks_generic(void *p_user_data) return p_env->toc_init ? p_env->i_tracks : CDIO_INVALID_TRACK; } -void -set_cdtext_field_generic(void *p_user_data, track_t i_track, - track_t i_first_track, - cdtext_field_t e_field, const char *psz_value) -{ - char **pp_field; - generic_img_private_t *p_env = p_user_data; - - if( i_track == 0 ) - pp_field = &(p_env->cdtext.field[e_field]); - - else - pp_field = &(p_env->cdtext_track[i_track-i_first_track].field[e_field]); - - if (*pp_field) free(*pp_field); - *pp_field = (psz_value) ? strdup(psz_value) : NULL; -} /*! Read CD-Text information for a CdIo_t object . - return true on success, false on error or CD-Text information does - not exist. + return pointer to raw cdtext on success, + NULL on failure + free when done and not NULL */ -bool -init_cdtext_generic (generic_img_private_t *p_env) +uint8_t * +read_cdtext_generic(void *p_env) { - return mmc_init_cdtext_private( p_env, - p_env->cdio->op.run_mmc_cmd, - set_cdtext_field_generic + generic_img_private_t *p_user_data = p_env; + return mmc_read_cdtext_private (p_user_data, + p_user_data->cdio->op.run_mmc_cmd ); } diff --git a/lib/driver/aix.c b/lib/driver/aix.c index 774ae0ed..4f4ec2d2 100644 --- a/lib/driver/aix.c +++ b/lib/driver/aix.c @@ -110,7 +110,6 @@ typedef struct { lsn_t start_lsn; uchar Control : 4; uchar Format; - cdtext_t cdtext; /* CD-TEXT */ } track_info_t; typedef struct { @@ -172,8 +171,6 @@ init_aix (_img_private_t *p_env) p_env->gen.init = true; p_env->gen.toc_init = false; - p_env->gen.b_cdtext_init = false; - p_env->gen.b_cdtext_error = false; p_env->gen.i_joliet_level = 0; /* Assume no Joliet extensions initally */ p_env->access_mode = _AM_CTRL_SCSI; @@ -946,6 +943,7 @@ cdio_open_am_aix (const char *psz_orig_source, const char *access_mode) _funcs.free = cdio_generic_free; _funcs.get_arg = get_arg_aix; _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_cdtext_raw = read_cdtext_generic; _funcs.get_default_device = cdio_get_default_device_aix; _funcs.get_devices = cdio_get_devices_aix; _funcs.get_disc_last_lsn = get_disc_last_lsn_aix; @@ -973,11 +971,10 @@ cdio_open_am_aix (const char *psz_orig_source, const char *access_mode) _data = calloc (1, sizeof (_img_private_t)); _data->access_mode = _AM_CTRL_SCSI; + _data->gen.b_cdtext_error = false; _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; - _data->gen.b_cdtext_init = false; - _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source) { psz_source = cdio_get_default_device_aix(); diff --git a/lib/driver/bsdi.c b/lib/driver/bsdi.c index d5424eb3..4c0a6ccb 100644 --- a/lib/driver/bsdi.c +++ b/lib/driver/bsdi.c @@ -995,6 +995,7 @@ cdio_open_bsdi (const char *psz_orig_source) .free = cdio_generic_free, .get_arg = _get_arg_bsdi, .get_cdtext = get_cdtext_generic, + .get_cdtext_raw = read_cdtext_generic, .get_default_device = cdio_get_default_device_bsdi, .get_devices = cdio_get_devices_bsdi, .get_drive_cap = get_drive_cap_mmc, @@ -1027,11 +1028,10 @@ cdio_open_bsdi (const char *psz_orig_source) _data = calloc (1, sizeof (_img_private_t)); _data->access_mode = _AM_IOCTL; + _data->gen.b_cdtext_error = false; _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; - _data->gen.b_cdtext_init = false; - _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source) { psz_source=cdio_get_default_device_bsdi(); diff --git a/lib/driver/cdio.c b/lib/driver/cdio.c index 02a9364f..03d1c41e 100644 --- a/lib/driver/cdio.c +++ b/lib/driver/cdio.c @@ -53,25 +53,6 @@ cdio_get_arg (const CdIo *obj, const char key[]) } } -/*! - Get cdtext information for a CdIo object . - - @param obj the CD object that may contain CD-TEXT information. - @return the CD-TEXT object or NULL if obj is NULL - or CD-TEXT information does not exist. -*/ -cdtext_t * -cdio_get_cdtext (CdIo *obj, track_t i_track) -{ - if (obj == NULL) return NULL; - - if (obj->op.get_cdtext) { - return obj->op.get_cdtext (obj->env, i_track); - } else { - return NULL; - } -} - CdIo_t * cdio_new (generic_img_private_t *p_env, cdio_funcs_t *p_funcs) { diff --git a/lib/driver/cdio_private.h b/lib/driver/cdio_private.h index 2b390dc8..e75d873e 100644 --- a/lib/driver/cdio_private.h +++ b/lib/driver/cdio_private.h @@ -150,11 +150,19 @@ extern "C" { @param obj the CD object that may contain CD-TEXT information. @return the CD-TEXT object or NULL if obj is NULL or CD-TEXT information does not exist. - - If i_track is 0 or CDIO_CDROM_LEADOUT_TRACK the track returned - is the information assocated with the CD. */ - cdtext_t * (*get_cdtext) ( void *p_env, track_t i_track ); + cdtext_t * (*get_cdtext) ( void *p_env ); + + /*! + Get raw cdtext information as on the disc for a CdIo object + + @param obj the CD object that may contain CD-TEXT information. + @return pointer to the raw CD-TEXT data or NULL if obj is NULL + or no CD-TEXT information present on the disc. + + free when done and not NULL. + */ + uint8_t * (*get_cdtext_raw) ( void *p_env ); /*! Return an array of device names. if CdIo is NULL (we haven't diff --git a/lib/driver/cdtext.c b/lib/driver/cdtext.c index d1b389e1..f8e9a55a 100644 --- a/lib/driver/cdtext.c +++ b/lib/driver/cdtext.c @@ -37,26 +37,26 @@ #include #endif -#include +#define _CDTEXT_DBCC /*! Note: the order and number items (except CDTEXT_INVALID) should match the cdtext_field_t enumeration. */ static const char cdtext_keywords[][16] = - { - "ARRANGER", - "COMPOSER", - "DISC_ID", - "GENRE", - "MESSAGE", - "ISRC", - "PERFORMER", - "SIZE_INFO", - "SONGWRITER", - "TITLE", - "TOC_INFO", - "TOC_INFO2", - "UPC_EAN", - }; +{ + "ARRANGER", + "COMPOSER", + "DISC_ID", + "GENRE", + "MESSAGE", + "ISRC", + "PERFORMER", + "SIZE_INFO", + "SONGWRITER", + "TITLE", + "TOC_INFO", + "TOC_INFO2", + "UPC_EAN", +}; static const char cdtext_genre[][30] = { @@ -88,7 +88,7 @@ static const char cdtext_genre[][30] = "Sound Effects", "Spoken Word", "World Music" -} ; +}; /*! Return string representation of the enum values above */ const char * @@ -100,19 +100,31 @@ cdtext_field2str (cdtext_field_t i) return cdtext_keywords[i]; } +/*! Return string representation of the given genre oode */ +const char * +cdtext_genre2str (cdtext_genre_t i) +{ + if (i >= MAX_CDTEXT_GENRE_CODE) + return "Invalid genre code"; + else + return cdtext_genre[i]; +} + /*! Free memory assocated with cdtext*/ void cdtext_destroy (cdtext_t *p_cdtext) { cdtext_field_t i; + track_t i2; if (!p_cdtext) return; - for (i=0; i < MAX_CDTEXT_FIELDS; i++) { - if (p_cdtext->field[i]) { - free(p_cdtext->field[i]); - p_cdtext->field[i] = NULL; + for (i2=0; i2<=99; i2++) { + for (i=0; i < MAX_CDTEXT_FIELDS; i++) { + if (p_cdtext->track[i2].field[i]) { + free(p_cdtext->track[i2].field[i]); + p_cdtext->track[i2].field[i] = NULL; + } } - } } @@ -121,18 +133,25 @@ cdtext_destroy (cdtext_t *p_cdtext) if key is CDTEXT_INVALID or the field is not set. */ char * -cdtext_get (cdtext_field_t key, const cdtext_t *p_cdtext) +cdtext_get (cdtext_field_t key, track_t track, const cdtext_t *p_cdtext) { - if ((key == CDTEXT_INVALID) || !p_cdtext - || (!p_cdtext->field[key])) return NULL; - return strdup(p_cdtext->field[key]); + const char *ret = cdtext_get_const(key, track, p_cdtext); + if (NULL == ret) + return NULL; + else + return strdup(ret); } const char * -cdtext_get_const (cdtext_field_t key, const cdtext_t *p_cdtext) +cdtext_get_const (cdtext_field_t key, track_t track, const cdtext_t *p_cdtext) { - if (key == CDTEXT_INVALID) return NULL; - return p_cdtext->field[key]; + if (CDTEXT_INVALID == key + || NULL == p_cdtext + || 0 > track + || 99 < track) + return NULL; + + return p_cdtext->track[track].field[key]; } @@ -144,28 +163,26 @@ void cdtext_init (cdtext_t *p_cdtext) { cdtext_field_t i; + track_t i2; - for (i=0; i < MAX_CDTEXT_FIELDS; i++) { - p_cdtext->field[i] = NULL; + for (i2=0; i2<=99; i2++) { + for (i=0; i < MAX_CDTEXT_FIELDS; i++) { + p_cdtext->track[i2].field[i] = NULL; + } } + + p_cdtext->genre_code = CDIO_CDTEXT_GENRE_UNUSED; + p_cdtext->language[0] = '\0'; + p_cdtext->encoding[0] = '\0'; + p_cdtext->block = 0; } /*! - returns 0 if field is a CD-TEXT keyword, returns non-zero otherwise + returns associated cdtext_field_t if field is a CD-TEXT keyword, returns non-zero otherwise */ cdtext_field_t cdtext_is_keyword (const char *key) { -#if 0 - char *item; - - item = bsearch(key, - cdtext_keywords, 12, - sizeof (char *), - (int (*)(const void *, const void *)) - strcmp); - return (NULL != item) ? 0 : 1; -#else unsigned int i; for (i = 0; i < 13 ; i++) @@ -173,31 +190,29 @@ cdtext_is_keyword (const char *key) return i; } return CDTEXT_INVALID; -#endif } /*! sets cdtext's keyword entry to field. */ void -cdtext_set (cdtext_field_t key, const char *p_value, cdtext_t *p_cdtext) +cdtext_set (cdtext_field_t key, track_t track, const char *p_value, cdtext_t *p_cdtext) { - if (NULL == p_value || key == CDTEXT_INVALID) return; - - if (p_cdtext->field[key]) free (p_cdtext->field[key]); - p_cdtext->field[key] = strdup (p_value); + if (NULL == p_value || key == CDTEXT_INVALID || 0 > track || 99 < track) return; + + if (p_cdtext->track[track].field[key]) + free (p_cdtext->track[track].field[key]); + p_cdtext->track[track].field[key] = strdup (p_value); } #define SET_CDTEXT_FIELD(FIELD) \ - (*set_cdtext_field_fn)(p_user_data, i_track, i_first_track, FIELD, buffer); + cdtext_set(FIELD, i_track, buffer, p_cdtext); /* parse all CD-TEXT data retrieved. */ bool -cdtext_data_init(void *p_user_data, track_t i_first_track, - unsigned char *wdata, int i_data, - set_cdtext_field_fn_t set_cdtext_field_fn) +cdtext_data_init(cdtext_t *p_cdtext, uint8_t *wdata) { CDText_data_t *p_data; int i = -1; @@ -206,14 +221,13 @@ cdtext_data_init(void *p_user_data, track_t i_first_track, int idx; int i_track; bool b_ret = false; - char block = 0; - char encoding[16]; + int block = 0; + uint16_t i_data = CDTEXT_GET_LEN16(wdata) - 2; CDText_blocksize_t p_blocksize; memset( buffer, 0x00, sizeof(buffer) ); idx = 0; - bzero(encoding,16); bzero(&p_blocksize, sizeof(CDText_blocksize_t)); p_data = (CDText_data_t *) (&wdata[4]); @@ -221,26 +235,40 @@ cdtext_data_init(void *p_user_data, track_t i_first_track, for( ; i_data > 0; i_data -= sizeof(CDText_data_t), p_data++ ) { -#if TESTED +#ifndef _CDTEXT_DBCC if ( p_data->bDBC ) { cdio_warn("Double-byte characters not supported"); return false; } #endif - + if ( p_data->seq != ++i || p_data->block != block ) break; /* only handle character packs */ - if ( ((p_data->type >= 0x80) && (p_data->type <= 0x86)) || - (p_data->type == 0x8E)) { - + if ( ((p_data->type >= 0x80) && (p_data->type <= 0x87)) || + (p_data->type == 0x8E)) + { i_track = p_data->i_track; - for( j=0; j < CDIO_CDTEXT_MAX_TEXT_DATA; (p_data->bDBC ? j+=2 : j++) ) { + j = 0; + if (CDIO_CDTEXT_GENRE == p_data->type) { + j = 2; + if (CDIO_CDTEXT_GENRE_UNUSED == p_cdtext->genre_code) { + p_cdtext->genre_code = CDTEXT_GET_LEN16(p_data->text); + } + } + +#ifdef _CDTEXT_DBCC + for( ; j < CDIO_CDTEXT_MAX_TEXT_DATA; (p_data->bDBC ? j+=2 : j++) ) { if( p_data->text[j] == 0x00 && (!p_data->bDBC || p_data->text[j+1] == 0x00)) { + if((buffer[0] != 0x00) && (!p_data->bDBC || buffer[1] != 0x00)) { +#else + for( ; j < CDIO_CDTEXT_MAX_TEXT_DATA; j++) { + if( p_data->text[j] == 0x00) { + if(buffer[0] != 0x00) { +#endif /* omit empty strings */ - if((buffer[0] != 0x00) && (!p_data->bDBC || buffer[1] != 0x00)) { switch( p_data->type) { case CDIO_CDTEXT_TITLE: SET_CDTEXT_FIELD(CDTEXT_TITLE); @@ -273,6 +301,9 @@ cdtext_data_init(void *p_user_data, track_t i_first_track, SET_CDTEXT_FIELD(CDTEXT_ISRC); } break; + case CDIO_CDTEXT_GENRE: + SET_CDTEXT_FIELD(CDTEXT_GENRE); + break; } b_ret = true; @@ -281,82 +312,125 @@ cdtext_data_init(void *p_user_data, track_t i_first_track, } } else { buffer[idx++] = p_data->text[j]; +#ifdef _CDTEXT_DBCC if(p_data->bDBC) buffer[idx++] = p_data->text[j+1]; +#endif } buffer[idx] = 0x00; +#ifdef _CDTEXT_DBCC if(p_data->bDBC) buffer[idx+1] = 0x00; +#endif } } else { /* not a character pack */ - if (p_data->type == CDIO_CDTEXT_GENRE) { - i_track = p_data->i_track; - /* seems like it is a uint_16 in the first 2 bytes */ - if((p_data->text[0] << 8) + p_data->text[1] != CDIO_CDTEXT_GENRE_UNUSED) { - sprintf(buffer,"%s",cdtext_genre[(p_data->text[0] << 8) + p_data->text[1]]); - SET_CDTEXT_FIELD(CDTEXT_GENRE); - } -#ifdef _DEBUG_CDTEXT - printf("GENRE information present: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - p_data->text[0],p_data->text[1],p_data->text[2],p_data->text[3], - p_data->text[4],p_data->text[5],p_data->text[6],p_data->text[7], - p_data->text[8],p_data->text[9],p_data->text[10],p_data->text[11]); -#endif - } if(p_data->type == CDIO_CDTEXT_TOC) { -#ifdef _DEBUG_CDTEXT - printf("TOC information present: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - p_data->text[0],p_data->text[1],p_data->text[2],p_data->text[3], - p_data->text[4],p_data->text[5],p_data->text[6],p_data->text[7], - p_data->text[8],p_data->text[9],p_data->text[10],p_data->text[11]); -#endif + /* no idea what this is */ } if (p_data->type == CDIO_CDTEXT_TOC2) { -#ifdef _DEBUG_CDTEXT - printf("TOC2 information present: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - p_data->text[0],p_data->text[1],p_data->text[2],p_data->text[3], - p_data->text[4],p_data->text[5],p_data->text[6],p_data->text[7], - p_data->text[8],p_data->text[9],p_data->text[10],p_data->text[11]); -#endif + /* no idea what this is */ } /* i got this info from cdrtools' cdda2wav; all the tests i ran so far were successful */ if (p_data->type == CDIO_CDTEXT_BLOCKSIZE) { - /* i_track is the pack element number in this case */ + /* i_track is the pack element number in this case */ switch(p_data->i_track){ - case 0: - memcpy((char*)&p_blocksize,p_data->text,0x0c); - break; - case 1: - memcpy(((char*)&p_blocksize)+0x0c,p_data->text,0x0c); - break; - case 2: - memcpy(((char*)&p_blocksize)+0x18,p_data->text,0x0c); - break; + case 0: + memcpy((char*)&p_blocksize,p_data->text,0x0c); + break; + case 1: + memcpy(((char*)&p_blocksize)+0x0c,p_data->text,0x0c); + break; + case 2: + memcpy(((char*)&p_blocksize)+0x18,p_data->text,0x0c); + break; } } } } - if (p_blocksize.packcount[15] >= 3) { - /* BLOCKSIZE packs present */ + if (p_blocksize.i_packs[15] >= 3) { + /* if there were more than 3 BLOCKSIZE packs */ switch (p_blocksize.charcode){ - case CDIO_CDTEXT_CHARCODE_ISO_8859_1: - sprintf(encoding,"ISO-8859-1"); - break; - case CDIO_CDTEXT_CHARCODE_ASCII: - sprintf(encoding,"ASCII"); - break; - case CDIO_CDTEXT_CHARCODE_KANJI: - sprintf(encoding,"Shift-JIS"); - break; + case CDIO_CDTEXT_CHARCODE_ISO_8859_1: + strcpy(p_cdtext->encoding, "ISO-8859-1"); + break; + case CDIO_CDTEXT_CHARCODE_ASCII: + strcpy(p_cdtext->encoding, "ASCII"); + break; + case CDIO_CDTEXT_CHARCODE_KANJI: + strcpy(p_cdtext->encoding, "Shift-JIS"); + break; + } + + /* set ISO 639-1 code */ + switch (p_blocksize.langcode[block]) { + case CDIO_CDTEXT_LANG_CZECH : + strcpy(p_cdtext->language, "cs"); + break; + case CDIO_CDTEXT_LANG_DANISH : + strcpy(p_cdtext->language, "da"); + break; + case CDIO_CDTEXT_LANG_GERMAN : + strcpy(p_cdtext->language, "de"); + break; + case CDIO_CDTEXT_LANG_ENGLISH : + strcpy(p_cdtext->language, "en"); + break; + case CDIO_CDTEXT_LANG_SPANISH : + strcpy(p_cdtext->language, "es"); + break; + case CDIO_CDTEXT_LANG_FRENCH : + strcpy(p_cdtext->language, "fr"); + break; + case CDIO_CDTEXT_LANG_ITALIAN : + strcpy(p_cdtext->language, "it"); + break; + case CDIO_CDTEXT_LANG_HUNGARIAN : + strcpy(p_cdtext->language, "hu"); + break; + case CDIO_CDTEXT_LANG_DUTCH : + strcpy(p_cdtext->language, "nl"); + break; + case CDIO_CDTEXT_LANG_NORWEGIAN : + strcpy(p_cdtext->language, "no"); + break; + case CDIO_CDTEXT_LANG_POLISH : + strcpy(p_cdtext->language, "pl"); + break; + case CDIO_CDTEXT_LANG_PORTUGUESE : + strcpy(p_cdtext->language, "pt"); + break; + case CDIO_CDTEXT_LANG_SLOVENE : + strcpy(p_cdtext->language, "sl"); + break; + case CDIO_CDTEXT_LANG_FINNISH : + strcpy(p_cdtext->language, "fi"); + break; + case CDIO_CDTEXT_LANG_SWEDISH : + strcpy(p_cdtext->language, "sv"); + break; + case CDIO_CDTEXT_LANG_RUSSIAN : + strcpy(p_cdtext->language, "ru"); + break; + case CDIO_CDTEXT_LANG_KOREAN : + strcpy(p_cdtext->language, "ko"); + break; + case CDIO_CDTEXT_LANG_JAPANESE : + strcpy(p_cdtext->language, "ja"); + break; + case CDIO_CDTEXT_LANG_GREEK : + strcpy(p_cdtext->language, "el"); + break; + case CDIO_CDTEXT_LANG_CHINESE : + strcpy(p_cdtext->language, "zh"); + break; } } - return b_ret; } diff --git a/lib/driver/cdtext_private.h b/lib/driver/cdtext_private.h index 02f338e4..739373d6 100644 --- a/lib/driver/cdtext_private.h +++ b/lib/driver/cdtext_private.h @@ -21,6 +21,8 @@ #include #include +#define CDTEXT_GET_LEN16(p) (p[0]<<8) + p[1] + /*! An enumeration for some of the CDIO_CDTEXT_* #defines below. This isn't really an enumeration one would really use in a program it is here to be helpful in debuggers where wants just to refer to the @@ -44,41 +46,6 @@ extern const enum cdtext_enum1_s { } cdtext_enums1; -/*! - * CD-Text Genre Codes - */ -extern const enum cdtext_genre_enum_s { - CDIO_CDTEXT_GENRE_UNUSED = 0, /**< not used */ - CDIO_CDTEXT_GENRE_UNDEFINED = 1, /**< not defined */ - CDIO_CDTEXT_GENRE_ADULT_CONTEMP = 2, /**< Adult Contemporary */ - CDIO_CDTEXT_GENRE_ALT_ROCK = 3, /**< Alternative Rock */ - CDIO_CDTEXT_GENRE_CHILDRENS = 4, /**< Childrens Music */ - CDIO_CDTEXT_GENRE_CLASSIC = 5, /**< Classical */ - CDIO_CDTEXT_GENRE_CHRIST_CONTEMP = 6, /**< Contemporary Christian */ - CDIO_CDTEXT_GENRE_COUNTRY = 7, /**< Country */ - CDIO_CDTEXT_GENRE_DANCE = 8, /**< Dance */ - CDIO_CDTEXT_GENRE_EASY_LISTENING = 9, /**< Easy Listening */ - CDIO_CDTEXT_GENRE_EROTIC = 10, /**< Erotic */ - CDIO_CDTEXT_GENRE_FOLK = 11, /**< Folk */ - CDIO_CDTEXT_GENRE_GOSPEL = 12, /**< Gospel */ - CDIO_CDTEXT_GENRE_HIPHOP = 13, /**< Hip Hop */ - CDIO_CDTEXT_GENRE_JAZZ = 14, /**< Jazz */ - CDIO_CDTEXT_GENRE_LATIN = 15, /**< Latin */ - CDIO_CDTEXT_GENRE_MUSICAL = 16, /**< Musical */ - CDIO_CDTEXT_GENRE_NEWAGE = 17, /**< New Age */ - CDIO_CDTEXT_GENRE_OPERA = 18, /**< Opera */ - CDIO_CDTEXT_GENRE_OPERETTA = 19, /**< Operetta */ - CDIO_CDTEXT_GENRE_POP = 20, /**< Pop Music */ - CDIO_CDTEXT_GENRE_RAP = 21, /**< RAP */ - CDIO_CDTEXT_GENRE_REGGAE = 22, /**< Reggae */ - CDIO_CDTEXT_GENRE_ROCK = 23, /**< Rock Music */ - CDIO_CDTEXT_GENRE_RYTHMANDBLUES = 24, /**< Rhythm & Blues */ - CDIO_CDTEXT_GENRE_SOUNDEFFECTS = 25, /**< Sound Effects */ - CDIO_CDTEXT_GENRE_SOUNDTRACK = 26, /**< Soundtrack */ - CDIO_CDTEXT_GENRE_SPOKEN_WORD = 27, /**< Spoken Word */ - CDIO_CDTEXT_GENRE_WORLD_MUSIC = 28 /**< World Music */ -} cdtext_genre_enum; - /*! * CD-Text character codes */ @@ -192,36 +159,30 @@ PRAGMA_END_PACKED /* * content of BLOCKSIZE packs */ -typedef struct CDText_blocksize + +PRAGMA_BEGIN_PACKED + +struct CDText_blocksize { uint8_t charcode; /* character code */ - uint8_t i_firstTrack; /* first track number */ - uint8_t i_lastTrack; /* last track number */ + uint8_t i_first_track; /* first track number */ + uint8_t i_last_track; /* last track number */ uint8_t copyright; /* cd-text information copyright byte */ - uint8_t packcount[16];/* number of packs of each type + uint8_t i_packs[16];/* number of packs of each type * 0 TITLE; 1 PERFORMER; 2 SONGWRITER; 3 COMPOSER; * 4 ARRANGER; 5 MESSAGE; 6 DISCID; 7 GENRE; * 8 TOC; 9 TOC2; 10-12 RESERVED; 13 CLOSED; * 14 UPC_ISRC; 15 BLOCKSIZE */ uint8_t lastseq[8]; /* last sequence for block 0..7 */ uint8_t langcode[8]; /* language code for block 0..7 */ -} CDText_blocksize_t; +} GNUC_PACKED; + +PRAGMA_END_PACKED; +typedef struct CDText_blocksize CDText_blocksize_t; typedef struct CDText_data CDText_data_t; -typedef void (*set_cdtext_field_fn_t) (void *user_data, track_t i_track, - track_t i_first_track, - cdtext_field_t field, - const char *buffer); - -/* - Internal routine to parse all CD-TEXT data retrieved. -*/ -bool cdtext_data_init(void *user_data, track_t i_first_track, - unsigned char *wdata, int i_data, - set_cdtext_field_fn_t set_cdtext_field_fn); - #endif /* __CDIO_CDTEXT_PRIVATE_H__ */ diff --git a/lib/driver/disc.c b/lib/driver/disc.c index fc2934fa..3c66ea95 100644 --- a/lib/driver/disc.c +++ b/lib/driver/disc.c @@ -49,6 +49,45 @@ const char *discmode2str[] = { "CD-i" }; +/*! + Get cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. +*/ +cdtext_t * +cdio_get_cdtext (CdIo *obj) +{ + if (obj == NULL) return NULL; + + if (NULL != obj->op.get_cdtext) { + return obj->op.get_cdtext (obj->env); + } else { + return NULL; + } +} + +/*! + Get binary cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return pointer to allocated memory area holding the raw CD-TEXT + or NULL if obj is NULL or CD-TEXT does not exist. + free() when done. +*/ +uint8_t * +cdio_get_cdtext_raw (CdIo *obj) +{ + if (obj == NULL) return NULL; + + if (NULL != obj->op.get_cdtext_raw) { + return obj->op.get_cdtext_raw (obj->env); + } else { + return NULL; + } +} + /*! Get the size of the CD in logical block address (LBA) units. diff --git a/lib/driver/generic.h b/lib/driver/generic.h index 182cbd4d..e0dd2618 100644 --- a/lib/driver/generic.h +++ b/lib/driver/generic.h @@ -43,7 +43,6 @@ extern "C" { char *source_name; /**< Name used in open. */ bool init; /**< True if structure has been initialized */ bool toc_init; /**< True if TOC read in */ - bool b_cdtext_init; /**< True if CD-Text read in */ bool b_cdtext_error; /**< True if trouble reading CD-Text */ int ioctls_debugged; /**< for debugging */ @@ -62,8 +61,7 @@ extern "C" { iso9660_pvd_t pvd; iso9660_svd_t svd; CdIo_t *cdio; /**< a way to call general cdio routines. */ - cdtext_t cdtext; /**< CD-Text for disc. */ - cdtext_t cdtext_track[CDIO_CD_MAX_TRACKS+1]; /**< CD-TEXT for each track*/ + cdtext_t *cdtext; /**< CD-Text for disc. */ track_flags_t track_flags[CDIO_CD_MAX_TRACKS+1]; /* Memorized sense reply of the most recent SCSI command. @@ -177,7 +175,7 @@ extern "C" { @return the CD-TEXT object or NULL if obj is NULL or CD-TEXT information does not exist. */ - cdtext_t *get_cdtext_generic (void *p_user_data, track_t i_track); + cdtext_t *get_cdtext_generic (void *p_user_data); /*! Return the number of of the first track. @@ -220,16 +218,13 @@ extern "C" { track_flag_t get_track_preemphasis_generic(const void *p_user_data, track_t i_track); - void set_cdtext_field_generic(void *user_data, track_t i_track, - track_t i_first_track, - cdtext_field_t e_field, const char *psz_value); /*! Read cdtext information for a CdIo object . return true on success, false on error or CD-Text information does not exist. */ - bool init_cdtext_generic (generic_img_private_t *p_env); + uint8_t * read_cdtext_generic (void *p_env); void set_track_flags(track_flags_t *p_track_flag, uint8_t flag); diff --git a/lib/driver/gnu_linux.c b/lib/driver/gnu_linux.c index 60f44fa9..d8b88533 100644 --- a/lib/driver/gnu_linux.c +++ b/lib/driver/gnu_linux.c @@ -1685,6 +1685,7 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) .get_arg = get_arg_linux, .get_blocksize = get_blocksize_mmc, .get_cdtext = get_cdtext_generic, + .get_cdtext_raw = read_cdtext_generic, .get_default_device = cdio_get_default_device_linux, .get_devices = cdio_get_devices_linux, .get_disc_last_lsn = get_disc_last_lsn_linux, @@ -1736,7 +1737,6 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) _data->gen.init = false; _data->gen.toc_init = false; _data->gen.fd = -1; - _data->gen.b_cdtext_init = false; _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source) { diff --git a/lib/driver/image.h b/lib/driver/image.h index 0a88f555..91c1eb20 100644 --- a/lib/driver/image.h +++ b/lib/driver/image.h @@ -63,7 +63,6 @@ typedef struct { */ track_format_t track_format; bool track_green; - cdtext_t cdtext; /**< CD-TEXT */ trackmode_t mode; uint16_t datasize; /**< How much is in the portion we return diff --git a/lib/driver/image/.gitignore b/lib/driver/image/.gitignore new file mode 100644 index 00000000..aeaec0f7 --- /dev/null +++ b/lib/driver/image/.gitignore @@ -0,0 +1 @@ +/*~ diff --git a/lib/driver/image/bincue.c b/lib/driver/image/bincue.c index 2ddd85dc..d465c48a 100644 --- a/lib/driver/image/bincue.c +++ b/lib/driver/image/bincue.c @@ -87,8 +87,6 @@ _init_bincue (_img_private_t *p_env) p_env->psz_mcn = NULL; p_env->disc_mode = CDIO_DISC_MODE_NO_INFO; - cdtext_init (&(p_env->gen.cdtext)); - lead_lsn = get_disc_last_lsn_bincue( (_img_private_t *) p_env); if (-1 == lead_lsn) return false; @@ -268,8 +266,6 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) if (cd) { cd->gen.i_tracks=0; cd->gen.i_first_track=1; - cd->gen.b_cdtext_init = true; - cd->gen.b_cdtext_error = false; cd->psz_mcn=NULL; } @@ -326,6 +322,52 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) } else { goto not_in_global_section; } + + /* CDTEXTFILE "" */ + } else if (0 == strcmp ("CDTEXTFILE", psz_keyword)) { + if(NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) { + if (cd) { + uint8_t cdt_data[MAX_CDTEXT_DATA_LENGTH+4]; + int size; + int i; + CdioDataSource_t *source; + + if(NULL == (source = cdio_stdio_new(psz_field))) { + cdio_log (log_level, "%s line %d: can't open file `%s' for reading", psz_cue_name, i_line, psz_field); + goto err_exit; + } + size = cdio_stream_read(source, cdt_data, MAX_CDTEXT_DATA_LENGTH, 1); + + if (size < 4) { + cdio_log (log_level, "%s line %d: file `%s' is too small to contain CD-TEXT", psz_cue_name, i_line, psz_field); + goto err_exit; + } + + /* prepend data length if not yet present */ + if (cdt_data[0] >= 0x80) { + for(i=size-1; i >=0; i--) + cdt_data[i+4] = cdt_data[i]; + + cdt_data[0] = (size+2) << 8; + cdt_data[1] = (size+2) & 0xff; + cdt_data[2] = 0x00; + cdt_data[3] = 0x00; + } + + /* init cdtext */ + if (NULL == cd->gen.cdtext) { + cd->gen.cdtext = malloc(sizeof(cdtext_t)); + cdtext_init (cd->gen.cdtext); + } + + if(!cdtext_data_init(cd->gen.cdtext, cdt_data)) + cdio_log (log_level, "%s line %d: failed to parse CD-TEXT file `%s'", psz_cue_name, i_line, psz_field); + + cdio_stdio_destroy (source); + } + } else { + goto format_error; + } /* FILE "" */ } else if (0 == strcmp ("FILE", psz_keyword)) { @@ -357,7 +399,6 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) this_track->track_num = cd->gen.i_tracks; this_track->num_indices = 0; b_first_index_for_track = false; - cdtext_init (&(cd->gen.cdtext_track[cd->gen.i_tracks])); cd->gen.i_tracks++; } i++; @@ -728,18 +769,15 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) /* CD-Text */ } else if ( CDTEXT_INVALID != (cdtext_key = cdtext_is_keyword (psz_keyword)) ) { - if (-1 == i) { - if (cd) { - cdtext_set (cdtext_key, - strtok (NULL, "\"\t\n\r"), - &(cd->gen.cdtext)); - } - } else { - if (cd) { - cdtext_set (cdtext_key, strtok (NULL, "\"\t\n\r"), - &(cd->gen.cdtext_track[i])); - } - } + if (cd) { + if (NULL == cd->gen.cdtext) { + cd->gen.cdtext = malloc(sizeof(cdtext_t)); + cdtext_init (cd->gen.cdtext); + } + cdtext_set (cdtext_key, + (-1 == i ? 0 : cd->gen.i_first_track + i + 1), + strtok (NULL, "\"\t\n\r"), cd->gen.cdtext); + } /* unrecognized line */ } else { @@ -1138,7 +1176,8 @@ cdio_open_cue (const char *psz_cue_name) _funcs.eject_media = _eject_media_image; _funcs.free = _free_image; _funcs.get_arg = _get_arg_image; - _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_cdtext = _get_cdtext_image; + _funcs.get_cdtext_raw = NULL; _funcs.get_devices = cdio_get_devices_bincue; _funcs.get_default_device = cdio_get_default_device_bincue; _funcs.get_disc_last_lsn = get_disc_last_lsn_bincue; diff --git a/lib/driver/image/cdrdao.c b/lib/driver/image/cdrdao.c index 9b9979e7..47dc78e8 100644 --- a/lib/driver/image/cdrdao.c +++ b/lib/driver/image/cdrdao.c @@ -108,8 +108,6 @@ _init_cdrdao (_img_private_t *env) env->psz_mcn = NULL; env->disc_mode = CDIO_DISC_MODE_NO_INFO; - cdtext_init (&(env->gen.cdtext)); - /* Read in TOC sheet. */ if ( !parse_tocfile(env, env->psz_cue_name) ) return false; @@ -292,7 +290,6 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name) } if (cd) { - cd->gen.b_cdtext_init = true; cd->gen.b_cdtext_error = false; } @@ -375,7 +372,6 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name) /* TRACK [] */ } else if (0 == strcmp ("TRACK", psz_keyword)) { i++; - if (NULL != cd) cdtext_init (&(cd->gen.cdtext_track[i])); if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { if (0 == strcmp ("AUDIO", psz_field)) { if (NULL != cd) { @@ -911,19 +907,16 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name) if (i_cdtext_nest > 0) i_cdtext_nest--; } else if ( CDTEXT_INVALID != (cdtext_key = cdtext_is_keyword (psz_keyword)) ) { - if (-1 == i) { - if (NULL != cd) { - cdtext_set (cdtext_key, - strtok (NULL, "\"\t\n\r"), - &(cd->gen.cdtext)); - } - } else { - if (NULL != cd) { - cdtext_set (cdtext_key, - strtok (NULL, "\"\t\n\r"), - &(cd->gen.cdtext_track[i])); - } - } + if (NULL != cd) { + if (NULL == cd->gen.cdtext) { + cd->gen.cdtext = malloc(sizeof(cdtext_t)); + cdtext_init (cd->gen.cdtext); + } + cdtext_set (cdtext_key, + (-1 == i ? 0 : cd->gen.i_first_track + i + 1), + strtok (NULL, "\"\t\n\r"), + cd->gen.cdtext); + } /* unrecognized line */ } else { @@ -1261,7 +1254,8 @@ cdio_open_cdrdao (const char *psz_cue_name) _funcs.eject_media = _eject_media_image; _funcs.free = _free_image; _funcs.get_arg = _get_arg_image; - _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_cdtext = _get_cdtext_image; + _funcs.get_cdtext_raw = NULL; _funcs.get_devices = cdio_get_devices_cdrdao; _funcs.get_default_device = cdio_get_default_device_cdrdao; _funcs.get_disc_last_lsn = get_disc_last_lsn_cdrdao; diff --git a/lib/driver/image/nrg.c b/lib/driver/image/nrg.c index 1573bda7..bdd6af4c 100644 --- a/lib/driver/image/nrg.c +++ b/lib/driver/image/nrg.c @@ -43,6 +43,7 @@ #include "cdio_assert.h" #include "_cdio_stdio.h" #include "nrg.h" +#include "cdtext_private.h" static const char _rcsid[] = "$Id: nrg.c,v 1.31 2008/04/21 18:30:22 karl Exp $"; @@ -431,7 +432,6 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name, } if (0 == disc_mode) { for (i=0; igen.i_tracks; i++) { - cdtext_init (&(p_env->gen.cdtext_track[i])); p_env->tocent[i].track_format= track_format; p_env->tocent[i].datastart = 0; p_env->tocent[i].track_green = false; @@ -446,7 +446,6 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name, } } else if (2 == disc_mode) { for (i=0; igen.i_tracks; i++) { - cdtext_init (&(p_env->gen.cdtext_track[i])); p_env->tocent[i].track_green = true; p_env->tocent[i].track_format= track_format; p_env->tocent[i].datasize = CDIO_CD_FRAMESIZE; @@ -749,7 +748,15 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name, uint8_t *wdata = (uint8_t *) chunk->data; int len = UINT32_FROM_BE (chunk->len); cdio_assert (len % sizeof (CDText_data_t) == 0); - cdtext_data_init (&p_env->gen, p_env->gen.i_first_track, &wdata[-4], len, set_cdtext_field_generic); + p_env->gen.cdtext = malloc(sizeof(cdtext_t)); + cdtext_init (p_env->gen.cdtext); + if(!cdtext_data_init (p_env->gen.cdtext, &wdata[-4])) + { + cdtext_destroy(p_env->gen.cdtext); + free(p_env->gen.cdtext); + p_env->gen.cdtext = NULL; + } + break; } @@ -777,7 +784,6 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name, p_env->tocent[p_env->gen.i_tracks-1].sec_count = cdio_lsn_to_lba(p_env->size - p_env->tocent[p_env->gen.i_tracks-1].start_lba); - p_env->gen.b_cdtext_init = true; p_env->gen.b_cdtext_error = false; p_env->gen.toc_init = true; free(footer_buf); @@ -804,8 +810,6 @@ _init_nrg (_img_private_t *p_env) p_env->psz_mcn = NULL; p_env->disc_mode = CDIO_DISC_MODE_NO_INFO; - cdtext_init (&(p_env->gen.cdtext)); - if ( !parse_nrg (p_env, p_env->gen.source_name, CDIO_LOG_WARN) ) { cdio_warn ("image file %s is not a Nero image", p_env->gen.source_name); @@ -1276,7 +1280,8 @@ cdio_open_nrg (const char *psz_source) _funcs.eject_media = _eject_media_nrg; _funcs.free = _free_nrg; _funcs.get_arg = _get_arg_image; - _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_cdtext = _get_cdtext_image; + _funcs.get_cdtext_raw = NULL; _funcs.get_devices = cdio_get_devices_nrg; _funcs.get_default_device = cdio_get_default_device_nrg; _funcs.get_disc_last_lsn = get_disc_last_lsn_nrg; diff --git a/lib/driver/image_common.c b/lib/driver/image_common.c index 8b91c3f6..da1c9baa 100644 --- a/lib/driver/image_common.c +++ b/lib/driver/image_common.c @@ -63,14 +63,13 @@ _free_image (void *p_user_data) track_info_t *p_tocent = &(p_env->tocent[i_track]); free_if_notnull(p_tocent->filename); free_if_notnull(p_tocent->isrc); - cdtext_destroy(&(p_tocent->cdtext)); if (p_tocent->data_source) cdio_stdio_destroy(p_tocent->data_source); } free_if_notnull(p_env->psz_mcn); free_if_notnull(p_env->psz_cue_name); free_if_notnull(p_env->psz_access_mode); - cdtext_destroy(&(p_env->gen.cdtext)); + cdtext_destroy(p_env->gen.cdtext); cdio_generic_stdio_free(p_env); free(p_env); } @@ -95,6 +94,20 @@ _get_arg_image (void *user_data, const char key[]) return NULL; } +/*! + Return CD-Text object + */ +cdtext_t * +_get_cdtext_image (void *user_data) +{ + generic_img_private_t *p_env = user_data; + + if(!p_env) + return NULL; + + return p_env->cdtext; +} + /*! Get disc type associated with cd_obj. */ diff --git a/lib/driver/image_common.h b/lib/driver/image_common.h index f7949817..c83a06e3 100644 --- a/lib/driver/image_common.h +++ b/lib/driver/image_common.h @@ -78,6 +78,11 @@ int _eject_media_image(void *p_user_data); */ const char * _get_arg_image (void *user_data, const char key[]); +/*! + Return CD-Text object or NULL + */ +cdtext_t * _get_cdtext_image(void *p_user_data); + /*! Get disc type associated with cd_obj. */ diff --git a/lib/driver/libcdio.sym b/lib/driver/libcdio.sym index d936b61b..c2e0fdcd 100644 --- a/lib/driver/libcdio.sym +++ b/lib/driver/libcdio.sym @@ -42,6 +42,7 @@ cdio_free_device_list cdio_from_bcd8 cdio_get_arg cdio_get_cdtext +cdio_get_cdtext_raw cdio_get_default_device cdio_get_default_device_bincue cdio_get_default_device_bsdi @@ -179,6 +180,7 @@ cdio_version_string cdio_warn cdtext_destroy cdtext_field2str +cdtext_genre2str cdtext_get cdtext_get_const cdtext_init diff --git a/lib/driver/mmc/mmc.c b/lib/driver/mmc/mmc.c index d5915719..fab246d1 100644 --- a/lib/driver/mmc/mmc.c +++ b/lib/driver/mmc/mmc.c @@ -324,16 +324,15 @@ mmc_get_mcn_private ( void *p_env, return true on success, false on error or CD-Text information does not exist. */ -bool -mmc_init_cdtext_private ( void *p_user_data, - const mmc_run_cmd_fn_t run_mmc_cmd, - set_cdtext_field_fn_t set_cdtext_field_fn +uint8_t * +mmc_read_cdtext_private ( void *p_user_data, + const mmc_run_cmd_fn_t run_mmc_cmd ) { generic_img_private_t *p_env = p_user_data; mmc_cdb_t cdb = {{0, }}; - unsigned char wdata[5000] = { 0, }; + unsigned char * wdata; int i_status, i_errno; if ( ! p_env || ! run_mmc_cmd || p_env->b_cdtext_error ) @@ -351,38 +350,45 @@ mmc_init_cdtext_private ( void *p_user_data, errno = 0; + wdata = calloc(MAX_CDTEXT_DATA_LENGTH, sizeof(unsigned char)); + /* We may need to give CD-Text a little more time to complete. */ /* First off, just try and read the size */ i_status = run_mmc_cmd (p_env, mmc_read_timeout_ms, mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, - 4, &wdata); + 4, wdata); if (i_status != 0) { cdio_info ("CD-Text read failed for header: %s\n", strerror(errno)); - i_errno = errno; + i_errno = errno; p_env->b_cdtext_error = true; - return false; + free(wdata); + return NULL; } else { /* Now read the CD-Text data */ int i_cdtext = CDIO_MMC_GET_LEN16(wdata); - if (i_cdtext > sizeof(wdata)) i_cdtext = sizeof(wdata); + if (i_cdtext+2 > 5000) + i_cdtext = MAX_CDTEXT_DATA_LENGTH-2; + else + wdata = realloc(wdata,i_cdtext+2); + /* the 2 bytes holding the size are not included in i_cdtext */ + CDIO_MMC_SET_READ_LENGTH16(cdb.field, i_cdtext); i_status = run_mmc_cmd (p_env, mmc_read_timeout_ms, mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, - i_cdtext, &wdata); + i_cdtext, wdata); if (i_status != 0) { cdio_info ("CD-Text read for text failed: %s\n", strerror(errno)); i_errno = errno; p_env->b_cdtext_error = true; - return false; + free(wdata); + return NULL; } - p_env->b_cdtext_init = true; - return cdtext_data_init(p_env, p_env->i_first_track, wdata, i_cdtext-2, - set_cdtext_field_fn); + return wdata; } } diff --git a/lib/driver/mmc/mmc_private.h b/lib/driver/mmc/mmc_private.h index dea2b303..66414e72 100644 --- a/lib/driver/mmc/mmc_private.h +++ b/lib/driver/mmc/mmc_private.h @@ -16,7 +16,6 @@ */ #include -#include "cdtext_private.h" /*! Convert milliseconds to seconds taking the ceiling value, i.e. 1002 milliseconds gets rounded to 2 seconds. @@ -131,9 +130,8 @@ char *mmc_get_mcn_private ( void *p_env, mmc_run_cmd_fn_t run_mmc_cmd ); -bool mmc_init_cdtext_private ( void *p_user_data, - mmc_run_cmd_fn_t run_mmc_cmd, - set_cdtext_field_fn_t set_cdtext_field_fn +uint8_t * mmc_read_cdtext_private ( void *p_user_data, + mmc_run_cmd_fn_t run_mmc_cmd ); /*! diff --git a/lib/driver/netbsd.c b/lib/driver/netbsd.c index 7c33a1f7..dfee81b1 100644 --- a/lib/driver/netbsd.c +++ b/lib/driver/netbsd.c @@ -558,6 +558,7 @@ static cdio_funcs_t _funcs = { .get_arg = get_arg_netbsd, .get_blocksize = get_blocksize_mmc, .get_cdtext = get_cdtext_generic, + .get_cdtext_raw = read_cdtext_generic, .get_default_device = cdio_get_default_device_netbsd, .get_devices = cdio_get_devices_netbsd, .get_disc_last_lsn = get_disc_last_lsn_netbsd, @@ -601,6 +602,7 @@ cdio_open_netbsd(const char *source_name) _img_private_t *_data; _data = calloc(1, sizeof(_img_private_t)); + _data->gen.b_cdtext_error = false; _data->gen.init = false; _data->gen.fd = -1; _data->toc_valid = false; diff --git a/lib/driver/os2.c b/lib/driver/os2.c index fa543e99..c63231c4 100644 --- a/lib/driver/os2.c +++ b/lib/driver/os2.c @@ -650,8 +650,6 @@ init_os2 (void *p_user_data) p_env->gen.init = true; p_env->gen.toc_init = false; - p_env->gen.b_cdtext_init = false; - p_env->gen.b_cdtext_error = false; p_env->gen.fd = p_env->h_cd; return true; @@ -1447,6 +1445,7 @@ cdio_open_os2 (const char *psz_orig_source) _funcs.get_blocksize = get_blocksize_os2; #endif _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_cdtext_raw = read_cdtext_generic; _funcs.get_default_device = cdio_get_default_device_os2; _funcs.get_devices = cdio_get_devices_os2; _funcs.get_disc_last_lsn = get_disc_last_lsn_os2; @@ -1487,6 +1486,7 @@ cdio_open_os2 (const char *psz_orig_source) _data = calloc(1, sizeof (_img_private_t)); _data->access_mode = _AM_OS2; + _data->gen.b_cdtext_error = false; _data->gen.init = false; _data->gen.fd = -1; diff --git a/lib/driver/osx.c b/lib/driver/osx.c index f0ad9ca7..fe7c499a 100644 --- a/lib/driver/osx.c +++ b/lib/driver/osx.c @@ -856,20 +856,6 @@ get_hwinfo_osx ( const CdIo_t *p_cdio, /*out*/ cdio_hwinfo_t *hw_info) } #endif -/* - Get cdtext information in p_user_data for track i_track. - For disc information i_track is 0. - - Return the CD-TEXT or NULL if obj is NULL, - CD-TEXT information does not exist, or (as is the case here) - we don't know how to get this implemented. -*/ -static cdtext_t * -get_cdtext_osx (void *p_user_data, track_t i_track) -{ - return NULL; -} - static void _free_osx (void *p_user_data) { _img_private_t *p_env = p_user_data; @@ -1893,7 +1879,8 @@ cdio_open_osx (const char *psz_orig_source) .eject_media = _eject_media_osx, .free = _free_osx, .get_arg = _get_arg_osx, - .get_cdtext = get_cdtext_osx, + .get_cdtext = NULL, + .get_cdtext_raw = NULL, .get_default_device = cdio_get_default_device_osx, .get_devices = cdio_get_devices_osx, .get_disc_last_lsn = get_disc_last_lsn_osx, @@ -1930,8 +1917,6 @@ cdio_open_osx (const char *psz_orig_source) _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; - _data->gen.b_cdtext_init = false; - _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source) { psz_source=cdio_get_default_device_osx(); diff --git a/lib/driver/solaris.c b/lib/driver/solaris.c index 963730ca..300e17d2 100644 --- a/lib/driver/solaris.c +++ b/lib/driver/solaris.c @@ -1380,6 +1380,7 @@ cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode) _funcs.get_blocksize = get_blocksize_solaris; #endif _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_cdtext_raw = read_cdtext_generic; _funcs.get_default_device = cdio_get_default_device_solaris; _funcs.get_devices = cdio_get_devices_solaris; _funcs.get_disc_last_lsn = get_disc_last_lsn_solaris; @@ -1422,7 +1423,6 @@ cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode) _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; - _data->gen.b_cdtext_init = false; _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source) { diff --git a/src/cd-info.c b/src/cd-info.c index 20572f92..b81bc5d0 100644 --- a/src/cd-info.c +++ b/src/cd-info.c @@ -409,8 +409,7 @@ _cddb_log_handler (cddb_log_level_t level, const char message[]) #endif static void -print_cdtext_track_info(CdIo_t *p_cdio, track_t i_track, const char *psz_msg) { - cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio, i_track); +print_cdtext_track_info(cdtext_t *p_cdtext, track_t i_track, const char *psz_msg) { if (NULL != p_cdtext) { cdtext_field_t i; @@ -418,23 +417,28 @@ print_cdtext_track_info(CdIo_t *p_cdio, track_t i_track, const char *psz_msg) { printf("%s\n", psz_msg); for (i=0; i < MAX_CDTEXT_FIELDS; i++) { - if (p_cdtext->field[i]) { - printf("\t%s: %s\n", cdtext_field2str(i), p_cdtext->field[i]); + if (cdtext_get_const(i, i_track, p_cdtext)) { + printf("\t%s: %s\n", cdtext_field2str(i), cdtext_get_const(i, i_track, p_cdtext)); } } } - cdtext_destroy(p_cdtext); } static void print_cdtext_info(CdIo_t *p_cdio, track_t i_tracks, track_t i_first_track) { track_t i_last_track = i_first_track+i_tracks; + cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio); + + if(NULL == p_cdtext) { + printf("No CD-TEXT on Disc.\n"); + return; + } - print_cdtext_track_info(p_cdio, 0, "\nCD-TEXT for Disc:"); + print_cdtext_track_info(p_cdtext, 0, "\nCD-TEXT for Disc:"); for ( ; i_first_track < i_last_track; i_first_track++ ) { char msg[50]; sprintf(msg, "CD-TEXT for Track %2d:", i_first_track); - print_cdtext_track_info(p_cdio, i_first_track, msg); + print_cdtext_track_info(p_cdtext, i_first_track, msg); } } diff --git a/src/cdda-player.c b/src/cdda-player.c index b400df3b..88cf5a77 100644 --- a/src/cdda-player.c +++ b/src/cdda-player.c @@ -537,23 +537,22 @@ get_cddb_disc_info(CdIo_t *p_cdio) return; } -#define add_cdtext_disc_info(format_str, info_field, FIELD) \ - if (p_cdtext->field[FIELD] && !strlen(info_field)) { \ - snprintf(info_field, sizeof(info_field), format_str, \ - p_cdtext->field[FIELD]); \ - b_cdtext_ ## info_field = true; \ +#define add_cdtext_disc_info(format_str, info_field, FIELD) \ + if (cdtext_get_const(FIELD, 0, p_cdtext) && !strlen(info_field)) { \ + snprintf(info_field, sizeof(info_field), format_str, \ + cdtext_get_const(FIELD, 0, p_cdtext)); \ + b_cdtext_ ## info_field = true; \ } static void get_cdtext_disc_info(CdIo_t *p_cdio) { - cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio, 0); + cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio); if (p_cdtext) { add_cdtext_disc_info("%s", title, CDTEXT_TITLE); add_cdtext_disc_info("%s", artist, CDTEXT_PERFORMER); add_cdtext_disc_info("%s", genre, CDTEXT_GENRE); - cdtext_destroy(p_cdtext); } } @@ -835,10 +834,10 @@ get_cddb_track_info(track_t i_track) } #define add_cdtext_track_info(format_str, info_field, FIELD) \ - if (p_cdtext->field[FIELD]) { \ - snprintf(cd_info[i_track].info_field, \ - sizeof(cd_info[i_track].info_field), \ - format_str, p_cdtext->field[FIELD]); \ + if (cdtext_get_const(FIELD, i_track, p_cdtext)) { \ + snprintf(cd_info[i_track].info_field, \ + sizeof(cd_info[i_track].info_field), \ + format_str, cdtext_get_const(FIELD, i_track, p_cdtext)); \ cd_info[i_track].b_cdtext = true; \ } @@ -847,12 +846,11 @@ static void get_cdtext_track_info(track_t i_track) { - cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio, i_track); + cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio); if (NULL != p_cdtext) { add_cdtext_track_info("%s", title, CDTEXT_TITLE); add_cdtext_track_info("%s", artist, CDTEXT_PERFORMER); - cdtext_destroy(p_cdtext); } } diff --git a/test/cdtext.right b/test/cdtext.right new file mode 100644 index 00000000..2cdc6e3d --- /dev/null +++ b/test/cdtext.right @@ -0,0 +1,49 @@ +__________________________________ + +Disc mode is listed as: CD-DA +CD-ROM Track List (1 - 3) + #: MSF LSN Type Green? Copy? Channels Premphasis? + 1: 00:02:00 000000 audio false no 2 no + 2: 00:04:00 000150 audio false no 2 no + 3: 00:06:00 000300 audio false no 2 no +170: 00:05:56 000281 leadout (645 KB raw, 645 KB formatted) +Media Catalog Number (MCN): not available +Last CD Session LSN: not supported by drive/driver +audio status: not implemented +__________________________________ +CD Analysis Report + +CD-TEXT for Disc: + ARRANGER: The Gnu Community + COMPOSER: Another Gnu + DISC_ID: 0815 42 + GENRE: Animal Soundz + MESSAGE: Gnu lives! + PERFORMER: A Gnu + SONGWRITER: A Gnu, too + TITLE: The Voice of the Gnu + UPC_EAN: 0123456789876 +CD-TEXT for Track 1: + ARRANGER: His Brother + COMPOSER: His Brother + MESSAGE: Free the Gnu! + ISRC: DE-GNU-11-00001 + PERFORMER: Gnu2 + SONGWRITER: Gnu2 + TITLE: I Will Survive +CD-TEXT for Track 2: + ARRANGER: The Guy With the Microphone + COMPOSER: The Alpha Gnu + MESSAGE: Isn't it beatiful? + ISRC: DE-GNU-11-00002 + PERFORMER: Those Particular Gnus + SONGWRITER: None in Particular + TITLE: A Forest Full of Gnus +CD-TEXT for Track 3: + ARRANGER: An Even Less Famous Gnu + COMPOSER: A Not So Famous Gnu + MESSAGE: Every Gnu Is Legal! + ISRC: DE-GNU-11-00003 + PERFORMER: Whatwasitsname? + SONGWRITER: A Famous Gnu + TITLE: Gnu Opera diff --git a/test/check_cue.sh.in b/test/check_cue.sh.in index b0aad8ad..700d455e 100644 --- a/test/check_cue.sh.in +++ b/test/check_cue.sh.in @@ -45,9 +45,26 @@ test_cdinfo "$opts" ${fname}.dump ${srcdir}/${fname}.right RC=$? check_result $RC "cd-info TOC test $testnum" "${CD_INFO} $opts" +fname=cdtext +testnum="CD-Text binary parser" +if test -f ${srcdir}/data/${fname}.bin ; then + if test -f ${srcdir}/data/${fname}.cdt ; then + opts="--quiet --no-device-info --cue-file ${srcdir}/data/${fname}.cue --no-cddb" + cp ${srcdir}/data/${fname}.cdt ${srcdir}/${fname}.cdt + test_cdinfo "$opts" ${fname}.dump ${srcdir}/${fname}.right + rm ${srcdir}/${fname}.cdt + RC=$? + check_result $RC "cd-info CD-Text CUE test $testnum" "${CD_INFO} $opts" + else + echo "Don't see CD-Text file ${srcdir}/data/${fname}.cdt. Test $testnum skipped." + fi +else + echo "Don't see binary file ${srcdir}/data/${fname}.bin. Test $testnum skipped." +fi + fname=isofs-m1 testnum='ISO 9660 mode1 CUE' -if test -f ${srcdir}/${fname}.bin ; then +if test -f ${srcdir}/data/${fname}.bin ; then if test -n "@HAVE_ROCK@"; then opts="-q --no-device-info --no-disc-mode --cue-file ${srcdir}/data/${fname}.cue --iso9660" test_cdinfo "$opts" ${fname}.dump ${srcdir}/${fname}.right @@ -83,7 +100,7 @@ else right=${srcdir}/${fname}_vcdinfo.right fi testnum='Video CD' -if test -f ${srcdir}/${fname}.bin ; then +if test -f ${srcdir}/data/${fname}.bin ; then opts="-q --no-device-info --no-disc-mode -c ${srcdir}/data/${fname}.cue --iso9660" test_cdinfo "$opts" ${fname}.dump $right RC=$? @@ -100,15 +117,15 @@ if test -f ${srcdir}/${fname}.bin ; then RC=$? check_result $RC "cd-info TOC test $testnum" "${CD_INFO} $opts" else - echo "Don't see TOC file ${srcdir}/${fname}.toc. Test $testnum skipped." + echo "Don't see TOC file ${srcdir}/data/${fname}.toc. Test $testnum skipped." fi else - echo "Don't see CUE file ${srcdir}/${fname}.cue. Test $testnum skipped." + echo "Don't see BIN file ${srcdir}/data/${fname}.bin. Test $testnum skipped." fi fname=svcd_ogt_test_ntsc testnum='Super Video CD' -if test -f ${srcdir}/${fname}.bin ; then +if test -f ${srcdir}/data/${fname}.bin ; then opts="-q --no-device-info --no-disc-mode --cue-file ${srcdir}/data/${fname}.cue $vcd_opt --iso9660" test_cdinfo "$opts" ${fname}.dump ${srcdir}/${fname}.right RC=$? diff --git a/test/check_fuzzyiso.sh b/test/check_fuzzyiso.sh index 251409ed..0eb71d9e 100755 --- a/test/check_fuzzyiso.sh +++ b/test/check_fuzzyiso.sh @@ -22,7 +22,7 @@ fi cd $srcdir; src_dir=`pwd` for file in $src_dir/data/*.bin $src_dir/data/*.iso $src_dir/data/*.nrg ; do case "$file" in - $src_dir/data/p1.nrg | $src_dir/data/p1.bin | $src_dir/data/cdda.bin | $src_dir/data/cdda-mcn.nrg | $src_dir/data/svcdgs.nrg ) + $src_dir/data/p1.nrg | $src_dir/data/p1.bin | $src_dir/data/cdda.bin | $src_dir/data/cdda-mcn.nrg | $src_dir/data/svcdgs.nrg | $src_dir/data/cdtext.bin ) good_rc=1 ;; *) diff --git a/test/data/cdtext.cue b/test/data/cdtext.cue new file mode 100644 index 00000000..fcd9f6ac --- /dev/null +++ b/test/data/cdtext.cue @@ -0,0 +1,8 @@ +CDTEXTFILE "cdtext.cdt" +FILE "cdtext.bin" BINARY + TRACK 01 AUDIO + INDEX 01 00:00:00 + TRACK 02 AUDIO + INDEX 01 00:02:00 + TRACK 03 AUDIO + INDEX 01 00:04:00 diff --git a/test/driver/nrg.c.in b/test/driver/nrg.c.in index 877a8a6c..18ee3da5 100644 --- a/test/driver/nrg.c.in +++ b/test/driver/nrg.c.in @@ -75,10 +75,10 @@ main(int argc, const char *argv[]) } { unsigned int i; - cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio, 0); + cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio); if (!p_cdtext) return(1); for (i=0; ifield[cdtext_fields[i]]; + const char *psz_field = cdtext_get_const(cdtext_fields[i], 0, p_cdtext); if (!psz_field) return(2); if (0 != strncmp(psz_field, cdtext_check[i], strlen(cdtext_check[i]))) {