File indexing completed on 2023-09-24 05:03:02
0001 /*************************************************************************** 0002 cdtext.c - description 0003 ------------------- 0004 begin : Mon Feb 12 2001 0005 copyright : (C) 2001,2003 by Alex Kern 0006 email : alex.kern@gmx.de 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 ***************************************************************************/ 0017 0018 #include <errno.h> 0019 #include <stdio.h> 0020 #include <unistd.h> 0021 #include <stdlib.h> 0022 #include <string.h> 0023 #include <sys/types.h> 0024 #ifdef libunicode 0025 #include <unicode.h> 0026 #endif 0027 0028 #include "include/wm_config.h" 0029 #include "include/wm_struct.h" 0030 #include "include/wm_cdrom.h" 0031 #include "include/wm_platform.h" 0032 #include "include/wm_helpers.h" 0033 #include "include/wm_cdtext.h" 0034 #include "include/wm_scsi.h" 0035 0036 #define WM_MSG_CLASS WM_MSG_CLASS_MISC 0037 0038 /* local prototypes */ 0039 int free_cdtext_info_block(struct cdtext_info_block* cdtextinfoblock); 0040 int free_cdtext_info(struct cdtext_info* cdtextinfo); 0041 struct cdtext_info_block* malloc_cdtext_info_block(int count_of_tracks); 0042 void get_data_from_cdtext_pack( 0043 const struct cdtext_pack_data_header *pack, 0044 cdtext_string *p_componente); 0045 0046 struct cdtext_info wm_cdtext_info; 0047 0048 int free_cdtext_info_block(struct cdtext_info_block* cdtextinfoblock) 0049 { 0050 if(cdtextinfoblock) 0051 { 0052 if(cdtextinfoblock->name) 0053 free(cdtextinfoblock->name); 0054 if(cdtextinfoblock->performer) 0055 free(cdtextinfoblock->performer); 0056 if(cdtextinfoblock->songwriter) 0057 free(cdtextinfoblock->songwriter); 0058 if(cdtextinfoblock->composer) 0059 free(cdtextinfoblock->composer); 0060 if(cdtextinfoblock->arranger) 0061 free(cdtextinfoblock->arranger); 0062 if(cdtextinfoblock->message) 0063 free(cdtextinfoblock->message); 0064 if(cdtextinfoblock->UPC_EAN_ISRC_code) 0065 free(cdtextinfoblock->UPC_EAN_ISRC_code); 0066 0067 if(cdtextinfoblock->block_encoding_text) 0068 free(cdtextinfoblock->block_encoding_text); 0069 } 0070 0071 return 0; 0072 } 0073 0074 int free_cdtext_info(struct cdtext_info* cdtextinfo) 0075 { 0076 int i; 0077 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0078 "CDTEXT INFO: free_cdtext_info() called\n"); 0079 0080 if(cdtextinfo) 0081 { 0082 for(i = 0; i < 8; i++) 0083 { 0084 if(cdtextinfo->blocks[i]) 0085 { 0086 free_cdtext_info_block(cdtextinfo->blocks[i]); 0087 } 0088 } 0089 memset(cdtextinfo, 0, sizeof(struct cdtext_info)); 0090 } 0091 0092 return 0; 0093 } 0094 0095 struct cdtext_info_block* malloc_cdtext_info_block(int count_of_tracks) 0096 { 0097 int memamount; 0098 struct cdtext_info_block* lp_block; 0099 0100 lp_block = malloc(sizeof(struct cdtext_info_block)); 0101 if(!lp_block) 0102 { 0103 return (struct cdtext_info_block*)0; 0104 } 0105 memset(lp_block, 0, sizeof(struct cdtext_info_block)); 0106 0107 memamount = count_of_tracks * sizeof(cdtext_string); 0108 0109 lp_block->name = malloc(memamount); 0110 if(!lp_block->name) 0111 goto bail_out; 0112 memset(lp_block->name, 0, memamount); 0113 0114 lp_block->performer = malloc(memamount); 0115 if(!lp_block->performer) 0116 goto bail_out; 0117 memset(lp_block->performer, 0, memamount); 0118 0119 lp_block->songwriter = malloc(memamount); 0120 if(!lp_block->songwriter) 0121 goto bail_out; 0122 memset(lp_block->songwriter, 0, memamount); 0123 0124 lp_block->composer = malloc(memamount); 0125 if(!lp_block->composer) 0126 goto bail_out; 0127 memset(lp_block->composer, 0, memamount); 0128 0129 lp_block->arranger = malloc(memamount); 0130 if(!lp_block->arranger) 0131 goto bail_out; 0132 memset(lp_block->arranger, 0, memamount); 0133 0134 lp_block->message = malloc(memamount); 0135 if(!lp_block->message) 0136 goto bail_out; 0137 memset(lp_block->message, 0, memamount); 0138 0139 lp_block->UPC_EAN_ISRC_code = malloc(memamount); 0140 if(!lp_block->UPC_EAN_ISRC_code) 0141 goto bail_out; 0142 memset(lp_block->UPC_EAN_ISRC_code, 0, memamount); 0143 0144 return lp_block; 0145 0146 bail_out: 0147 free_cdtext_info_block(lp_block); 0148 free(lp_block); 0149 return 0; 0150 } 0151 0152 void get_data_from_cdtext_pack( 0153 const struct cdtext_pack_data_header *pack, 0154 cdtext_string *p_componente) 0155 { 0156 0157 int arr = pack->header_field_id2_tracknumber; 0158 int i; 0159 int language_block; 0160 int unicode; 0161 0162 language_block = (pack->header_field_id4_block_no >> 4) & 0x07; 0163 unicode = pack->header_field_id4_block_no & 0x80; 0164 0165 if(!unicode) 0166 { 0167 for(i = 0; i < DATAFIELD_LENGHT_IN_PACK; i++) 0168 { 0169 if(pack->text_data_field[i] == 0x00) /* end marker */ 0170 { 0171 arr++; 0172 } 0173 else if(pack->text_data_field[i] == 0x09) /* repeat last marker */ 0174 { 0175 /* ASSERT(arr > 0) */ 0176 strcat((char*)(p_componente[arr]), (char*)(p_componente[arr-1])); 0177 arr++; 0178 } 0179 else 0180 { 0181 strncat((char*)(p_componente[arr]), (char*)(&(pack->text_data_field[i])), 1); 0182 } 0183 } 0184 } 0185 #ifdef libunicode 0186 else /* doublebytes ;-) */ 0187 { 0188 for(i = 0; i < DATAFIELD_LENGHT_IN_PACK; i += 2) 0189 { 0190 if((Uchar)(pack->text_data_field[i]) == 0x0000) /* end marker */ 0191 { 0192 arr++; 0193 } 0194 else if((Uchar)(pack->text_data_field[i]) == 0x0909) /* repeat last marker */ 0195 { 0196 /* ASSERT(arr > 0) */ 0197 strcat((char*)(p_componente[arr]), (char*)(p_componente[arr-1])); 0198 arr++; 0199 } 0200 else 0201 { 0202 strncat((char*)(p_componente[arr]), u_uc_to_utf8((Uchar*)(&(pack->text_data_field[i]))), 1); 0203 } 0204 } 0205 } 0206 #else 0207 else { 0208 wm_lib_message(WM_MSG_LEVEL_ERROR | WM_MSG_CLASS, "cannot handle unicode"); 0209 } 0210 #endif 0211 } 0212 0213 struct cdtext_info *get_glob_cdtext(struct wm_drive *d, int redo) 0214 { 0215 /* alloc cdtext_info */ 0216 0217 unsigned char *buffer; 0218 int buffer_length; 0219 int ret; 0220 int i; 0221 struct cdtext_pack_data_header *pack, *pack_previous; 0222 cdtext_string *p_componente; 0223 struct cdtext_info_block *lp_block; 0224 0225 if(!redo && wm_cdtext_info.valid) { 0226 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, "CDTEXT DEBUG: recycle cdtext\n"); 0227 return &wm_cdtext_info; 0228 } else { 0229 free_cdtext_info(&wm_cdtext_info); 0230 } 0231 0232 lp_block = 0; 0233 p_componente = 0; 0234 buffer = 0; 0235 buffer_length = 0; 0236 0237 ret = wm_scsi_get_cdtext(d, &buffer, &buffer_length); 0238 if(!ret) 0239 { 0240 if(!d->proto.get_trackcount || d->proto.get_trackcount(d, &wm_cdtext_info.count_of_entries) < 0) 0241 wm_cdtext_info.count_of_entries = 1; 0242 else 0243 wm_cdtext_info.count_of_entries++; 0244 0245 i = 0; 0246 0247 pack = 0; /* NULL pointer*/ 0248 while(i < buffer_length) 0249 { 0250 pack_previous = pack; 0251 pack = (struct cdtext_pack_data_header*)(buffer+i); 0252 /* to implement: check_crc(pack); */ 0253 0254 /* only for valid packs */ 0255 if(pack->header_field_id1_typ_of_pack >= 0x80 && pack->header_field_id1_typ_of_pack < 0x90) 0256 { 0257 int code, j; 0258 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0259 "CDTEXT DEBUG: valid packet at 0x%08X: 0x %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 0260 i, 0261 pack->header_field_id1_typ_of_pack, 0262 pack->header_field_id2_tracknumber, 0263 pack->header_field_id3_sequence, 0264 pack->header_field_id4_block_no, 0265 pack->text_data_field[0], 0266 pack->text_data_field[1], 0267 pack->text_data_field[2], 0268 pack->text_data_field[3], 0269 pack->text_data_field[4], 0270 pack->text_data_field[5], 0271 pack->text_data_field[6], 0272 pack->text_data_field[7], 0273 pack->text_data_field[8], 0274 pack->text_data_field[9], 0275 pack->text_data_field[10], 0276 pack->text_data_field[11], 0277 pack->crc_byte1, 0278 pack->crc_byte2); 0279 wm_cdtext_info.count_of_valid_packs++; 0280 0281 code = (pack->header_field_id4_block_no >> 4) & 0x07; 0282 if(0 == lp_block || lp_block->block_code != code) /* find or create one new block */ 0283 { 0284 lp_block = 0; 0285 for(j = 0; j < MAX_LANGUAGE_BLOCKS && wm_cdtext_info.blocks[j] != 0 && 0 == lp_block; j++) 0286 { 0287 if(wm_cdtext_info.blocks[j]->block_code == code) 0288 { 0289 lp_block = wm_cdtext_info.blocks[j]; 0290 } 0291 } 0292 0293 if(MAX_LANGUAGE_BLOCKS <= j) 0294 { 0295 free_cdtext_info(&wm_cdtext_info); 0296 wm_lib_message(WM_MSG_LEVEL_ERROR | WM_MSG_CLASS, 0297 "CDTEXT ERROR: more as 8 languageblocks defined\n"); 0298 return NULL; 0299 } 0300 0301 if(0 == lp_block) 0302 { 0303 /* make next new block */ 0304 lp_block = malloc_cdtext_info_block(wm_cdtext_info.count_of_entries); 0305 if(0 == lp_block) 0306 { 0307 wm_lib_message(WM_MSG_LEVEL_ERROR | WM_MSG_CLASS, 0308 "CDTEXT ERROR: out of memory, cannot create a new language block\n"); 0309 free_cdtext_info(&wm_cdtext_info); 0310 return NULL /*ENOMEM*/; 0311 } 0312 else 0313 { 0314 wm_cdtext_info.blocks[j] = lp_block; 0315 wm_cdtext_info.blocks[j]->block_code = code; 0316 wm_cdtext_info.blocks[j]->block_unicode = pack->header_field_id4_block_no & 0x80; 0317 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0318 "CDTEXT INFO: created a new language block; code %i, %s characters\n", code, lp_block->block_unicode?"doublebyte":"singlebyte"); 0319 /* 0320 unsigned char block_encoding; not jet! 0321 cdtext_string* block_encoding_text; 0322 */ 0323 } 0324 } 0325 } 0326 } 0327 0328 switch(pack->header_field_id1_typ_of_pack) 0329 { 0330 case 0x80: 0331 p_componente = (lp_block->name); 0332 get_data_from_cdtext_pack(pack, p_componente); 0333 break; 0334 case 0x81: 0335 p_componente = (lp_block->performer); 0336 get_data_from_cdtext_pack(pack, p_componente); 0337 break; 0338 case 0x82: 0339 p_componente = (lp_block->songwriter); 0340 get_data_from_cdtext_pack(pack, p_componente); 0341 break; 0342 case 0x83: 0343 p_componente = (lp_block->composer); 0344 get_data_from_cdtext_pack(pack, p_componente); 0345 break; 0346 case 0x84: 0347 p_componente = (lp_block->arranger); 0348 get_data_from_cdtext_pack(pack, p_componente); 0349 break; 0350 case 0x85: 0351 p_componente = (lp_block->message); 0352 get_data_from_cdtext_pack(pack, p_componente); 0353 break; 0354 case 0x86: 0355 memcpy((char*)(lp_block->binary_disc_identification_info), 0356 (char*)(pack->text_data_field), DATAFIELD_LENGHT_IN_PACK); 0357 break; 0358 case 0x87: 0359 memcpy((char*)(lp_block->binary_genreidentification_info), 0360 (char*)(pack->text_data_field), DATAFIELD_LENGHT_IN_PACK); 0361 break; 0362 case 0x88: 0363 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0364 "CDTEXT INFO: PACK with code 0x88 (TOC)\n"); 0365 break; 0366 case 0x89: 0367 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0368 "CDTEXT INFO: PACK with code 0x89 (second TOC)\n"); 0369 break; 0370 case 0x8A: 0371 case 0x8B: 0372 case 0x8C: 0373 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0374 "CDTEXT INFO: PACK with code 0x%02X (reserved)\n", pack->header_field_id1_typ_of_pack); 0375 break; 0376 case 0x8D: 0377 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0378 "CDTEXT INFO: PACK with code 0x8D (for content provider only)\n"); 0379 break; 0380 case 0x8E: 0381 p_componente = (lp_block->UPC_EAN_ISRC_code); 0382 get_data_from_cdtext_pack(pack, p_componente); 0383 break; 0384 case 0x8F: 0385 memcpy((char*)(lp_block->binary_size_information), 0386 (char*)(pack->text_data_field), DATAFIELD_LENGHT_IN_PACK); 0387 break; 0388 default: 0389 wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, 0390 "CDTEXT ERROR: invalid packet at 0x%08X: 0x %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 0391 i, 0392 pack->header_field_id1_typ_of_pack, 0393 pack->header_field_id2_tracknumber, 0394 pack->header_field_id3_sequence, 0395 pack->header_field_id4_block_no, 0396 pack->text_data_field[0], 0397 pack->text_data_field[1], 0398 pack->text_data_field[2], 0399 pack->text_data_field[3], 0400 pack->text_data_field[4], 0401 pack->text_data_field[5], 0402 pack->text_data_field[6], 0403 pack->text_data_field[7], 0404 pack->text_data_field[8], 0405 pack->text_data_field[9], 0406 pack->text_data_field[10], 0407 pack->text_data_field[11], 0408 pack->crc_byte1, 0409 pack->crc_byte2); 0410 wm_cdtext_info.count_of_invalid_packs++; 0411 } 0412 i += sizeof(struct cdtext_pack_data_header); 0413 } /* while */ 0414 } 0415 0416 if(0 == ret && wm_cdtext_info.count_of_valid_packs > 0) 0417 wm_cdtext_info.valid = 1; 0418 0419 return &wm_cdtext_info; 0420 } 0421 0422 void free_cdtext(void) 0423 { 0424 if (wm_cdtext_info.valid) 0425 free_cdtext_info(&wm_cdtext_info); 0426 }