diff --git a/example/cdtext.c b/example/cdtext.c index 4808b086..2d0ebb35 100644 --- a/example/cdtext.c +++ b/example/cdtext.c @@ -1,6 +1,6 @@ /* Copyright (C) 2004, 2005, 2006, 2008, 2009, 2011, 2012 - Rocky Bernstein + Rocky Bernstein This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,6 +18,9 @@ /* Simple program to list CD-Text info of a Compact Disc using libcdio. See also corresponding C++ programs of similar names. */ + +#define EXAMPLE_CUE_FILE "../test/data/cat.cue" + #ifdef HAVE_CONFIG_H #include "config.h" #define __CDIO_CONFIG_H__ 1 @@ -40,8 +43,9 @@ print_cdtext_track_info(cdtext_t *cdtext, track_t i_track, const char *psz_msg) 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)); + if (cdtext_get_const(cdtext, i, i_track)) { + printf("\t%s: %s\n", cdtext_field2str(i), + cdtext_get_const(cdtext, i, i_track)); } } @@ -52,8 +56,9 @@ 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); + int i; - printf("%s\n", discmode2str[cd_discmode]); + printf("Discmode: %s\n", discmode2str[cd_discmode]); if (NULL == cdtext) { @@ -61,13 +66,33 @@ print_disc_info(CdIo_t *p_cdio, track_t i_tracks, track_t i_first_track) { 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(cdtext, i_first_track, psz_msg); + /* print available languages */ + { + cdtext_lang_t *languages; + + printf("\nCD-Text available in: "); + + languages = cdtext_languages_available(cdtext); + for(i=0; i<8; i++) + if ( CDTEXT_LANGUAGE_UNKNOWN != languages[i]) + printf("%s ", cdtext_lang2str(languages[i])); + printf("\n"); + } + + /* select language */ + if(cdtext_select_language(cdtext, "German")) { + printf("%s selected.\n", "German"); + } else { + printf("'%s' is not available. Using '%s'\n", "German", + cdtext_lang2str (cdtext_get_language (cdtext))); + } + + /* print cd-text */ + print_cdtext_track_info(cdtext, 0, "CD-Text for Disc:"); + for (i=i_first_track ; i < i_last_track; i++ ) { + char psz_msg[50]; + snprintf(psz_msg, sizeof(psz_msg), "CD-Text for Track %d:", i); + print_cdtext_track_info(cdtext, i, psz_msg); } } @@ -76,11 +101,13 @@ main(int argc, const char *argv[]) { track_t i_first_track; track_t i_tracks; - CdIo_t *p_cdio = cdio_open ("../test/cdda.cue", DRIVER_BINCUE); - + CdIo_t *p_cdio; + /* read CD-Text from a bin/cue (CDRWIN) image */ + p_cdio = cdio_open(EXAMPLE_CUE_FILE, DRIVER_BINCUE); if (NULL == p_cdio) { - printf("Couldn't open ../test/cdda.cue with BIN/CUE driver.\n"); + printf("Couldn't open %s with BIN/CUE driver.\n", + EXAMPLE_CUE_FILE); } else { i_first_track = cdio_get_first_track_num(p_cdio); i_tracks = cdio_get_num_tracks(p_cdio); @@ -88,14 +115,14 @@ main(int argc, const char *argv[]) cdio_destroy(p_cdio); } + /* read CD-Text from default device */ p_cdio = cdio_open (NULL, DRIVER_DEVICE); - i_first_track = cdio_get_first_track_num(p_cdio); - i_tracks = cdio_get_num_tracks(p_cdio); - if (NULL == p_cdio) { printf("Couldn't find CD\n"); return 77; } else { + i_first_track = cdio_get_first_track_num(p_cdio); + i_tracks = cdio_get_num_tracks(p_cdio); print_disc_info(p_cdio, i_tracks, i_first_track); } diff --git a/include/cdio++/cdio.hpp b/include/cdio++/cdio.hpp index a8bcf222..acb28900 100644 --- a/include/cdio++/cdio.hpp +++ b/include/cdio++/cdio.hpp @@ -101,10 +101,9 @@ void possible_throw_device_exception(driver_return_code_t drc); class CdioCDText { public: - CdioCDText(cdtext_t *p) + CdioCDText() { - p_cdtext = p; - cdtext_init(p); // make sure we're initialized on the C side + p_cdtext = cdtext_init(); // make sure we're initialized on the C side } ~CdioCDText() diff --git a/include/cdio++/cdtext.hpp b/include/cdio++/cdtext.hpp index 21542575..93a3fa26 100644 --- a/include/cdio++/cdtext.hpp +++ b/include/cdio++/cdtext.hpp @@ -28,6 +28,16 @@ const char *field2str (cdtext_field_t i) return cdtext_field2str (i); } +const char *genre2str (cdtext_genre_t i) +{ + return cdtext_genre2str (i); +} + +const char *lang2str (cdtext_lang_t i) +{ + return cdtext_lang2str (i); +} + /*! returns an allocated string associated with the given field. NULL is returned if key is CDTEXT_INVALID or the field is not set. @@ -39,7 +49,7 @@ const char *field2str (cdtext_field_t i) */ char *get (cdtext_field_t key, track_t i_track) { - return cdtext_get (key, i_track, p_cdtext); + return cdtext_get (p_cdtext, key, i_track); } /*! returns the C cdtext_t pointer associated with this object. */ @@ -60,24 +70,15 @@ cdtext_t *get () */ const char *getConst (cdtext_field_t key, track_t i_track) { - return cdtext_get_const (key, i_track, p_cdtext); -} - -/*! - returns enum of keyword if key is a CD-Text keyword, - returns MAX_CDTEXT_FIELDS non-zero otherwise. -*/ -cdtext_field_t isKeyword (const char *key) -{ - return cdtext_is_keyword (key); + return cdtext_get_const (p_cdtext, key, i_track); } /*! sets cdtext's keyword entry to field */ -void set (cdtext_field_t key, track_t i_track, const char *value) +void set (cdtext_field_t key, track_t i_track, const uint8_t *value, const char *charset) { - cdtext_set (key, i_track, value, p_cdtext); + cdtext_set (p_cdtext, key, value, i_track, charset); } diff --git a/include/cdio/cdio.h b/include/cdio/cdio.h index 9792e942..044f3469 100644 --- a/include/cdio/cdio.h +++ b/include/cdio/cdio.h @@ -45,8 +45,6 @@ extern "C" { /** This is an opaque structure for the CD object. */ typedef struct _CdIo CdIo_t; - typedef struct cdtext_s cdtext_t; - #ifdef __cplusplus } #endif /* __cplusplus */ @@ -56,6 +54,9 @@ extern "C" { */ #include +/* CD-Text-related functions. */ +#include + /* Disc-related functions. */ #include @@ -64,9 +65,6 @@ extern "C" { */ #include -/* CD-Text-related functions. */ -#include - /* Track-related functions. */ #include diff --git a/include/cdio/cdtext.h b/include/cdio/cdtext.h index c7231e50..42cf9aa1 100644 --- a/include/cdio/cdtext.h +++ b/include/cdio/cdtext.h @@ -29,139 +29,278 @@ #ifndef __CDIO_CDTEXT_H__ #define __CDIO_CDTEXT_H__ -#include +#include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#define MAX_CDTEXT_FIELDS 13 -#define MIN_CDTEXT_FIELD 0 -#define MAX_CDTEXT_DATA_LENGTH 5000 -#define MAX_CDTEXT_GENRE_CODE 28 +#define MAX_CDTEXT_FIELDS 10 +/*! Enumeration of CD-TEXT text fields. */ +typedef enum { + CDTEXT_FIELD_TITLE = 0, /**< title of album name or track titles */ + CDTEXT_FIELD_PERFORMER = 1, /**< name(s) of the performer(s) */ + CDTEXT_FIELD_SONGWRITER = 2, /**< name(s) of the songwriter(s) */ + CDTEXT_FIELD_COMPOSER = 3, /**< name(s) of the composer(s) */ + CDTEXT_FIELD_MESSAGE = 4, /**< message(s) from content provider or artist, ISO-8859-1 encoded*/ + CDTEXT_FIELD_ARRANGER = 5, /**< name(s) of the arranger(s) */ + CDTEXT_FIELD_ISRC = 6, /**< ISRC code of each track */ + CDTEXT_FIELD_UPC_EAN = 7, /**< upc/european article number of disc, ISO-8859-1 encoded */ + CDTEXT_FIELD_GENRE = 8, /**< genre identification and genre information, ASCII encoded */ + CDTEXT_FIELD_DISCID = 9, /**< disc identification, ASCII encoded (may be non-printable) */ + CDTEXT_FIELD_INVALID = MAX_CDTEXT_FIELDS /**< INVALID FIELD*/ +} cdtext_field_t; + +/*! Enumeration of possible genre codes. */ +typedef enum { + CDTEXT_GENRE_UNUSED = 0, /**< field is not used. default */ + CDTEXT_GENRE_UNDEFINED = 1, /**< not defined */ + CDTEXT_GENRE_ADULT_CONTEMP = 2, /**< Adult Contemporary */ + CDTEXT_GENRE_ALT_ROCK = 3, /**< Alternative Rock */ + CDTEXT_GENRE_CHILDRENS = 4, /**< Childrens Music */ + CDTEXT_GENRE_CLASSIC = 5, /**< Classical */ + CDTEXT_GENRE_CHRIST_CONTEMP = 6, /**< Contemporary Christian */ + CDTEXT_GENRE_COUNTRY = 7, /**< Country */ + CDTEXT_GENRE_DANCE = 8, /**< Dance */ + CDTEXT_GENRE_EASY_LISTENING = 9, /**< Easy Listening */ + CDTEXT_GENRE_EROTIC = 10, /**< Erotic */ + CDTEXT_GENRE_FOLK = 11, /**< Folk */ + CDTEXT_GENRE_GOSPEL = 12, /**< Gospel */ + CDTEXT_GENRE_HIPHOP = 13, /**< Hip Hop */ + CDTEXT_GENRE_JAZZ = 14, /**< Jazz */ + CDTEXT_GENRE_LATIN = 15, /**< Latin */ + CDTEXT_GENRE_MUSICAL = 16, /**< Musical */ + CDTEXT_GENRE_NEWAGE = 17, /**< New Age */ + CDTEXT_GENRE_OPERA = 18, /**< Opera */ + CDTEXT_GENRE_OPERETTA = 19, /**< Operetta */ + CDTEXT_GENRE_POP = 20, /**< Pop Music */ + CDTEXT_GENRE_RAP = 21, /**< RAP */ + CDTEXT_GENRE_REGGAE = 22, /**< Reggae */ + CDTEXT_GENRE_ROCK = 23, /**< Rock Music */ + CDTEXT_GENRE_RYTHMANDBLUES = 24, /**< Rhythm & Blues */ + CDTEXT_GENRE_SOUNDEFFECTS = 25, /**< Sound Effects */ + CDTEXT_GENRE_SOUNDTRACK = 26, /**< Soundtrack */ + CDTEXT_GENRE_SPOKEN_WORD = 27, /**< Spoken Word */ + CDTEXT_GENRE_WORLD_MUSIC = 28 /**< World Music */ +} cdtext_genre_t; + +/*! Enumeration of possible CD-TEXT languages. + * + * The language code is encoded as specified in ANNEX 1 to part 5 of EBU + * Tech 32 58 -E (1991). + */ +typedef enum { + CDTEXT_LANGUAGE_UNKNOWN = 0x00, + CDTEXT_LANGUAGE_ALBANIAN = 0x01, + CDTEXT_LANGUAGE_BRETON = 0x02, + CDTEXT_LANGUAGE_CATALAN = 0x03, + CDTEXT_LANGUAGE_CROATIAN = 0x04, + CDTEXT_LANGUAGE_WELSH = 0x05, + CDTEXT_LANGUAGE_CZECH = 0x06, + CDTEXT_LANGUAGE_DANISH = 0x07, + CDTEXT_LANGUAGE_GERMAN = 0x08, + CDTEXT_LANGUAGE_ENGLISH = 0x09, + CDTEXT_LANGUAGE_SPANISH = 0x0A, + CDTEXT_LANGUAGE_ESPERANTO = 0x0B, + CDTEXT_LANGUAGE_ESTONIAN = 0x0C, + CDTEXT_LANGUAGE_BASQUE = 0x0D, + CDTEXT_LANGUAGE_FAROESE = 0x0E, + CDTEXT_LANGUAGE_FRENCH = 0x0F, + CDTEXT_LANGUAGE_FRISIAN = 0x10, + CDTEXT_LANGUAGE_IRISH = 0x11, + CDTEXT_LANGUAGE_GAELIC = 0x12, + CDTEXT_LANGUAGE_GALICIAN = 0x13, + CDTEXT_LANGUAGE_ICELANDIC = 0x14, + CDTEXT_LANGUAGE_ITALIAN = 0x15, + CDTEXT_LANGUAGE_LAPPISH = 0x16, + CDTEXT_LANGUAGE_LATIN = 0x17, + CDTEXT_LANGUAGE_LATVIAN = 0x18, + CDTEXT_LANGUAGE_LUXEMBOURGIAN = 0x19, + CDTEXT_LANGUAGE_LITHUANIAN = 0x1A, + CDTEXT_LANGUAGE_HUNGARIAN = 0x1B, + CDTEXT_LANGUAGE_MALTESE = 0x1C, + CDTEXT_LANGUAGE_DUTCH = 0x1D, + CDTEXT_LANGUAGE_NORWEGIAN = 0x1E, + CDTEXT_LANGUAGE_OCCITAN = 0x1F, + CDTEXT_LANGUAGE_POLISH = 0x20, + CDTEXT_LANGUAGE_PORTUGUESE = 0x21, + CDTEXT_LANGUAGE_ROMANIAN = 0x22, + CDTEXT_LANGUAGE_ROMANSH = 0x23, + CDTEXT_LANGUAGE_SERBIAN = 0x24, + CDTEXT_LANGUAGE_SLOVAK = 0x25, + CDTEXT_LANGUAGE_SLOVENIAN = 0x26, + CDTEXT_LANGUAGE_FINNISH = 0x27, + CDTEXT_LANGUAGE_SWEDISH = 0x28, + CDTEXT_LANGUAGE_TURKISH = 0x29, + CDTEXT_LANGUAGE_FLEMISH = 0x2A, + CDTEXT_LANGUAGE_WALLON = 0x2B, + CDTEXT_LANGUAGE_ZULU = 0x45, + CDTEXT_LANGUAGE_VIETNAMESE = 0x46, + CDTEXT_LANGUAGE_UZBEK = 0x47, + CDTEXT_LANGUAGE_URDU = 0x48, + CDTEXT_LANGUAGE_UKRAINIAN = 0x49, + CDTEXT_LANGUAGE_THAI = 0x4A, + CDTEXT_LANGUAGE_TELUGU = 0x4B, + CDTEXT_LANGUAGE_TATAR = 0x4C, + CDTEXT_LANGUAGE_TAMIL = 0x4D, + CDTEXT_LANGUAGE_TADZHIK = 0x4E, + CDTEXT_LANGUAGE_SWAHILI = 0x4F, + CDTEXT_LANGUAGE_SRANANTONGO = 0x50, + CDTEXT_LANGUAGE_SOMALI = 0x51, + CDTEXT_LANGUAGE_SINHALESE = 0x52, + CDTEXT_LANGUAGE_SHONA = 0x53, + CDTEXT_LANGUAGE_SERBO_CROAT = 0x54, + CDTEXT_LANGUAGE_RUTHENIAN = 0x55, + CDTEXT_LANGUAGE_RUSSIAN = 0x56, + CDTEXT_LANGUAGE_QUECHUA = 0x57, + CDTEXT_LANGUAGE_PUSHTU = 0x58, + CDTEXT_LANGUAGE_PUNJABI = 0x59, + CDTEXT_LANGUAGE_PERSIAN = 0x5A, + CDTEXT_LANGUAGE_PAPAMIENTO = 0x5B, + CDTEXT_LANGUAGE_ORIYA = 0x5C, + CDTEXT_LANGUAGE_NEPALI = 0x5D, + CDTEXT_LANGUAGE_NDEBELE = 0x5E, + CDTEXT_LANGUAGE_MARATHI = 0x5F, + CDTEXT_LANGUAGE_MOLDAVIAN = 0x60, + CDTEXT_LANGUAGE_MALAYSIAN = 0x61, + CDTEXT_LANGUAGE_MALAGASAY = 0x62, + CDTEXT_LANGUAGE_MACEDONIAN = 0x63, + CDTEXT_LANGUAGE_LAOTIAN = 0x64, + CDTEXT_LANGUAGE_KOREAN = 0x65, + CDTEXT_LANGUAGE_KHMER = 0x66, + CDTEXT_LANGUAGE_KAZAKH = 0x67, + CDTEXT_LANGUAGE_KANNADA = 0x68, + CDTEXT_LANGUAGE_JAPANESE = 0x69, + CDTEXT_LANGUAGE_INDONESIAN = 0x6A, + CDTEXT_LANGUAGE_HINDI = 0x6B, + CDTEXT_LANGUAGE_HEBREW = 0x6C, + CDTEXT_LANGUAGE_HAUSA = 0x6D, + CDTEXT_LANGUAGE_GURANI = 0x6E, + CDTEXT_LANGUAGE_GUJURATI = 0x6F, + CDTEXT_LANGUAGE_GREEK = 0x70, + CDTEXT_LANGUAGE_GEORGIAN = 0x71, + CDTEXT_LANGUAGE_FULANI = 0x72, + CDTEXT_LANGUAGE_DARI = 0x73, + CDTEXT_LANGUAGE_CHURASH = 0x74, + CDTEXT_LANGUAGE_CHINESE = 0x75, + CDTEXT_LANGUAGE_BURMESE = 0x76, + CDTEXT_LANGUAGE_BULGARIAN = 0x77, + CDTEXT_LANGUAGE_BENGALI = 0x78, + CDTEXT_LANGUAGE_BIELORUSSIAN = 0x79, + CDTEXT_LANGUAGE_BAMBORA = 0x7A, + CDTEXT_LANGUAGE_AZERBAIJANI = 0x7B, + CDTEXT_LANGUAGE_ASSAMESE = 0x7C, + CDTEXT_LANGUAGE_ARMENIAN = 0x7D, + CDTEXT_LANGUAGE_ARABIC = 0x7E, + CDTEXT_LANGUAGE_AMHARIC = 0x7F +} cdtext_lang_t; + +/*! + Opaque type for CD-Text. +*/ +typedef struct cdtext_s cdtext_t; + +/*! + Return string representation of the given genre code. +*/ +const char *cdtext_genre2str (cdtext_genre_t i); + +/*! + Return string representation of the given language code. +*/ +const char *cdtext_lang2str (cdtext_lang_t i); + +/*! + Return string representation of given field type. +*/ +const char *cdtext_field2str (cdtext_field_t i); + +/*! + Initialize a new cdtext structure. + + When the structure is no longer needed, release the + resources using cdtext_delete. +*/ +cdtext_t *cdtext_init (void); + +/*! + Read a binary CD-TEXT and fill a cdtext struct. + + @param p_cdtext the CD-TEXT object + @param wdata the data + @param i_data size of wdata + + @returns 0 on success, non-zero on failure +*/ +int cdtext_data_init(cdtext_t *p_cdtext, uint8_t *wdata, size_t length); + +/*! + Free memory associated with the given cdtext_t object. + + @param p_cdtext the CD-TEXT object +*/ +void cdtext_destroy (cdtext_t *p_cdtext); + +/*! + Returns a copy of the return value of cdtext_get_const or NULL. + + Should be freed when done. + @see cdtext_get_const +*/ +char *cdtext_get (const cdtext_t *p_cdtext, cdtext_field_t key, track_t track); + +/*! + Returns value of the given field. + + NULL is returned if key is CDTEXT_INVALID or the field is not set. + Strings are encoded in UTF-8. + + @param p_cdtext the CD-TEXT object + @param field type of the field to return + @param track specifies the track, 0 stands for disc +*/ +const char *cdtext_get_const (const cdtext_t *p_cdtext, cdtext_field_t key, track_t track); + +/*! + Returns the currently active language. + + @param p_cdtext the CD-TEXT object +*/ +cdtext_lang_t cdtext_get_language (const cdtext_t *p_cdtext); + +/*! + Try to select the given language. + + @param p_cdtext the CD-TEXT object + @param language string representation of the language + + @return true on success, false if language is not available +*/ +bool cdtext_select_language(cdtext_t *p_cdtext, const char *lang); + +/* + Returns a list of available languages or NULL. + + Internally the list is stored in a static array. + + @param p_cdtext the CD-TEXT object +*/ +cdtext_lang_t *cdtext_languages_available (const cdtext_t *p_cdtext); + +/*! + Sets the given field at the given track to the given value. - /*! \brief structure for holding CD-Text information - - @see cdtext_init, cdtext_destroy, cdtext_get, and cdtext_set. - */ - 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 */ - }; + Recodes to UTF-8 if charset is not NULL. - /*! \brief A list of all of the CD-Text fields. Because - the interval has no gaps, we can use ++ to iterate over fields. - */ - typedef enum { - CDTEXT_ARRANGER = 0, /**< name(s) of the arranger(s) */ - CDTEXT_COMPOSER = 1, /**< name(s) of the composer(s) */ - CDTEXT_DISCID = 2, /**< disc identification information */ - CDTEXT_GENRE = 3, /**< genre identification and genre information */ - CDTEXT_MESSAGE = 4, /**< ISRC code of each track */ - CDTEXT_ISRC = 5, /**< message(s) from the content provider or artist */ - CDTEXT_PERFORMER = 6, /**< name(s) of the performer(s) */ - CDTEXT_SIZE_INFO = 7, /**< size information of the block */ - CDTEXT_SONGWRITER = 8, /**< name(s) of the songwriter(s) */ - CDTEXT_TITLE = 9, /**< title of album name or track titles */ - CDTEXT_TOC_INFO = 10, /**< table of contents information */ - CDTEXT_TOC_INFO2 = 11, /**< second table of contents information */ - CDTEXT_UPC_EAN = 12, - CDTEXT_INVALID = MAX_CDTEXT_FIELDS - } cdtext_field_t; + @param p_cdtext the CD-TEXT object + @param key field to set + @param value value to set + @param track track to work on + @param charset charset to convert from + */ +void cdtext_set (cdtext_t *p_cdtext, cdtext_field_t key, const uint8_t *value, track_t track, const char *charset); - /*! 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, size_t length); - - /*! Free memory assocated with cdtext*/ - void cdtext_destroy (cdtext_t *cdtext); - - /*! returns an allocated string associated with the given field. NULL is - returned if key is CDTEXT_INVALID or the field is not set. - - The user needs to free the string when done with it. - - @see cdio_get_const to retrieve a constant string that doesn't - have to be freed. - */ - 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. - - Don't use the string when the cdtext object (i.e. the CdIo_t object - you got it from) is no longer valid. - - @see cdio_get to retrieve an allocated string that persists past - the cdtext object. - */ - 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, - returns MAX_CDTEXT_FIELDS non-zero otherwise. - */ - cdtext_field_t cdtext_is_keyword (const char *key); - - /*! - sets cdtext's keyword entry to field - */ - void cdtext_set (cdtext_field_t key, track_t track, const char *value, cdtext_t *cdtext); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/cdio/disc.h b/include/cdio/disc.h index 638c0320..3e51cb80 100644 --- a/include/cdio/disc.h +++ b/include/cdio/disc.h @@ -56,6 +56,7 @@ extern "C" { } discmode_t; extern const char *discmode2str[]; + /** Get binary CD-Text information for a CdIo_t object. diff --git a/include/cdio/utf8.h b/include/cdio/utf8.h index 236105e9..6e79e7fe 100644 --- a/include/cdio/utf8.h +++ b/include/cdio/utf8.h @@ -87,6 +87,6 @@ bool cdio_charset_from_utf8(cdio_utf8_t * src, char ** dst, */ -bool cdio_charset_to_utf8(char *src, size_t src_len, cdio_utf8_t **dst, +bool cdio_charset_to_utf8(const char *src, size_t src_len, cdio_utf8_t **dst, const char * src_charset); diff --git a/lib/driver/FreeBSD/freebsd_cam.c b/lib/driver/FreeBSD/freebsd_cam.c index df4c3923..9eb66355 100644 --- a/lib/driver/FreeBSD/freebsd_cam.c +++ b/lib/driver/FreeBSD/freebsd_cam.c @@ -1,5 +1,6 @@ /* - Copyright (C) 2004, 2005, 2008, 2009, 2010 Rocky Bernstein + Copyright (C) 2004, 2005, 2008, 2009, 2010, 2012 + Rocky Bernstein This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -317,7 +318,7 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx_) return -1; } - bzero(&(idx->ccb), sizeof(union ccb)); + memset(&(idx->ccb), 0, sizeof(union ccb)); idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID; idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; diff --git a/lib/driver/MSWindows/aspi32.c b/lib/driver/MSWindows/aspi32.c index 781484cf..e710d9b8 100644 --- a/lib/driver/MSWindows/aspi32.c +++ b/lib/driver/MSWindows/aspi32.c @@ -50,7 +50,6 @@ #include #include #include "aspi32.h" -#include "cdtext_private.h" /* Amount of time we are willing to wait for an operation to complete. 10 seconds? diff --git a/lib/driver/MSWindows/aspi32.h b/lib/driver/MSWindows/aspi32.h index 2be044cb..9f12c7df 100644 --- a/lib/driver/MSWindows/aspi32.h +++ b/lib/driver/MSWindows/aspi32.h @@ -189,14 +189,6 @@ track_format_t get_track_format_aspi(const _img_private_t *env, */ bool init_aspi (_img_private_t *env); -/* - Read cdtext information for a CdIo object . - - return true on success, false on error or CD-TEXT information does - not exist. -*/ -bool init_cdtext_aspi (_img_private_t *env); - const char *is_cdrom_aspi(const char drive_letter); /*! diff --git a/lib/driver/MSWindows/win32.h b/lib/driver/MSWindows/win32.h index e0eb5cee..3136cadc 100644 --- a/lib/driver/MSWindows/win32.h +++ b/lib/driver/MSWindows/win32.h @@ -25,7 +25,6 @@ typedef struct { lsn_t start_lsn; UCHAR Control : 4; UCHAR Format; - cdtext_t cdtext; /* CD-TEXT */ } track_info_t; typedef enum { @@ -197,14 +196,6 @@ bool read_toc_win32ioctl (_img_private_t *p_env); */ char *get_mcn_win32ioctl (const _img_private_t *p_env); -/* - Read cdtext information for a CdIo object . - - return true on success, false on error or CD-TEXT information does - not exist. -*/ -bool init_cdtext_win32ioctl (_img_private_t *p_env); - /*! Return the the kind of drive capabilities of device. @@ -234,8 +225,3 @@ void get_drive_cap_win32ioctl (const _img_private_t *p_env, */ track_format_t get_track_format_win32ioctl(const _img_private_t *p_env, track_t i_track); - -void set_cdtext_field_win32(void *user_data, track_t i_track, - track_t i_first_track, - cdtext_field_t e_field, const char *psz_value); - diff --git a/lib/driver/MSWindows/win32_ioctl.c b/lib/driver/MSWindows/win32_ioctl.c index 6e95cf5c..482517c7 100755 --- a/lib/driver/MSWindows/win32_ioctl.c +++ b/lib/driver/MSWindows/win32_ioctl.c @@ -58,7 +58,6 @@ #include #include "cdio_assert.h" #include -#include "cdtext_private.h" #include "cdio/logging.h" #if defined (_XBOX) diff --git a/lib/driver/_cdio_generic.c b/lib/driver/_cdio_generic.c index 36352686..6af11761 100644 --- a/lib/driver/_cdio_generic.c +++ b/lib/driver/_cdio_generic.c @@ -286,8 +286,7 @@ get_cdtext_generic (void *p_user_data) 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); + p_env->cdtext = cdtext_init(); len = CDIO_MMC_GET_LEN16(p_cdtext_data); if(!cdtext_data_init (p_env->cdtext, &p_cdtext_data[4], len-2)) { diff --git a/lib/driver/cdtext.c b/lib/driver/cdtext.c index 1fe0c5ea..dda3a8d2 100644 --- a/lib/driver/cdtext.c +++ b/lib/driver/cdtext.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004, 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 2004, 2005, 2008, 2011, 2012 Rocky Bernstein toc reading routine adapted from cuetools Copyright (C) 2003 Svend Sanjay Sorensen @@ -25,6 +25,7 @@ #include #include #include "cdtext_private.h" +#include #ifdef HAVE_STDLIB_H #include @@ -33,32 +34,26 @@ #ifdef HAVE_STRING_H #include #endif -#ifdef HAVE_STRINGS_H -#include -#endif #define _CDTEXT_DBCC +#define MAX_CDTEXT_GENRE_CODE 28 +#define MAX_CDTEXT_LANGUAGE_CODE 127 -/*! Note: the order and number items (except CDTEXT_INVALID) should - match the cdtext_field_t enumeration. */ -static const char cdtext_keywords[][16] = +const char *cdtext_field[MAX_CDTEXT_FIELDS] = { - "ARRANGER", - "COMPOSER", - "DISC_ID", - "GENRE", - "MESSAGE", - "ISRC", - "PERFORMER", - "SIZE_INFO", - "SONGWRITER", "TITLE", - "TOC_INFO", - "TOC_INFO2", + "PERFORMER", + "SONGWRITER", + "COMPOSER", + "MESSAGE", + "ARRANGER", + "ISRC", "UPC_EAN", + "GENRE", + "DISC_ID", }; -static const char cdtext_genre[][30] = +const char *cdtext_genre[MAX_CDTEXT_GENRE_CODE] = { "Not Used", "Not Defined", @@ -90,349 +85,655 @@ static const char cdtext_genre[][30] = "World Music" }; -/*! Return string representation of the enum values above */ +const char *cdtext_language[MAX_CDTEXT_LANGUAGE_CODE] = +{ + "Unknown", + "Albanian", + "Breton", + "Catalan", + "Croatian", + "Welsh", + "Czech", + "Danish", + "German", + "English", + "Spanish", + "Esperanto", + "Estonian", + "Basque", + "Faroese", + "French", + "Frisian", + "Irish", + "Gaelic", + "Galician", + "Icelandic", + "Italian", + "Lappish", + "Latin", + "Latvian", + "Luxembourgian", + "Lithuanian", + "Hungarian", + "Maltese", + "Dutch", + "Norwegian", + "Occitan", + "Polish", + "Portuguese", + "Romanian", + "Romansh", + "Serbian", + "Slovak", + "Slovenian", + "Finnish", + "Swedish", + "Turkish", + "Flemish", + "Wallon", + "Zulu", + "Vietnamese", + "Uzbek", + "Urdu", + "Ukrainian", + "Thai", + "Telugu", + "Tatar", + "Tamil", + "Tadzhik", + "Swahili", + "SrananTongo", + "Somali", + "Sinhalese", + "Shona", + "Serbo-croat", + "Ruthenian", + "Russian", + "Russian", + "Quechua", + "Pushtu", + "Punjabi", + "Persian", + "Papamiento", + "Oriya", + "Nepali", + "Ndebele", + "Marathi", + "Moldavian", + "Malaysian", + "Malagasay", + "Macedonian", + "Laotian", + "Korean", + "Khmer", + "Kazakh", + "Kannada", + "Japanese", + "Indonesian", + "Hindi", + "Hebrew", + "Hausa", + "Gurani", + "Gujurati", + "Greek", + "Georgian", + "Fulani", + "Dari", + "Churash", + "Chinese", + "Burmese", + "Bulgarian", + "Bengali", + "Bielorussian", + "Bambora", + "Azerbaijani", + "Assamese", + "Armenian", + "Arabic", + "Amharic" +}; + +/*! + Return string representation of given field type. +*/ const char * cdtext_field2str (cdtext_field_t i) { if (i >= MAX_CDTEXT_FIELDS) - return "Invalid CDTEXT field index"; + return "INVALID"; else - return cdtext_keywords[i]; + return cdtext_field[i]; } -/*! Return string representation of the given genre oode */ +/*! + Return string representation of the given genre code. +*/ const char * cdtext_genre2str (cdtext_genre_t i) { if (i >= MAX_CDTEXT_GENRE_CODE) - return "Invalid genre code"; + return "INVALID"; else return cdtext_genre[i]; } -/*! Free memory assocated with cdtext*/ +/*! + Return string representation of the given language code. +*/ +const char * +cdtext_lang2str (cdtext_lang_t i) +{ + if (i >= MAX_CDTEXT_LANGUAGE_CODE) + return "INVALID"; + else + return cdtext_language[i]; +} + +/*! + Free memory associated with the given cdtext_t object. + + @param p_cdtext the CD-TEXT object +*/ void cdtext_destroy (cdtext_t *p_cdtext) { - cdtext_field_t i; - track_t i2; + cdtext_field_t k; + track_t j; + int i; if (!p_cdtext) return; - 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; + for (i=0; iblock[i].track[j].field[k]) { + free(p_cdtext->block[i].track[j].field[k]); + p_cdtext->block[i].track[j].field[k] = NULL; + } } } } } -/*! - returns the CDTEXT value associated with key. NULL is returned - if key is CDTEXT_INVALID or the field is not set. - */ +/*! + Returns a copy of the return value of cdtext_get_const or NULL. + + Should be freed when done. + @see cdtext_get_const +*/ char * -cdtext_get (cdtext_field_t key, track_t track, const cdtext_t *p_cdtext) +cdtext_get (const cdtext_t *p_cdtext, cdtext_field_t field, track_t track) { - const char *ret = cdtext_get_const(key, track, p_cdtext); + const char *ret = cdtext_get_const(p_cdtext, field, track); if (NULL == ret) return NULL; else return strdup(ret); } +/*! + Returns value of the given field. + + NULL is returned if key is CDTEXT_INVALID or the field is not set. + Strings are encoded in UTF-8. + + @param p_cdtext the CD-TEXT object + @param field type of the field to return + @param track specifies the track, 0 stands for disc +*/ const char * -cdtext_get_const (cdtext_field_t key, track_t track, const cdtext_t *p_cdtext) +cdtext_get_const(const cdtext_t *p_cdtext, cdtext_field_t field, track_t track) { - if (CDTEXT_INVALID == key + if (CDTEXT_FIELD_INVALID == field || NULL == p_cdtext || 0 > track || 99 < track) return NULL; - return p_cdtext->track[track].field[key]; + return p_cdtext->block[p_cdtext->block_i].track[track].field[field]; } -/*! Initialize a new cdtext structure. +/*! + Returns the currently active language. + + @param p_cdtext the CD-TEXT object +*/ +cdtext_lang_t +cdtext_get_language(const cdtext_t *p_cdtext) +{ + if (NULL == p_cdtext) + return CDTEXT_LANGUAGE_UNKNOWN; + return p_cdtext->block[p_cdtext->block_i].language_code; +} + +/* + Returns a list of available languages or NULL. + + Internally the list is stored in a static array. + + @param p_cdtext the CD-TEXT object +*/ +cdtext_lang_t +*cdtext_languages_available (const cdtext_t *p_cdtext) +{ + static cdtext_lang_t avail[CDTEXT_NUM_BLOCKS_MAX]; + int i, j=0; + + if (NULL == p_cdtext) + return NULL; + + for (i=0; iblock[i].language_code) + avail[j++] = p_cdtext->block[i].language_code; + } + return avail; +} + + +/*! + Try to select the given language. + Select default language if specified is not available or invalid and + return false. + + @param p_cdtext the CD-TEXT object + @param language string representation of the language + + @return true on success, false if language is not available +*/ +bool +cdtext_select_language(cdtext_t *p_cdtext, const char *language) +{ + cdtext_lang_t lang_id; + lang_id = cdtext_is_language(language); + + if(NULL == p_cdtext) + return false; + + if (CDTEXT_LANGUAGE_UNKNOWN != lang_id) + { + int i; + for (i=0; iblock[i].language_code) { + p_cdtext->block_i = i; + return true; + } + } + } else { + p_cdtext->block_i = 0; + } + return false; +} + +/*! + Initialize a new cdtext structure. + When the structure is no longer needed, release the resources using cdtext_delete. */ -void -cdtext_init (cdtext_t *p_cdtext) +cdtext_t +*cdtext_init (void) { - cdtext_field_t i; - track_t i2; + cdtext_field_t k; + track_t j; + int i; + cdtext_t *p_cdtext; - for (i2=0; i2<=99; i2++) { - for (i=0; i < MAX_CDTEXT_FIELDS; i++) { - p_cdtext->track[i2].field[i] = NULL; + p_cdtext = (cdtext_t *) malloc (sizeof (struct cdtext_s)); + + for (i=0; iblock[i].track[j].field[k] = NULL; + } } } - p_cdtext->genre_code = CDIO_CDTEXT_GENRE_UNUSED; - p_cdtext->language[0] = '\0'; - p_cdtext->encoding[0] = '\0'; - p_cdtext->block = 0; + p_cdtext->block_i = 0; + + return p_cdtext; } /*! - returns associated cdtext_field_t if field is a CD-TEXT keyword, returns non-zero otherwise + Returns associated cdtext_field_t if field is a CD-TEXT keyword. + + Internal function. + + @param key key to test + + @return CDTEXT_INVALID if the given keyword is invalid */ cdtext_field_t -cdtext_is_keyword (const char *key) +cdtext_is_field(const char *key) { unsigned int i; - for (i = 0; i < 13 ; i++) - if (0 == strcmp (cdtext_keywords[i], key)) { + for (i = 0; i < MAX_CDTEXT_FIELDS ; i++) + if (0 == strcmp (cdtext_field[i], key)) { return i; } - return CDTEXT_INVALID; + return CDTEXT_FIELD_INVALID; } -/*! sets cdtext's keyword entry to field. +/*! + Returns associated cdtext_lang_t if argument is a supported language. + + Internal function. + + @param lang language to test + + @return CDTEXT_LANGUAGE_UNKNOWN if language is not supported +*/ +cdtext_lang_t +cdtext_is_language (const char *lang) +{ + unsigned int i; + + for (i = 0; i < MAX_CDTEXT_LANGUAGE_CODE; i++) + if (0 == strcmp (cdtext_language[i], lang)) { + return i; + } + return CDTEXT_LANGUAGE_UNKNOWN; +} + +/*! + Sets the given field at the given track to the given value. + + Recodes to UTF-8 if charset is not NULL. + + @param p_cdtext the CD-TEXT object + @param key field to set + @param value value to set + @param track track to work on + @param charset charset to convert from */ void -cdtext_set (cdtext_field_t key, track_t track, const char *p_value, cdtext_t *p_cdtext) +cdtext_set (cdtext_t *p_cdtext, cdtext_field_t key, const uint8_t *value, + track_t track, const char *charset) { - if (NULL == p_value || key == CDTEXT_INVALID || 0 > track || 99 < track) return; + if (NULL == value || key == CDTEXT_FIELD_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); - -} + /* free old memory */ + if (p_cdtext->block[p_cdtext->block_i].track[track].field[key]) + free (p_cdtext->block[p_cdtext->block_i].track[track].field[key]); -#define SET_CDTEXT_FIELD(FIELD) \ - cdtext_set(FIELD, i_track, buffer, p_cdtext); + /* recode to UTF-8 */ + if (NULL != charset) { + cdio_utf8_t *utf8_str = NULL; + cdio_charset_to_utf8((const char*) value, strlen((const char*)value), + &utf8_str, charset); + p_cdtext->block[p_cdtext->block_i].track[track].field[key] = + (char *)utf8_str; + } else + p_cdtext->block[p_cdtext->block_i].track[track].field[key] = strdup ((const char *)value); + } -/* - parse all CD-TEXT data retrieved. +/*! + Read a binary CD-TEXT and fill a cdtext struct. + + @param p_cdtext the CD-TEXT object + @param wdata the data + @param i_data size of wdata + + @returns 0 on success, non-zero on failure */ -bool +int cdtext_data_init(cdtext_t *p_cdtext, uint8_t *wdata, size_t i_data) { - CDText_data_t *p_data; - int i; - int j; - char buffer[256]; - int idx; - int i_track; - bool b_ret = false; - int block = 0; - CDText_blocksize_t p_blocksize; - - memset( buffer, 0x00, sizeof(buffer) ); - idx = 0; - - memset( &p_blocksize, 0x00, sizeof(CDText_blocksize_t) ); +/* uint8_t *p_data; */ +/* int j; */ +/* uint8_t buffer[256]; */ +/* int i_buf = 0; */ +/* int i_block; */ +/* int i_seq = 0; */ +/* int i; */ +/* cdtext_blocksize_t blocksize; */ +/* char *charset = NULL; */ - p_data = (CDText_data_t *) wdata; - if (0 != i_data % sizeof(CDText_data_t)) { - cdio_warn("CD-Text size is not multiple of pack size"); - return false; - } +/* p_data = wdata; */ +/* if (i_data < CDTEXT_LEN_PACK || 0 != i_data % CDTEXT_LEN_PACK) { */ +/* cdio_warn("CD-Text size is not multiple of pack size"); */ +/* return -1; */ +/* } */ - for( i = -1; i_data > 0; i_data -= sizeof(CDText_data_t), p_data++ ) { - -#ifndef _CDTEXT_DBCC - if ( p_data->bDBC ) { - cdio_warn("Double-byte characters not supported"); - return false; - } -#endif +/* #if 0 */ +/* for(i=0; i < i_data; i++) */ +/* printf("%0x%c", wdata[i], ((i+1) % 18 == 0 ? '\n' : ' ')); */ +/* #endif */ - if ( p_data->seq != ++i || p_data->block != block ) break; - /* only handle character packs */ - if ( ((p_data->type >= 0x80) && (p_data->type <= 0x87)) || - (p_data->type == 0x8E)) - { - i_track = p_data->i_track; +/* /\* Iterate over blocks *\/ */ +/* i_block = -1; */ +/* while(i_data > 0) { */ +/* cdtext_pack_t pack; */ +/* cdtext_read_pack(&pack, p_data); */ - 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); - } - } +/* if (i_block != pack.block || i_seq != pack.seq) { */ +/* cdtext_pack_t tpack; */ +/* i_block = pack.block; */ +/* if (i_block >= CDTEXT_NUM_BLOCKS_MAX) { */ +/* cdio_warn("CD-TEXT: Invalid blocknumber %d.\n", i_block); */ +/* return -1; */ +/* } */ +/* p_cdtext->block_i = i_block; */ +/* i_seq = 0; */ +/* memset( &blocksize, 0, CDTEXT_LEN_BLOCKSIZE); */ -#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 */ - switch( p_data->type) { - case CDIO_CDTEXT_TITLE: - SET_CDTEXT_FIELD(CDTEXT_TITLE); - break; - case CDIO_CDTEXT_PERFORMER: - SET_CDTEXT_FIELD(CDTEXT_PERFORMER); - break; - case CDIO_CDTEXT_SONGWRITER: - SET_CDTEXT_FIELD(CDTEXT_SONGWRITER); - break; - case CDIO_CDTEXT_COMPOSER: - SET_CDTEXT_FIELD(CDTEXT_COMPOSER); - break; - case CDIO_CDTEXT_ARRANGER: - SET_CDTEXT_FIELD(CDTEXT_ARRANGER); - break; - case CDIO_CDTEXT_MESSAGE: - SET_CDTEXT_FIELD(CDTEXT_MESSAGE); - break; - case CDIO_CDTEXT_DISCID: - if(i_track == 0) { - SET_CDTEXT_FIELD(CDTEXT_DISCID); - } - break; - case CDIO_CDTEXT_UPC: - if(i_track == 0) { - SET_CDTEXT_FIELD(CDTEXT_UPC_EAN); - } - else { - SET_CDTEXT_FIELD(CDTEXT_ISRC); - } - break; - case CDIO_CDTEXT_GENRE: - SET_CDTEXT_FIELD(CDTEXT_GENRE); - break; - } - - b_ret = true; - i_track++; - idx = 0; - } - } else { - buffer[idx++] = p_data->text[j]; -#ifdef _CDTEXT_DBCC - if(p_data->bDBC) - buffer[idx++] = p_data->text[j+1]; -#endif - } +/* /\* first read block size information for sanity checks and encoding *\/ */ +/* for(i=0; i <= i_data-CDTEXT_LEN_PACK; i+=CDTEXT_LEN_PACK) { */ - buffer[idx] = 0x00; -#ifdef _CDTEXT_DBCC - if(p_data->bDBC) - buffer[idx+1] = 0x00; -#endif - } - } else { - /* not a character pack */ +/* if (p_data[i+0] == CDTEXT_PACK_BLOCKSIZE) { */ +/* cdtext_read_pack(&tpack, p_data+i); */ +/* switch (tpack.i_track) { */ +/* case 0: */ +/* blocksize.charcode = tpack.text[0]; */ +/* blocksize.i_first_track = tpack.text[1]; */ +/* blocksize.i_last_track = tpack.text[2]; */ +/* blocksize.copyright = tpack.text[3]; */ +/* blocksize.i_packs[0] = tpack.text[4]; */ +/* blocksize.i_packs[1] = tpack.text[5]; */ +/* blocksize.i_packs[2] = tpack.text[6]; */ +/* blocksize.i_packs[3] = tpack.text[7]; */ +/* blocksize.i_packs[4] = tpack.text[8]; */ +/* blocksize.i_packs[5] = tpack.text[9]; */ +/* blocksize.i_packs[6] = tpack.text[10]; */ +/* blocksize.i_packs[7] = tpack.text[11]; */ +/* break; */ +/* case 1: */ +/* blocksize.i_packs[8] = tpack.text[0]; */ +/* blocksize.i_packs[9] = tpack.text[1]; */ +/* blocksize.i_packs[10] = tpack.text[2]; */ +/* blocksize.i_packs[11] = tpack.text[3]; */ +/* blocksize.i_packs[12] = tpack.text[4]; */ +/* blocksize.i_packs[13] = tpack.text[5]; */ +/* blocksize.i_packs[14] = tpack.text[6]; */ +/* blocksize.i_packs[15] = tpack.text[7]; */ +/* blocksize.lastseq[0] = tpack.text[8]; */ +/* blocksize.lastseq[1] = tpack.text[9]; */ +/* blocksize.lastseq[2] = tpack.text[10]; */ +/* blocksize.lastseq[3] = tpack.text[11]; */ +/* break; */ +/* case 2: */ +/* blocksize.lastseq[4] = tpack.text[0]; */ +/* blocksize.lastseq[5] = tpack.text[1]; */ +/* blocksize.lastseq[6] = tpack.text[2]; */ +/* blocksize.lastseq[7] = tpack.text[3]; */ +/* blocksize.langcode[0] = tpack.text[4]; */ +/* blocksize.langcode[1] = tpack.text[5]; */ +/* blocksize.langcode[2] = tpack.text[6]; */ +/* blocksize.langcode[3] = tpack.text[7]; */ +/* blocksize.langcode[4] = tpack.text[8]; */ +/* blocksize.langcode[5] = tpack.text[9]; */ +/* blocksize.langcode[6] = tpack.text[10]; */ +/* blocksize.langcode[7] = tpack.text[11]; */ +/* break; */ +/* } */ +/* } */ - if(p_data->type == CDIO_CDTEXT_TOC) { - /* no idea what this is */ - } +/* if(blocksize.i_packs[15] == 3) { */ +/* /\* if there were 3 BLOCKSIZE packs *\/ */ +/* /\* set copyright *\/ */ +/* p_cdtext->block[i_block].copyright = (0x03 == (blocksize.copyright & 0x03)); */ - if (p_data->type == CDIO_CDTEXT_TOC2) { - /* no idea what this is */ - } +/* /\* set Language *\/ */ +/* if(blocksize.langcode[i_block] <= 0x7f) */ +/* p_cdtext->block[i_block].language_code = blocksize.langcode[i_block]; */ - /* 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 */ - 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; - } - } - } - } - - 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: - 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; +/* /\* determine encoding *\/ */ +/* switch (blocksize.charcode){ */ +/* case CDTEXT_CHARCODE_ISO_8859_1: */ +/* /\* default *\/ */ +/* charset = (char *) "ISO-8859-1"; */ +/* break; */ +/* case CDTEXT_CHARCODE_ASCII: */ +/* charset = (char *) "ASCII"; */ +/* break; */ +/* case CDTEXT_CHARCODE_SHIFT_JIS: */ +/* charset = (char *) "SHIFT_JIS"; */ +/* break; */ +/* } */ +/* } else { */ +/* cdio_warn("CD-TEXT: No blocksize information available for block %d.\n", i_block); */ +/* return -1; */ +/* } */ + +/* } */ + +/* cdtext_read_pack(&pack, p_data); */ + +/* #ifndef _CDTEXT_DBCC */ +/* if ( pack.db_chars ) { */ +/* cdio_warn("CD-TEXT: Double-byte characters not supported"); */ +/* return -1; */ +/* } */ +/* #endif */ + +/* /\* read text packs first *\/ */ +/* j = 0; */ +/* switch (pack.type) { */ +/* case CDTEXT_PACK_GENRE: */ +/* /\* If pack.text starts with an unprintable character, it is likely to bethe genre_code. */ +/* * While the specification requires the first GENRE pack to start with te 2 byte genre code, */ +/* * it is not specific about the following ones. *\/ */ +/* if (pack.text[0] <= 31) { */ +/* j = 2; */ +/* if (CDTEXT_GENRE_UNUSED == p_cdtext->block[i_block].genre_code) */ +/* p_cdtext->block[i_block].genre_code = CDTEXT_GET_LEN16(pack.text); */ +/* } */ +/* case CDTEXT_PACK_TITLE: */ +/* case CDTEXT_PACK_PERFORMER: */ +/* case CDTEXT_PACK_SONGWRITER: */ +/* case CDTEXT_PACK_COMPOSER: */ +/* case CDTEXT_PACK_ARRANGER: */ +/* case CDTEXT_PACK_MESSAGE: */ +/* case CDTEXT_PACK_DISCID: */ +/* case CDTEXT_PACK_UPC: */ +/* while (j < CDTEXT_LEN_TEXTDATA) { */ +/* /\* not terminated *\/ */ +/* if (pack.text[j] != 0 || (pack.db_chars && pack.text[j+1] != 0)) { */ +/* buffer[i_buf++] = pack.text[j]; */ +/* if(pack.db_chars) */ +/* buffer[i_buf++] = pack.text[j+1]; */ +/* } else if(i_buf > 1) { */ +/* buffer[i_buf++] = 0; */ +/* if(pack.db_chars) */ +/* buffer[i_buf++] = 0; */ + +/* switch (pack.type) { */ +/* case CDTEXT_PACK_TITLE: */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_TITLE, buffer, */ +/* pack.i_track, charset); */ +/* break; */ +/* case CDTEXT_PACK_PERFORMER: */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_PERFORMER, buffer, */ +/* pack.i_track, charset); */ +/* break; */ +/* case CDTEXT_PACK_SONGWRITER: */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_SONGWRITER, buffer, */ +/* pack.i_track, charset); */ +/* break; */ +/* case CDTEXT_PACK_COMPOSER: */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_COMPOSER, buffer, */ +/* pack.i_track, charset); */ +/* break; */ +/* case CDTEXT_PACK_ARRANGER: */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_ARRANGER, buffer, */ +/* pack.i_track, charset); */ +/* break; */ +/* case CDTEXT_PACK_MESSAGE: */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_MESSAGE, buffer, */ +/* pack.i_track,charset); */ +/* break; */ +/* case CDTEXT_PACK_DISCID: */ +/* if (pack.i_track == 0) */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_DISCID, buffer, */ +/* pack.i_track, NULL); */ +/* break; */ +/* case CDTEXT_PACK_GENRE: */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_GENRE, buffer, */ +/* pack.i_track, "ASCII"); */ +/* break; */ +/* case CDTEXT_PACK_UPC: */ +/* if (pack.i_track == 0) */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_UPC_EAN, buffer, */ +/* pack.i_track, "ASCII"); */ +/* else */ +/* cdtext_set(p_cdtext, CDTEXT_FIELD_ISRC, buffer, */ +/* pack.i_track, "ISO-8859-1"); */ +/* break; */ +/* } */ +/* i_buf = 0; */ + +/* } */ +/* if (pack.db_chars) */ +/* j+=2; */ +/* else */ +/* j+=1; */ +/* } */ +/* break; */ +/* } */ +/* /\* This would be the right place to parse TOC and TOC2 fields. *\/ */ + +/* i_seq++; */ +/* i_data-=CDTEXT_LEN_PACK; */ +/* p_data+=CDTEXT_LEN_PACK; */ +/* } /\* end of while loop *\/ */ + +/* p_cdtext->block_i = 0; */ + return 0; +} + + +/*! + Fills cdtext_pack_t with information read from p_data + + @param p_pack out + @param p_data in +*/ +int +cdtext_read_pack(cdtext_pack_t *p_pack, const uint8_t *p_data) { + p_pack->type = p_data[0]; + p_pack->i_track = p_data[1]; + p_pack->seq = p_data[2]; + p_pack->char_pos = p_data[3] & 0x0F; + p_pack->block = (p_data[3] >> 4) & 0x07; + p_pack->db_chars = (p_data[3] >> 7) & 0x01; + p_pack->text[0] = p_data[4]; + p_pack->text[1] = p_data[5]; + p_pack->text[2] = p_data[6]; + p_pack->text[3] = p_data[7]; + p_pack->text[4] = p_data[8]; + p_pack->text[5] = p_data[9]; + p_pack->text[6] = p_data[10]; + p_pack->text[7] = p_data[11]; + p_pack->text[8] = p_data[12]; + p_pack->text[9] = p_data[13]; + p_pack->text[10] = p_data[14]; + p_pack->text[11] = p_data[15]; + p_pack->crc[0] = p_data[16]; + p_pack->crc[2] = p_data[17]; + + return 0; } diff --git a/lib/driver/cdtext_private.h b/lib/driver/cdtext_private.h index 739373d6..518a3cf9 100644 --- a/lib/driver/cdtext_private.h +++ b/lib/driver/cdtext_private.h @@ -18,170 +18,122 @@ #ifndef __CDIO_CDTEXT_PRIVATE_H__ #define __CDIO_CDTEXT_PRIVATE_H__ -#include -#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 - ISO_*_ names and get something. - */ -extern const enum cdtext_enum1_s { - CDIO_CDTEXT_MAX_PACK_DATA = 255, - CDIO_CDTEXT_MAX_TEXT_DATA = 12, - CDIO_CDTEXT_TITLE = 0x80, - CDIO_CDTEXT_PERFORMER = 0x81, - CDIO_CDTEXT_SONGWRITER = 0x82, - CDIO_CDTEXT_COMPOSER = 0x83, - CDIO_CDTEXT_ARRANGER = 0x84, - CDIO_CDTEXT_MESSAGE = 0x85, - CDIO_CDTEXT_DISCID = 0x86, - CDIO_CDTEXT_GENRE = 0x87, - CDIO_CDTEXT_TOC = 0x88, - CDIO_CDTEXT_TOC2 = 0x89, - CDIO_CDTEXT_UPC = 0x8E, - CDIO_CDTEXT_BLOCKSIZE = 0x8F -} cdtext_enums1; +enum { + CDTEXT_LEN_BINARY_MAX = 9216, + CDTEXT_LEN_TEXTDATA = 12, + CDTEXT_LEN_PACK = 18, + CDTEXT_LEN_BLOCKSIZE = 36, + CDTEXT_NUM_BLOCKS_MAX = 8, + CDTEXT_NUM_TRACKS_MAX = 100, + CDTEXT_NUM_BLOCKPACKS_MAX = 255 +} cdtext_format_enum; -/*! - * CD-Text character codes +/** + * From table J.2 - Pack Type Indicator Definitions from + * Working Draft NCITS XXX T10/1364-D Revision 10G. November 12, 2001. */ -extern const enum cdtext_charcode_enum_s { - CDIO_CDTEXT_CHARCODE_ISO_8859_1 = 0x00, /**< ISO-8859-1 */ - CDIO_CDTEXT_CHARCODE_ASCII = 0x01, /**< ASCII - 7 bit */ - CDIO_CDTEXT_CHARCODE_KANJI = 0x80, /**< Music Shift-JIS Kanji - - double byte */ - CDIO_CDTEXT_CHARCODE_KOREAN = 0x81, /**< Korean */ - CDIO_CDTEXT_CHARCODE_CHINESE = 0x82, /**< Mandarin Chinese */ - CDIO_CDTEXT_CHARCODE_UNDEFINED = 0xFF, /**< everything else */ +enum { + CDTEXT_PACK_TITLE = 0x80, + CDTEXT_PACK_PERFORMER = 0x81, + CDTEXT_PACK_SONGWRITER = 0x82, + CDTEXT_PACK_COMPOSER = 0x83, + CDTEXT_PACK_ARRANGER = 0x84, + CDTEXT_PACK_MESSAGE = 0x85, + CDTEXT_PACK_DISCID = 0x86, + CDTEXT_PACK_GENRE = 0x87, + CDTEXT_PACK_TOC = 0x88, + CDTEXT_PACK_TOC2 = 0x89, + CDTEXT_PACK_UPC = 0x8E, + CDTEXT_PACK_BLOCKSIZE = 0x8F +} cdtext_packtype_enum; + + +/** CD-Text character encodings */ +enum cdtext_charcode_enum_s { + CDTEXT_CHARCODE_ISO_8859_1 = 0x00, /**< ISO-8859-1 (8 bit), Latin-1 */ + CDTEXT_CHARCODE_ASCII = 0x01, /**< ASCII (7 bit) */ + CDTEXT_CHARCODE_SHIFT_JIS = 0x80 /**< Shift_JIS (double byte), JIS X 0208 Appendix 1 */ +///* The following were proposed but never implemented anywhere. +// * They are mentioned for completeness here +// * CDTEXT_CHARCODE_KOREAN = 0x81, /**< Korean */ +// * CDTEXT_CHARCODE_CHINESE = 0x82, /**< Mandarin Chinese */ +// * CDTEXT_CHARCODE_UNDEFINED = 0xFF, /**< everything else */ +// */ } cdtext_charcode_enum; -/*! - * The language code is encoded as specified in ANNEX 1 to part 5 of EBU - * Tech 32 58 -E (1991). - */ -extern const enum cdtext_lang_enum_s -{ - CDIO_CDTEXT_LANG_CZECH = 0x06, - CDIO_CDTEXT_LANG_DANISH = 0x07, - CDIO_CDTEXT_LANG_GERMAN = 0x08, - CDIO_CDTEXT_LANG_ENGLISH = 0x09, - CDIO_CDTEXT_LANG_SPANISH = 0x0A, - CDIO_CDTEXT_LANG_FRENCH = 0x0F, - CDIO_CDTEXT_LANG_ITALIAN = 0x15, - CDIO_CDTEXT_LANG_HUNGARIAN = 0x1b, - CDIO_CDTEXT_LANG_DUTCH = 0x1d, - CDIO_CDTEXT_LANG_NORWEGIAN = 0x1e, - CDIO_CDTEXT_LANG_POLISH = 0x20, - CDIO_CDTEXT_LANG_PORTUGUESE = 0x21, - CDIO_CDTEXT_LANG_SLOVENE = 0x26, - CDIO_CDTEXT_LANG_FINNISH = 0x27, - CDIO_CDTEXT_LANG_SWEDISH = 0x28, - CDIO_CDTEXT_LANG_RUSSIAN = 0x56, - CDIO_CDTEXT_LANG_KOREAN = 0x65, - CDIO_CDTEXT_LANG_JAPANESE = 0x69, - CDIO_CDTEXT_LANG_GREEK = 0x70, - CDIO_CDTEXT_LANG_CHINESE = 0x75, -} cdtext_lang_enum; - - -#define CDIO_CDTEXT_MAX_PACK_DATA 255 -#define CDIO_CDTEXT_MAX_TEXT_DATA 12 - -/* From table J.2 - Pack Type Indicator Definitions from - Working Draft NCITS XXX T10/1364-D Revision 10G. November 12, 2001. -*/ -/* Title of Album name (ID=0) or Track Titles (ID != 0) */ -#define CDIO_CDTEXT_TITLE 0x80 - -/* Name(s) of the performer(s) in ASCII */ -#define CDIO_CDTEXT_PERFORMER 0x81 - -/* Name(s) of the songwriter(s) in ASCII */ -#define CDIO_CDTEXT_SONGWRITER 0x82 - -/* Name(s) of the Composers in ASCII */ -#define CDIO_CDTEXT_COMPOSER 0x83 - -/* Name(s) of the Arrangers in ASCII */ -#define CDIO_CDTEXT_ARRANGER 0x84 - -/* Message(s) from content provider and/or artist in ASCII */ -#define CDIO_CDTEXT_MESSAGE 0x85 - -/* Disc Identificatin information */ -#define CDIO_CDTEXT_DISCID 0x86 - -/* Genre Identification and Genre Information */ -#define CDIO_CDTEXT_GENRE 0x87 - -/* Table of Content Information */ -#define CDIO_CDTEXT_TOC 0x88 - -/* Second Table of Content Information */ -#define CDIO_CDTEXT_TOC2 0x89 - -/* 0x8A, 0x8B, 0x8C are reserved - 0x8D Reserved for content provider only. - */ - -/* UPC/EAN code of the album and ISRC code of each track */ -#define CDIO_CDTEXT_UPC 0x8E - -/* Size information of the Block */ -#define CDIO_CDTEXT_BLOCKSIZE 0x8F - -PRAGMA_BEGIN_PACKED - -struct CDText_data +/** Structure of CD-TEXT data Packs */ +struct cdtext_pack_s { uint8_t type; - track_t i_track; + uint8_t i_track; uint8_t seq; -#ifdef WORDS_BIGENDIAN - uint8_t bDBC: 1; /* double byte character */ - uint8_t block: 3; /* block number 0..7 */ - uint8_t characterPosition:4; /* character position */ -#else - uint8_t characterPosition:4; /* character position */ - uint8_t block :3; /* block number 0..7 */ - uint8_t bDBC :1; /* double byte character */ -#endif - char text[CDIO_CDTEXT_MAX_TEXT_DATA]; + uint8_t char_pos; /* character position */ + uint8_t block; /* block number 0..7 */ + uint8_t db_chars; /* double byte character */ + uint8_t text[CDTEXT_LEN_TEXTDATA]; uint8_t crc[2]; -} GNUC_PACKED; +}; -PRAGMA_END_PACKED -/* - * content of BLOCKSIZE packs - */ - -PRAGMA_BEGIN_PACKED - -struct CDText_blocksize +/** Structure of of block size information packs */ +struct cdtext_blocksize_s { - uint8_t charcode; /* character code */ + uint8_t charcode; /* character code */ 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 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 */ -} GNUC_PACKED; + uint8_t copyright; /* 3 CD-TEXT is copyrighted, 0 no copyright on CD-TEXT */ + 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 */ +}; -PRAGMA_END_PACKED; +typedef struct cdtext_pack_s cdtext_pack_t; +typedef struct cdtext_blocksize_s cdtext_blocksize_t; +/*! Structure for CD-TEXT of a track. */ +struct cdtext_track_s { + char *field[MAX_CDTEXT_FIELDS]; +}; -typedef struct CDText_blocksize CDText_blocksize_t; -typedef struct CDText_data CDText_data_t; +/*! Structure for CD-TEXT of a block. */ +struct cdtext_block_s { + struct cdtext_track_s track[CDTEXT_NUM_TRACKS_MAX]; /**< 0: disc; 1..99: tracks */ + cdtext_genre_t genre_code; /**< genre code of the disc */ + cdtext_lang_t language_code; /**< language of this block */ + bool copyright; /**< CD-TEXT copyright */ +}; + +/*! Structure for CD-TEXT of a disc. + + @see cdtext_init, cdtext_destroy, cdtext_get, and cdtext_set. + */ +struct cdtext_s { + struct cdtext_block_s block[CDTEXT_NUM_BLOCKS_MAX]; /**< CD-TEXT for block 0..7 */ + uint8_t block_i; /**< index of active block */ +}; + +int cdtext_read_pack (cdtext_pack_t *pack, const uint8_t *data); + +/*! + returns enum of field if key is a CD-Text keyword, + returns CDTEXT_FIELD_INVALID otherwise. +*/ +cdtext_field_t cdtext_is_field (const char *field); + +/*! + returns enum of language if lang is a valid language, + returns CDTEXT_LANGUAGE_UNKNOWN otherwise. +*/ +cdtext_lang_t cdtext_is_language (const char *lang); #endif /* __CDIO_CDTEXT_PRIVATE_H__ */ diff --git a/lib/driver/image/bincue.c b/lib/driver/image/bincue.c index b11b0c45..e17e09ec 100644 --- a/lib/driver/image/bincue.c +++ b/lib/driver/image/bincue.c @@ -27,6 +27,7 @@ #include "image.h" #include "cdio_assert.h" #include "cdio_private.h" +#include "cdtext_private.h" #include "_cdio_stdio.h" #include @@ -107,7 +108,7 @@ _init_bincue (_img_private_t *p_env) p_env->tocent[p_env->gen.i_tracks].start_lba = cdio_lsn_to_lba(lead_lsn); p_env->tocent[p_env->gen.i_tracks - p_env->gen.i_first_track].sec_count = cdio_lsn_to_lba(lead_lsn - - p_env->tocent[p_env->gen.i_tracks - p_env->gen.i_first_track].start_lba); + p_env->tocent[p_env->gen.i_tracks - p_env->gen.i_first_track].start_lba); return true; } @@ -227,11 +228,11 @@ get_disc_last_lsn_bincue (void *p_user_data) if (size % CDIO_CD_FRAMESIZE_RAW) { cdio_warn ("image %s size (%" PRId64 ") not multiple of blocksize (%d)", - p_env->gen.source_name, (int64_t)size, CDIO_CD_FRAMESIZE_RAW); + p_env->gen.source_name, (int64_t)size, CDIO_CD_FRAMESIZE_RAW); if (size % M2RAW_SECTOR_SIZE == 0) - cdio_warn ("this may be a 2336-type disc image"); + cdio_warn ("this may be a 2336-type disc image"); else if (size % CDIO_CD_FRAMESIZE_RAW == 0) - cdio_warn ("this may be a 2352-type disc image"); + cdio_warn ("this may be a 2352-type disc image"); /* exit (EXIT_FAILURE); */ } @@ -240,7 +241,7 @@ get_disc_last_lsn_bincue (void *p_user_data) return (lsn_t)size; } -#define MAXLINE 4096 /* maximum line length + 1 */ +#define MAXLINE 4096 /* maximum line length + 1 */ static bool parse_cuefile (_img_private_t *cd, const char *psz_cue_name) @@ -250,7 +251,7 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) char psz_line[MAXLINE]; /* text of current line read in file fp. */ unsigned int i_line=0; /* line number in file of psz_line. */ int i = -1; /* Position in tocent. Same as - cd->gen.i_tracks - 1 */ + cd->gen.i_tracks - 1 */ char *psz_keyword, *psz_field; cdio_log_level_t log_level = (NULL == cd) ? CDIO_LOG_INFO : CDIO_LOG_WARN; cdtext_field_t cdtext_key; @@ -265,7 +266,7 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) fp = fopen (psz_cue_name, "r"); if (fp == NULL) { cdio_log(log_level, "error opening %s for reading: %s", - psz_cue_name, strerror(errno)); + psz_cue_name, strerror(errno)); return false; } @@ -282,71 +283,73 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) if (NULL != (psz_keyword = strtok (psz_line, " \t\n\r"))) { /* REM remarks ... */ if (0 == strcmp ("REM", psz_keyword)) { - ; - - /* global section */ - /* CATALOG ddddddddddddd */ + ; + + /* global section */ + /* CATALOG ddddddddddddd */ } else if (0 == strcmp ("CATALOG", psz_keyword)) { - if (-1 == i) { - if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { - cdio_log(log_level, - "%s line %d after word CATALOG: ", - psz_cue_name, i_line); - cdio_log(log_level, - "expecting 13-digit media catalog number, got nothing."); - goto err_exit; - } - if (strlen(psz_field) != 13) { - cdio_log(log_level, - "%s line %d after word CATALOG: ", - psz_cue_name, i_line); - cdio_log(log_level, - "Token %s has length %ld. Should be 13 digits.", - psz_field, (long int) strlen(psz_field)); - goto err_exit; - } else { - /* Check that we have all digits*/ - unsigned int i; - for (i=0; i<13; i++) { - if (!isdigit(psz_field[i])) { - cdio_log(log_level, - "%s line %d after word CATALOG:", - psz_cue_name, i_line); - cdio_log(log_level, - "Character \"%c\" at postition %i of token \"%s\" " - "is not all digits.", - psz_field[i], i+1, psz_field); - goto err_exit; - } - } - } - - if (cd) cd->psz_mcn = strdup (psz_field); - if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - goto format_error; - } - } else { - goto not_in_global_section; - } + if (-1 == i) { + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + cdio_log(log_level, + "%s line %d after word CATALOG: ", + psz_cue_name, i_line); + cdio_log(log_level, + "expecting 13-digit media catalog number, got nothing."); + goto err_exit; + } + if (strlen(psz_field) != 13) { + cdio_log(log_level, + "%s line %d after word CATALOG: ", + psz_cue_name, i_line); + cdio_log(log_level, + "Token %s has length %ld. Should be 13 digits.", + psz_field, (long int) strlen(psz_field)); + goto err_exit; + } else { + /* Check that we have all digits*/ + unsigned int i; + for (i=0; i<13; i++) { + if (!isdigit(psz_field[i])) { + cdio_log(log_level, + "%s line %d after word CATALOG:", + psz_cue_name, i_line); + cdio_log(log_level, + "Character \"%c\" at postition %i of token \"%s\" " + "is not all digits.", + psz_field[i], i+1, psz_field); + goto err_exit; + } + } + } + + if (cd) cd->psz_mcn = strdup (psz_field); + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } 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]; + uint8_t cdt_data[CDTEXT_LEN_BINARY_MAX+4]; int size; CdioDataSource_t *source; - const char *dirname = cdio_dirname(psz_cue_name); - const char *psz_filename = cdio_abspath (dirname, psz_field); + const char *dirname = cdio_dirname(psz_cue_name); + const char *psz_filename = cdio_abspath (dirname, psz_field); if(NULL == (source = cdio_stdio_new(psz_filename))) { 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); + size = cdio_stream_read(source, cdt_data, CDTEXT_LEN_BINARY_MAX, 1); if (size < 5) { - cdio_log (log_level, "%s line %d: file `%s' is too small to contain CD-TEXT", psz_cue_name, i_line, psz_field); + cdio_log (log_level, + "%s line %d: file `%s' is too small to contain CD-TEXT", + psz_cue_name, i_line, (char *) psz_filename); goto err_exit; } @@ -355,438 +358,441 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) size -= 4; } + /* ignore trailing 0 */ + if (1 == size % 18) + size -= 1; + /* init cdtext */ if (NULL == cd->gen.cdtext) { - cd->gen.cdtext = malloc(sizeof(cdtext_t)); - cdtext_init (cd->gen.cdtext); + cd->gen.cdtext = cdtext_init (); } - if(!cdtext_data_init(cd->gen.cdtext, cdt_data, size)) - cdio_log (log_level, "%s line %d: failed to parse CD-TEXT file `%s'", psz_cue_name, i_line, psz_field); + if(0 != cdtext_data_init(cd->gen.cdtext, cdt_data, size)) + cdio_log (log_level, "%s line %d: failed to parse CD-TEXT file `%s'", psz_cue_name, i_line, (char *) psz_filename); cdio_stdio_destroy (source); } } else { goto format_error; } - - /* FILE "" */ + + /* FILE "" */ } else if (0 == strcmp ("FILE", psz_keyword)) { - if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) { - const char *dirname = cdio_dirname(psz_cue_name); - const char *filename = cdio_abspath (dirname, psz_field); - if (cd) cd->tocent[i + 1].filename = (char *) filename; - } else { - goto format_error; - } - - /* TRACK N */ + if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) { + const char *dirname = cdio_dirname(psz_cue_name); + const char *filename = cdio_abspath (dirname, psz_field); + if (cd) cd->tocent[i + 1].filename = (char *) filename; + } else { + goto format_error; + } + + /* TRACK N */ } else if (0 == strcmp ("TRACK", psz_keyword)) { - int i_track; + int i_track; - if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - if (1!=sscanf(psz_field, "%d", &i_track)) { - cdio_log(log_level, - "%s line %d after word TRACK:", - psz_cue_name, i_line); - cdio_log(log_level, - "Expecting a track number, got %s", psz_field); - goto err_exit; - } - } - if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - track_info_t *this_track=NULL; + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (1!=sscanf(psz_field, "%d", &i_track)) { + cdio_log(log_level, + "%s line %d after word TRACK:", + psz_cue_name, i_line); + cdio_log(log_level, + "Expecting a track number, got %s", psz_field); + goto err_exit; + } + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + track_info_t *this_track=NULL; - if (cd) { - this_track = &(cd->tocent[cd->gen.i_tracks]); - this_track->track_num = cd->gen.i_tracks; - this_track->num_indices = 0; - b_first_index_for_track = false; - cd->gen.i_tracks++; - } - i++; - - if (0 == strcmp ("AUDIO", psz_field)) { - if (cd) { - this_track->mode = AUDIO; - this_track->blocksize = CDIO_CD_FRAMESIZE_RAW; - this_track->datasize = CDIO_CD_FRAMESIZE_RAW; - this_track->datastart = 0; - this_track->endsize = 0; - this_track->track_format = TRACK_FORMAT_AUDIO; - this_track->track_green = false; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_DA; - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DATA: - case CDIO_DISC_MODE_CD_XA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else if (0 == strcmp ("MODE1/2048", psz_field)) { - if (cd) { - this_track->mode = MODE1; - this_track->blocksize = 2048; - this_track->track_format= TRACK_FORMAT_DATA; - this_track->track_green = false; - /* Is the below correct? */ - this_track->datastart = 0; - this_track->datasize = CDIO_CD_FRAMESIZE; - this_track->endsize = 0; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_DATA; - break; - case CDIO_DISC_MODE_CD_DATA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_XA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else if (0 == strcmp ("MODE1/2352", psz_field)) { - if (cd) { - this_track->blocksize = 2352; - this_track->track_format= TRACK_FORMAT_DATA; - this_track->track_green = false; - this_track->datastart = CDIO_CD_SYNC_SIZE - + CDIO_CD_HEADER_SIZE; - this_track->datasize = CDIO_CD_FRAMESIZE; - this_track->endsize = CDIO_CD_EDC_SIZE - + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE; - this_track->mode = MODE1_RAW; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_DATA; - break; - case CDIO_DISC_MODE_CD_DATA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_XA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else if (0 == strcmp ("MODE2/2336", psz_field)) { - if (cd) { - this_track->blocksize = 2336; - this_track->track_format= TRACK_FORMAT_XA; - this_track->track_green = true; - this_track->mode = MODE2; - this_track->datastart = CDIO_CD_SYNC_SIZE - + CDIO_CD_HEADER_SIZE; - this_track->datasize = M2RAW_SECTOR_SIZE; - this_track->endsize = 0; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_DATA; - break; - case CDIO_DISC_MODE_CD_DATA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_XA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else if (0 == strcmp ("MODE2/2048", psz_field)) { - if (cd) { - this_track->blocksize = 2048; - this_track->track_format= TRACK_FORMAT_XA; - this_track->track_green = true; - this_track->mode = MODE2_FORM1; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_XA; - break; - case CDIO_DISC_MODE_CD_XA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_DATA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else if (0 == strcmp ("MODE2/2324", psz_field)) { - if (cd) { - this_track->blocksize = 2324; - this_track->track_format= TRACK_FORMAT_XA; - this_track->track_green = true; - this_track->mode = MODE2_FORM2; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_XA; - break; - case CDIO_DISC_MODE_CD_XA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_DATA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else if (0 == strcmp ("MODE2/2336", psz_field)) { - if (cd) { - this_track->blocksize = 2336; - this_track->track_format= TRACK_FORMAT_XA; - this_track->track_green = true; - this_track->mode = MODE2_FORM_MIX; - this_track->datastart = CDIO_CD_SYNC_SIZE - + CDIO_CD_HEADER_SIZE; - this_track->datasize = M2RAW_SECTOR_SIZE; - this_track->endsize = 0; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_XA; - break; - case CDIO_DISC_MODE_CD_XA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_DATA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else if (0 == strcmp ("MODE2/2352", psz_field)) { - if (cd) { - this_track->blocksize = 2352; - this_track->track_format= TRACK_FORMAT_XA; - this_track->track_green = true; - this_track->mode = MODE2_RAW; - this_track->datastart = CDIO_CD_SYNC_SIZE - + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; - this_track->datasize = CDIO_CD_FRAMESIZE; - this_track->endsize = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE; - switch(cd->disc_mode) { - case CDIO_DISC_MODE_NO_INFO: - cd->disc_mode = CDIO_DISC_MODE_CD_XA; - break; - case CDIO_DISC_MODE_CD_XA: - case CDIO_DISC_MODE_CD_MIXED: - case CDIO_DISC_MODE_ERROR: - /* Disc type stays the same. */ - break; - case CDIO_DISC_MODE_CD_DA: - case CDIO_DISC_MODE_CD_DATA: - cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; - break; - default: - cd->disc_mode = CDIO_DISC_MODE_ERROR; - } - } - } else { - cdio_log(log_level, - "%s line %d after word TRACK:", - psz_cue_name, i_line); - cdio_log(log_level, - "Unknown track mode %s", psz_field); - goto err_exit; - } - } else { - goto format_error; - } - - /* FLAGS flag1 flag2 ... */ + if (cd) { + this_track = &(cd->tocent[cd->gen.i_tracks]); + this_track->track_num = cd->gen.i_tracks; + this_track->num_indices = 0; + b_first_index_for_track = false; + cd->gen.i_tracks++; + } + i++; + + if (0 == strcmp ("AUDIO", psz_field)) { + if (cd) { + this_track->mode = AUDIO; + this_track->blocksize = CDIO_CD_FRAMESIZE_RAW; + this_track->datasize = CDIO_CD_FRAMESIZE_RAW; + this_track->datastart = 0; + this_track->endsize = 0; + this_track->track_format = TRACK_FORMAT_AUDIO; + this_track->track_green = false; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DA; + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE1/2048", psz_field)) { + if (cd) { + this_track->mode = MODE1; + this_track->blocksize = 2048; + this_track->track_format= TRACK_FORMAT_DATA; + this_track->track_green = false; + /* Is the below correct? */ + this_track->datastart = 0; + this_track->datasize = CDIO_CD_FRAMESIZE; + this_track->endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE1/2352", psz_field)) { + if (cd) { + this_track->blocksize = 2352; + this_track->track_format= TRACK_FORMAT_DATA; + this_track->track_green = false; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + this_track->datasize = CDIO_CD_FRAMESIZE; + this_track->endsize = CDIO_CD_EDC_SIZE + + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE; + this_track->mode = MODE1_RAW; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2336", psz_field)) { + if (cd) { + this_track->blocksize = 2336; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + this_track->datasize = M2RAW_SECTOR_SIZE; + this_track->endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2048", psz_field)) { + if (cd) { + this_track->blocksize = 2048; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_FORM1; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2324", psz_field)) { + if (cd) { + this_track->blocksize = 2324; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_FORM2; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2336", psz_field)) { + if (cd) { + this_track->blocksize = 2336; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_FORM_MIX; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + this_track->datasize = M2RAW_SECTOR_SIZE; + this_track->endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2352", psz_field)) { + if (cd) { + this_track->blocksize = 2352; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_RAW; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; + this_track->datasize = CDIO_CD_FRAMESIZE; + this_track->endsize = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else { + cdio_log(log_level, + "%s line %d after word TRACK:", + psz_cue_name, i_line); + cdio_log(log_level, + "Unknown track mode %s", psz_field); + goto err_exit; + } + } else { + goto format_error; + } + + /* FLAGS flag1 flag2 ... */ } else if (0 == strcmp ("FLAGS", psz_keyword)) { - if (0 <= i) { - while (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - if (0 == strcmp ("PRE", psz_field)) { - if (cd) cd->tocent[i].flags |= PRE_EMPHASIS; - } else if (0 == strcmp ("DCP", psz_field)) { - if (cd) cd->tocent[i].flags |= COPY_PERMITTED; - } else if (0 == strcmp ("4CH", psz_field)) { - if (cd) cd->tocent[i].flags |= FOUR_CHANNEL_AUDIO; - } else if (0 == strcmp ("SCMS", psz_field)) { - if (cd) cd->tocent[i].flags |= SCMS; - } else { - goto format_error; - } - } - } else { - goto format_error; - } - - /* ISRC CCOOOYYSSSSS */ + if (0 <= i) { + while (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (0 == strcmp ("PRE", psz_field)) { + if (cd) cd->tocent[i].flags |= PRE_EMPHASIS; + } else if (0 == strcmp ("DCP", psz_field)) { + if (cd) cd->tocent[i].flags |= COPY_PERMITTED; + } else if (0 == strcmp ("4CH", psz_field)) { + if (cd) cd->tocent[i].flags |= FOUR_CHANNEL_AUDIO; + } else if (0 == strcmp ("SCMS", psz_field)) { + if (cd) cd->tocent[i].flags |= SCMS; + } else { + goto format_error; + } + } + } else { + goto format_error; + } + + /* ISRC CCOOOYYSSSSS */ } else if (0 == strcmp ("ISRC", psz_keyword)) { - if (0 <= i) { - if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - if (cd) cd->tocent[i].isrc = strdup (psz_field); - } else { - goto format_error; - } - } else { - goto in_global_section; - } - - /* PREGAP MM:SS:FF */ + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (cd) cd->tocent[i].isrc = strdup (psz_field); + } else { + goto format_error; + } + } else { + goto in_global_section; + } + + /* PREGAP MM:SS:FF */ } else if (0 == strcmp ("PREGAP", psz_keyword)) { - if (0 <= i) { - if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - lba_t lba = cdio_lsn_to_lba(cdio_mmssff_to_lba (psz_field)); - if (CDIO_INVALID_LBA == lba) { - cdio_log(log_level, "%s line %d: after word PREGAP:", - psz_cue_name, i_line); - cdio_log(log_level, "Invalid MSF string %s", - psz_field); - goto err_exit; - } - if (cd) { - cd->tocent[i].silence = lba; - } - } else { - goto format_error; - } if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - goto format_error; - } - } else { - goto in_global_section; - } - - /* INDEX [##] MM:SS:FF */ + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + lba_t lba = cdio_lsn_to_lba(cdio_mmssff_to_lba (psz_field)); + if (CDIO_INVALID_LBA == lba) { + cdio_log(log_level, "%s line %d: after word PREGAP:", + psz_cue_name, i_line); + cdio_log(log_level, "Invalid MSF string %s", + psz_field); + goto err_exit; + } + if (cd) { + cd->tocent[i].silence = lba; + } + } else { + goto format_error; + } if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } else { + goto in_global_section; + } + + /* INDEX [##] MM:SS:FF */ } else if (0 == strcmp ("INDEX", psz_keyword)) { - if (0 <= i) { - if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) - if (1!=sscanf(psz_field, "%d", &start_index)) { - cdio_log(log_level, - "%s line %d after word INDEX:", - psz_cue_name, i_line); - cdio_log(log_level, - "expecting an index number, got %s", - psz_field); - goto err_exit; - } - if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { - lba_t lba = cdio_mmssff_to_lba (psz_field); - if (CDIO_INVALID_LBA == lba) { - cdio_log(log_level, "%s line %d: after word INDEX:", - psz_cue_name, i_line); - cdio_log(log_level, "Invalid MSF string %s", - psz_field); - goto err_exit; - } - if (cd) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) + if (1!=sscanf(psz_field, "%d", &start_index)) { + cdio_log(log_level, + "%s line %d after word INDEX:", + psz_cue_name, i_line); + cdio_log(log_level, + "expecting an index number, got %s", + psz_field); + goto err_exit; + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + lba_t lba = cdio_mmssff_to_lba (psz_field); + if (CDIO_INVALID_LBA == lba) { + cdio_log(log_level, "%s line %d: after word INDEX:", + psz_cue_name, i_line); + cdio_log(log_level, "Invalid MSF string %s", + psz_field); + goto err_exit; + } + if (cd) { #if FIXED_ME - cd->tocent[i].indexes[cd->tocent[i].nindex++] = lba; + cd->tocent[i].indexes[cd->tocent[i].nindex++] = lba; #else - track_info_t *this_track= - &(cd->tocent[cd->gen.i_tracks - cd->gen.i_first_track]); + track_info_t *this_track= + &(cd->tocent[cd->gen.i_tracks - cd->gen.i_first_track]); - switch (start_index) { + switch (start_index) { - case 0: - lba += CDIO_PREGAP_SECTORS; - this_track->pregap = lba; - break; + case 0: + lba += CDIO_PREGAP_SECTORS; + this_track->pregap = lba; + break; - case 1: - if (!b_first_index_for_track) { - lba += CDIO_PREGAP_SECTORS; - cdio_lba_to_msf(lba, &(this_track->start_msf)); - b_first_index_for_track = true; - this_track->start_lba = lba; - } - - if (cd->gen.i_tracks > 1) { - /* Figure out number of sectors for previous track */ - track_info_t *prev_track=&(cd->tocent[cd->gen.i_tracks-2]); - if ( this_track->start_lba < prev_track->start_lba ) { - cdio_log (log_level, - "track %d at LBA %lu starts before track %d at LBA %lu", - cd->gen.i_tracks, - (unsigned long int) this_track->start_lba, - cd->gen.i_tracks, - (unsigned long int) prev_track->start_lba); - prev_track->sec_count = 0; - } else if ( this_track->start_lba >= prev_track->start_lba - + CDIO_PREGAP_SECTORS ) { - prev_track->sec_count = this_track->start_lba - - prev_track->start_lba - CDIO_PREGAP_SECTORS ; - } else { - cdio_log (log_level, - "%lu fewer than pregap (%d) sectors in track %d", - (long unsigned int) - this_track->start_lba - prev_track->start_lba, - CDIO_PREGAP_SECTORS, - cd->gen.i_tracks); - /* Include pregap portion in sec_count. Maybe the pregap - was omitted. */ - prev_track->sec_count = this_track->start_lba - - prev_track->start_lba; - } - } - this_track->num_indices++; - break; + case 1: + if (!b_first_index_for_track) { + lba += CDIO_PREGAP_SECTORS; + cdio_lba_to_msf(lba, &(this_track->start_msf)); + b_first_index_for_track = true; + this_track->start_lba = lba; + } + + if (cd->gen.i_tracks > 1) { + /* Figure out number of sectors for previous track */ + track_info_t *prev_track=&(cd->tocent[cd->gen.i_tracks-2]); + if ( this_track->start_lba < prev_track->start_lba ) { + cdio_log (log_level, + "track %d at LBA %lu starts before track %d at LBA %lu", + cd->gen.i_tracks, + (unsigned long int) this_track->start_lba, + cd->gen.i_tracks, + (unsigned long int) prev_track->start_lba); + prev_track->sec_count = 0; + } else if ( this_track->start_lba >= prev_track->start_lba + + CDIO_PREGAP_SECTORS ) { + prev_track->sec_count = this_track->start_lba - + prev_track->start_lba - CDIO_PREGAP_SECTORS ; + } else { + cdio_log (log_level, + "%lu fewer than pregap (%d) sectors in track %d", + (long unsigned int) + this_track->start_lba - prev_track->start_lba, + CDIO_PREGAP_SECTORS, + cd->gen.i_tracks); + /* Include pregap portion in sec_count. Maybe the pregap + was omitted. */ + prev_track->sec_count = this_track->start_lba - + prev_track->start_lba; + } + } + this_track->num_indices++; + break; - default: - break; - } - } + default: + break; + } + } #endif - } else { - goto format_error; - } - } else { - goto in_global_section; - } - - /* CD-Text */ - } else if ( CDTEXT_INVALID != - (cdtext_key = cdtext_is_keyword (psz_keyword)) ) { + } else { + goto format_error; + } + } else { + goto in_global_section; + } + + /* CD-Text */ + } else if ( CDTEXT_FIELD_INVALID != + (cdtext_key = cdtext_is_field (psz_keyword)) ) { if (cd) { if (NULL == cd->gen.cdtext) { - cd->gen.cdtext = malloc(sizeof(cdtext_t)); - cdtext_init (cd->gen.cdtext); + cd->gen.cdtext = cdtext_init (); + cd->gen.cdtext->block[cd->gen.cdtext->block_i].language_code = CDTEXT_LANGUAGE_ENGLISH; } - cdtext_set (cdtext_key, + cdtext_set (cd->gen.cdtext, cdtext_key, (uint8_t*) strtok (NULL, "\"\t\n\r"), (-1 == i ? 0 : cd->gen.i_first_track + i + 1), - strtok (NULL, "\"\t\n\r"), cd->gen.cdtext); + "ISO-8859-1"); } - - /* unrecognized line */ + + /* unrecognized line */ } else { - cdio_log(log_level, "%s line %d: warning: unrecognized keyword: %s", - psz_cue_name, i_line, psz_keyword); - goto err_exit; + cdio_log(log_level, "%s line %d: warning: unrecognized keyword: %s", + psz_cue_name, i_line, psz_keyword); + goto err_exit; } } } @@ -800,17 +806,17 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) format_error: cdio_log(log_level, "%s line %d after word %s", - psz_cue_name, i_line, psz_keyword); + psz_cue_name, i_line, psz_keyword); goto err_exit; in_global_section: cdio_log(log_level, "%s line %d: word %s not allowed in global section", - psz_cue_name, i_line, psz_keyword); + psz_cue_name, i_line, psz_keyword); goto err_exit; not_in_global_section: cdio_log(log_level, "%s line %d: word %s only allowed in global section", - psz_cue_name, i_line, psz_keyword); + psz_cue_name, i_line, psz_keyword); err_exit: fclose (fp); @@ -824,7 +830,7 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) */ static driver_return_code_t _read_audio_sectors_bincue (void *p_user_data, void *data, lsn_t lsn, - unsigned int nblocks) + unsigned int nblocks) { _img_private_t *p_env = p_user_data; int ret; @@ -846,7 +852,7 @@ _read_audio_sectors_bincue (void *p_user_data, void *data, lsn_t lsn, */ static driver_return_code_t _read_mode1_sector_bincue (void *p_user_data, void *data, lsn_t lsn, - bool b_form2) + bool b_form2) { _img_private_t *p_env = p_user_data; int ret; @@ -861,7 +867,7 @@ _read_mode1_sector_bincue (void *p_user_data, void *data, lsn_t lsn, if (ret==0) return ret; memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, - b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); + b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); return DRIVER_OP_SUCCESS; } @@ -873,7 +879,7 @@ _read_mode1_sector_bincue (void *p_user_data, void *data, lsn_t lsn, */ static driver_return_code_t _read_mode1_sectors_bincue (void *p_user_data, void *data, lsn_t lsn, - bool b_form2, unsigned int nblocks) + bool b_form2, unsigned int nblocks) { _img_private_t *p_env = p_user_data; int i; @@ -882,8 +888,8 @@ _read_mode1_sectors_bincue (void *p_user_data, void *data, lsn_t lsn, for (i = 0; i < nblocks; i++) { if ( (retval = _read_mode1_sector_bincue (p_env, - ((char *)data) + (blocksize * i), - lsn + i, b_form2)) ) + ((char *)data) + (blocksize * i), + lsn + i, b_form2)) ) return retval; } return DRIVER_OP_SUCCESS; @@ -895,7 +901,7 @@ _read_mode1_sectors_bincue (void *p_user_data, void *data, lsn_t lsn, */ static driver_return_code_t _read_mode2_sector_bincue (void *p_user_data, void *data, lsn_t lsn, - bool b_form2) + bool b_form2) { _img_private_t *p_env = p_user_data; int ret; @@ -919,7 +925,7 @@ _read_mode2_sector_bincue (void *p_user_data, void *data, lsn_t lsn, /* See NOTE above. */ if (b_form2) memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, - M2RAW_SECTOR_SIZE); + M2RAW_SECTOR_SIZE); else memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, CDIO_CD_FRAMESIZE); @@ -933,7 +939,7 @@ _read_mode2_sector_bincue (void *p_user_data, void *data, lsn_t lsn, */ static driver_return_code_t _read_mode2_sectors_bincue (void *p_user_data, void *data, lsn_t lsn, - bool b_form2, unsigned int nblocks) + bool b_form2, unsigned int nblocks) { _img_private_t *p_env = p_user_data; int i; @@ -942,8 +948,8 @@ _read_mode2_sectors_bincue (void *p_user_data, void *data, lsn_t lsn, for (i = 0; i < nblocks; i++) { if ( (retval = _read_mode2_sector_bincue (p_env, - ((char *)data) + (blocksize * i), - lsn + i, b_form2)) ) + ((char *)data) + (blocksize * i), + lsn + i, b_form2)) ) return retval; } return 0; @@ -989,13 +995,13 @@ static bool get_hwinfo_bincue ( const CdIo_t *p_cdio, /*out*/ cdio_hwinfo_t *hw_info) { strncpy(hw_info->psz_vendor, "libcdio", - sizeof(hw_info->psz_vendor)-1); + sizeof(hw_info->psz_vendor)-1); hw_info->psz_vendor[sizeof(hw_info->psz_vendor)-1] = '\0'; strncpy(hw_info->psz_model, "CDRWIN", - sizeof(hw_info->psz_model)-1); + sizeof(hw_info->psz_model)-1); hw_info->psz_model[sizeof(hw_info->psz_model)-1] = '\0'; strncpy(hw_info->psz_revision, CDIO_VERSION, - sizeof(hw_info->psz_revision)-1); + sizeof(hw_info->psz_revision)-1); hw_info->psz_revision[sizeof(hw_info->psz_revision)-1] = '\0'; return true; @@ -1033,7 +1039,7 @@ _get_track_green_bincue(void *p_user_data, track_t i_track) if ( NULL == p_env || ( i_track < p_env->gen.i_first_track - || i_track >= p_env->gen.i_tracks + p_env->gen.i_first_track ) ) + || i_track >= p_env->gen.i_tracks + p_env->gen.i_first_track ) ) return false; return p_env->tocent[i_track-p_env->gen.i_first_track].track_green; @@ -1084,16 +1090,16 @@ cdio_is_cuefile(const char *psz_cue_name) if (psz_cue_name[i]=='c' && psz_cue_name[i+1]=='u' && psz_cue_name[i+2]=='e') { psz_bin_name[i++]='b'; psz_bin_name[i++]='i'; psz_bin_name[i++]='n'; if (parse_cuefile(NULL, psz_cue_name)) - return psz_bin_name; + return psz_bin_name; else - goto error; + goto error; } else if (psz_cue_name[i]=='C' && psz_cue_name[i+1]=='U' && psz_cue_name[i+2]=='E') { psz_bin_name[i++]='B'; psz_bin_name[i++]='I'; psz_bin_name[i++]='N'; if (parse_cuefile(NULL, psz_cue_name)) - return psz_bin_name; + return psz_bin_name; else - goto error; + goto error; } } error: @@ -1140,7 +1146,7 @@ cdio_open_am_bincue (const char *psz_source_name, const char *psz_access_mode) { if (psz_access_mode != NULL) cdio_warn ("there is only one access mode for bincue. Arg %s ignored", - psz_access_mode); + psz_access_mode); return cdio_open_bincue(psz_source_name); } @@ -1231,7 +1237,7 @@ cdio_open_cue (const char *psz_cue_name) if (NULL == psz_bin_name) { cdio_error ("source name %s is not recognized as a CUE file", - psz_cue_name); + psz_cue_name); } _set_arg_image (p_data, "cue", psz_cue_name); diff --git a/lib/driver/image/cdrdao.c b/lib/driver/image/cdrdao.c index b075392f..788d1758 100644 --- a/lib/driver/image/cdrdao.c +++ b/lib/driver/image/cdrdao.c @@ -70,6 +70,7 @@ #define DEFAULT_CDIO_CDRDAO "videocd.toc" #include "image_common.h" +#include "cdtext_private.h" static lsn_t get_disc_last_lsn_cdrdao (void *p_user_data); static bool parse_tocfile (_img_private_t *cd, const char *p_toc_name); @@ -907,48 +908,49 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name) goto not_in_global_section; } - /* CD_TEXT { ... } */ - /* todo: opening { must be on same line as CD_TEXT */ + /* CD_TEXT { ... } */ + /* todo: opening { must be on same line as CD_TEXT */ } else if (0 == strcmp ("CD_TEXT", psz_keyword)) { - if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { - goto format_error; - } - if ( 0 == strcmp( "{", psz_field ) ) { - i_cdtext_nest++; - } else { - cdio_log (log_level, - "%s line %d: expecting '{'", psz_cue_name, i_line); - goto err_exit; - } - + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + if ( 0 == strcmp( "{", psz_field ) ) { + i_cdtext_nest++; + } else { + cdio_log (log_level, + "%s line %d: expecting '{'", psz_cue_name, i_line); + goto err_exit; + } + + // TODO: implement language mapping } else if (0 == strcmp ("LANGUAGE_MAP", psz_keyword)) { - /* LANGUAGE d { ... } */ + /* LANGUAGE d { ... } */ } else if (0 == strcmp ("LANGUAGE", psz_keyword)) { - if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { - goto format_error; - } - /* Language number */ - if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { - goto format_error; - } - if ( 0 == strcmp( "{", psz_field ) ) { - i_cdtext_nest++; - } + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + /* Language number */ + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + if ( 0 == strcmp( "{", psz_field ) ) { + i_cdtext_nest++; + } } else if (0 == strcmp ("{", psz_keyword)) { - i_cdtext_nest++; + i_cdtext_nest++; } else if (0 == strcmp ("}", psz_keyword)) { - if (i_cdtext_nest > 0) i_cdtext_nest--; - } else if ( CDTEXT_INVALID != - (cdtext_key = cdtext_is_keyword (psz_keyword)) ) { + if (i_cdtext_nest > 0) i_cdtext_nest--; + } else if ( CDTEXT_FIELD_INVALID != + (cdtext_key = cdtext_is_field (psz_keyword)) ) { if (NULL != cd) { if (NULL == cd->gen.cdtext) { - cd->gen.cdtext = malloc(sizeof(cdtext_t)); - cdtext_init (cd->gen.cdtext); + cd->gen.cdtext = cdtext_init (); + /* until language mapping is implemented ...*/ + cd->gen.cdtext->block[cd->gen.cdtext->block_i].language_code = CDTEXT_LANGUAGE_ENGLISH; } - cdtext_set (cdtext_key, - (-1 == i ? 0 : cd->gen.i_first_track + i + 1), - strtok (NULL, "\"\t\n\r"), - cd->gen.cdtext); + cdtext_set (cd->gen.cdtext, cdtext_key, (uint8_t*) strtok (NULL, "\"\t\n\r"), + (-1 == i ? 0 : cd->gen.i_first_track + i + 1), + "ISO-8859-1"); } /* unrecognized line */ diff --git a/lib/driver/image/nrg.c b/lib/driver/image/nrg.c index 9ba83d48..68777d3e 100644 --- a/lib/driver/image/nrg.c +++ b/lib/driver/image/nrg.c @@ -747,10 +747,9 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name, case CDTX_ID: { /* "CD TEXT" */ uint8_t *wdata = (uint8_t *) chunk->data; int len = UINT32_FROM_BE (chunk->len); - cdio_assert (len % sizeof (CDText_data_t) == 0); - p_env->gen.cdtext = malloc(sizeof(cdtext_t)); - cdtext_init (p_env->gen.cdtext); - if(!cdtext_data_init (p_env->gen.cdtext, wdata, len)) + cdio_assert (len % CDTEXT_LEN_PACK == 0); + p_env->gen.cdtext = cdtext_init (); + if(0 !=cdtext_data_init (p_env->gen.cdtext, wdata, len)) { cdtext_destroy(p_env->gen.cdtext); free(p_env->gen.cdtext); diff --git a/lib/driver/libcdio.sym b/lib/driver/libcdio.sym index 2aee1d09..79dcff28 100644 --- a/lib/driver/libcdio.sym +++ b/lib/driver/libcdio.sym @@ -183,11 +183,14 @@ cdio_warn cdtext_destroy cdtext_field2str cdtext_genre2str +cdtext_lang2str cdtext_get cdtext_get_const +cdtext_get_language cdtext_init -cdtext_is_keyword +cdtext_languages_available cdtext_set +cdtext_select_language debug_cdio_mmc_feature debug_cdio_mmc_feature_interface debug_cdio_mmc_feature_profile diff --git a/lib/driver/mmc/mmc.c b/lib/driver/mmc/mmc.c index d9329df8..2022992e 100644 --- a/lib/driver/mmc/mmc.c +++ b/lib/driver/mmc/mmc.c @@ -27,6 +27,7 @@ #include #include #include "cdio_private.h" +#include "cdtext_private.h" #ifdef HAVE_STRING_H #include @@ -350,7 +351,7 @@ mmc_read_cdtext_private ( void *p_user_data, errno = 0; - wdata = calloc(MAX_CDTEXT_DATA_LENGTH, sizeof(unsigned char)); + wdata = calloc(CDTEXT_LEN_BINARY_MAX, sizeof(unsigned char)); /* We may need to give CD-Text a little more time to complete. */ /* First off, just try and read the size */ @@ -368,8 +369,8 @@ mmc_read_cdtext_private ( void *p_user_data, /* Now read the CD-Text data */ int i_cdtext = CDIO_MMC_GET_LEN16(wdata); - if (i_cdtext+2 > MAX_CDTEXT_DATA_LENGTH) - i_cdtext = MAX_CDTEXT_DATA_LENGTH-2; + if (i_cdtext+2 > CDTEXT_LEN_BINARY_MAX) + i_cdtext = CDTEXT_LEN_BINARY_MAX-2; else wdata = realloc(wdata,i_cdtext+2); /* the 2 bytes holding the size are not included in i_cdtext */ diff --git a/lib/driver/utf8.c b/lib/driver/utf8.c index 5ae9adc3..892f84c3 100644 --- a/lib/driver/utf8.c +++ b/lib/driver/utf8.c @@ -97,7 +97,7 @@ void cdio_charset_converter_destroy(cdio_charset_coverter_t*cnv) #define BYTES_INCREMENT 16 static bool -do_convert(iconv_t cd, char * src, int src_len, +do_convert(iconv_t cd, const char * src, int src_len, char ** dst, int *dst_len) { char * ret; @@ -124,7 +124,7 @@ do_convert(iconv_t cd, char * src, int src_len, ret = malloc(alloc_size); - inbuf = src; + inbuf = (char *)src; outbuf = ret; while(1) @@ -199,7 +199,7 @@ bool cdio_charset_from_utf8(cdio_utf8_t * src, char ** dst, -bool cdio_charset_to_utf8(char *src, size_t src_len, cdio_utf8_t **dst, +bool cdio_charset_to_utf8(const char *src, size_t src_len, cdio_utf8_t **dst, const char * src_charset) { iconv_t ic; diff --git a/src/cd-info.c b/src/cd-info.c index cbe57068..6a3d52f7 100644 --- a/src/cd-info.c +++ b/src/cd-info.c @@ -423,8 +423,8 @@ print_cdtext_track_info(cdtext_t *p_cdtext, track_t i_track, const char *psz_msg printf("%s\n", psz_msg); for (i=0; i < MAX_CDTEXT_FIELDS; 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)); + if (cdtext_get_const(p_cdtext, i, i_track)) { + printf("\t%s: %s\n", cdtext_field2str(i), cdtext_get_const(p_cdtext, i, i_track)); } } } @@ -434,18 +434,28 @@ 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); + cdtext_lang_t *languages; + int i, j; if(NULL == p_cdtext) { printf("No CD-TEXT on Disc.\n"); return; } - 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_cdtext, i_first_track, msg); - } + languages = cdtext_languages_available(p_cdtext); + for(i=0; i<8; i++) + if ( CDTEXT_LANGUAGE_UNKNOWN != languages[i] + && cdtext_select_language(p_cdtext, cdtext_lang2str(languages[i]))) + { + printf("\nLanguage %d '%s':\n", i, cdtext_lang2str(languages[i])); + + print_cdtext_track_info(p_cdtext, 0, "CD-TEXT for Disc:"); + for ( j = i_first_track ; j < i_last_track; j++ ) { + char msg[50]; + sprintf(msg, "CD-TEXT for Track %2d:", j); + print_cdtext_track_info(p_cdtext, j, msg); + } + } } #ifdef HAVE_CDDB diff --git a/src/cdda-player.c b/src/cdda-player.c index de9c680d..c7d92fd5 100644 --- a/src/cdda-player.c +++ b/src/cdda-player.c @@ -542,9 +542,9 @@ get_cddb_disc_info(CdIo_t *p_cdio) } #define add_cdtext_disc_info(format_str, info_field, FIELD) \ - if (cdtext_get_const(FIELD, 0, p_cdtext) && !strlen(info_field)) { \ + if (cdtext_get_const(p_cdtext, FIELD, 0) && !strlen(info_field)) { \ snprintf(info_field, sizeof(info_field), format_str, \ - cdtext_get_const(FIELD, 0, p_cdtext)); \ + cdtext_get_const(p_cdtext, FIELD, 0)); \ b_cdtext_ ## info_field = true; \ } @@ -554,9 +554,9 @@ get_cdtext_disc_info(CdIo_t *p_cdio) 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); + add_cdtext_disc_info("%s", title, CDTEXT_FIELD_TITLE); + add_cdtext_disc_info("%s", artist, CDTEXT_FIELD_PERFORMER); + add_cdtext_disc_info("%s", genre, CDTEXT_FIELD_GENRE); } } @@ -838,10 +838,10 @@ get_cddb_track_info(track_t i_track) } #define add_cdtext_track_info(format_str, info_field, FIELD) \ - if (cdtext_get_const(FIELD, i_track, p_cdtext)) { \ + if (cdtext_get_const(p_cdtext, FIELD, i_track)) { \ snprintf(cd_info[i_track].info_field, \ sizeof(cd_info[i_track].info_field), \ - format_str, cdtext_get_const(FIELD, i_track, p_cdtext)); \ + format_str, cdtext_get_const(p_cdtext, FIELD, i_track)); \ cd_info[i_track].b_cdtext = true; \ } @@ -853,8 +853,8 @@ get_cdtext_track_info(track_t 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); + add_cdtext_track_info("%s", title, CDTEXT_FIELD_TITLE); + add_cdtext_track_info("%s", artist, CDTEXT_FIELD_PERFORMER); } } diff --git a/test/cdda.right b/test/cdda.right index 63645164..31505f9f 100644 --- a/test/cdda.right +++ b/test/cdda.right @@ -11,7 +11,8 @@ audio status: not implemented __________________________________ CD Analysis Report +Language 0 'English': CD-TEXT for Disc: - PERFORMER: Richard Stallman TITLE: Join us now we have the software + PERFORMER: Richard Stallman CD-TEXT for Track 1: diff --git a/test/cdtext.right b/test/cdtext.right index f13283e4..b8e3a02e 100644 --- a/test/cdtext.right +++ b/test/cdtext.right @@ -13,37 +13,69 @@ audio status: not implemented __________________________________ CD Analysis Report +Language 0 'English': 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 + TITLE: Joyful Nights + PERFORMER: United Cat Orchestra + SONGWRITER: Various Songwriters + COMPOSER: Various Composers + MESSAGE: For all our fans + ARRANGER: Tom Cat + UPC_EAN: 1234567890123 + GENRE: Feline classic music + DISC_ID: 1234567890 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 + TITLE: Song of Joy + PERFORMER: Felix and The Purrs + SONGWRITER: Friedrich Schiller + COMPOSER: unknown + MESSAGE: Fritz and Louie once were punks + ARRANGER: Tom Cat + ISRC: XYBLG1101234 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 + TITLE: Humpty Dumpty + PERFORMER: Catwalk Beauties + SONGWRITER: Mother Goose + MESSAGE: Pluck the goose + ISRC: XYBLG1100005 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 + TITLE: Mee Owwww + PERFORMER: Mia Kitten + SONGWRITER: Mia Kitten + COMPOSER: Mia Kitten + ARRANGER: Mia Kitten + ISRC: XYBLG1100006 + +Language 1 'German': +CD-TEXT for Disc: + TITLE: Freudvolle Nächte + PERFORMER: Vereinigtes Katzenorchester + SONGWRITER: Verschiedene Liedschreiber + COMPOSER: Verschiedene Komponisten + MESSAGE: Für alle unsere Fans + ARRANGER: Tom Cat + UPC_EAN: 1234567890123 + GENRE: Katzenhafte Klassik + DISC_ID: 1234567890 +CD-TEXT for Track 1: + TITLE: Lied der Freude + PERFORMER: Felix und Die Schnurrer + SONGWRITER: Friedrich Schiller + COMPOSER: Ludwig van Beethoven + MESSAGE: Fritz und Louie waren einmal Punks + ARRANGER: Tom Cat + ISRC: XYBLG1101234 +CD-TEXT for Track 2: + TITLE: Rubbeldiekatz + PERFORMER: Katzengang Schönheiten + SONGWRITER: Mutter Gans + COMPOSER: unbekannt + MESSAGE: Rupft die Gans + ISRC: XYBLG1100005 +CD-TEXT for Track 3: + TITLE: Mie auu + PERFORMER: Mia Kätzchen + SONGWRITER: Mia Kätzchen + COMPOSER: Mia Kätzchen + ARRANGER: Mia Kätzchen + ISRC: XYBLG1100006 diff --git a/test/check_cue.sh.in b/test/check_cue.sh.in index ff34721f..d52b6661 100644 --- a/test/check_cue.sh.in +++ b/test/check_cue.sh.in @@ -72,7 +72,7 @@ if test -f ${abs_top_srcdir}/test/data/${fname}.bin ; then fi else - echo "Don't see CUE file ${abs_top_srcdir}/test/data/${fname}.bin. Test $testnum skipped." + echo "Don't see binary file ${abs_top_srcdir}/test/data/${fname}.bin. Test $testnum skipped." fi if test -n "@HAVE_ROCK@"; then diff --git a/test/data/cdtext.cdt b/test/data/cdtext.cdt index bf62455b..37b5f7de 100644 Binary files a/test/data/cdtext.cdt and b/test/data/cdtext.cdt differ diff --git a/test/driver/nrg.c.in b/test/driver/nrg.c.in index 1e746cbe..f20f4f11 100644 --- a/test/driver/nrg.c.in +++ b/test/driver/nrg.c.in @@ -56,7 +56,7 @@ main(int argc, const char *argv[]) "Richard Stallman", "Join us now we have the software" }; - const int cdtext_fields[NUM_FIELDS] = {CDTEXT_PERFORMER, CDTEXT_TITLE}; + const int cdtext_fields[NUM_FIELDS] = {CDTEXT_FIELD_PERFORMER, CDTEXT_FIELD_TITLE}; cdio_loglevel_default = (argc > 1) ? CDIO_LOG_DEBUG : CDIO_LOG_INFO; /* snprintf(psz_nrgfile, sizeof(psz_nrgfile)-1, @@ -77,7 +77,7 @@ main(int argc, const char *argv[]) cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio); if (!p_cdtext) return(1); for (i=0; i