summaryrefslogtreecommitdiffstats
path: root/kscd/libwm/cdtext.c
diff options
context:
space:
mode:
Diffstat (limited to 'kscd/libwm/cdtext.c')
-rw-r--r--kscd/libwm/cdtext.c428
1 files changed, 428 insertions, 0 deletions
diff --git a/kscd/libwm/cdtext.c b/kscd/libwm/cdtext.c
new file mode 100644
index 00000000..bb4e19b8
--- /dev/null
+++ b/kscd/libwm/cdtext.c
@@ -0,0 +1,428 @@
+/***************************************************************************
+ cdtext.c - description
+ -------------------
+ begin : Mon Feb 12 2001
+ copyright : (C) 2001,2003 by Alex Kern
+ email : alex.kern@gmx.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef libunicode
+ #include <unicode.h>
+#endif
+
+#include "include/wm_config.h"
+#include "include/wm_struct.h"
+#include "include/wm_cdrom.h"
+#include "include/wm_database.h"
+#include "include/wm_platform.h"
+#include "include/wm_helpers.h"
+#include "include/wm_cdinfo.h"
+#include "include/wm_cdtext.h"
+
+#define WM_MSG_CLASS WM_MSG_CLASS_MISC
+
+/* local prototypes */
+int free_cdtext_info_block(struct cdtext_info_block* cdtextinfoblock);
+int free_cdtext_info(struct cdtext_info* cdtextinfo);
+struct cdtext_info_block* malloc_cdtext_info_block(int count_of_tracks);
+void get_data_from_cdtext_pack(
+ const struct cdtext_pack_data_header *pack,
+ const struct cdtext_pack_data_header *pack_previous,
+ cdtext_string *p_componente);
+
+struct cdtext_info wm_cdtext_info = { 0, 0, 0, 0 };
+
+int free_cdtext_info_block(struct cdtext_info_block* cdtextinfoblock)
+{
+ if(cdtextinfoblock)
+ {
+ if(cdtextinfoblock->name)
+ free(cdtextinfoblock->name);
+ if(cdtextinfoblock->performer)
+ free(cdtextinfoblock->performer);
+ if(cdtextinfoblock->songwriter)
+ free(cdtextinfoblock->songwriter);
+ if(cdtextinfoblock->composer)
+ free(cdtextinfoblock->composer);
+ if(cdtextinfoblock->arranger)
+ free(cdtextinfoblock->arranger);
+ if(cdtextinfoblock->message)
+ free(cdtextinfoblock->message);
+ if(cdtextinfoblock->UPC_EAN_ISRC_code)
+ free(cdtextinfoblock->UPC_EAN_ISRC_code);
+
+ if(cdtextinfoblock->block_encoding_text)
+ free(cdtextinfoblock->block_encoding_text);
+ }
+
+ return 0;
+}
+
+int free_cdtext_info(struct cdtext_info* cdtextinfo)
+{
+ int i;
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "CDTEXT INFO: free_cdtext_info() called\n");
+
+ if(cdtextinfo)
+ {
+ for(i = 0; i < 8; i++)
+ {
+ if(cdtextinfo->blocks[i])
+ {
+ free_cdtext_info_block(cdtextinfo->blocks[i]);
+ }
+ }
+ memset(cdtextinfo, 0, sizeof(struct cdtext_info));
+ }
+
+ return 0;
+}
+
+struct cdtext_info_block* malloc_cdtext_info_block(int count_of_tracks)
+{
+ int memamount;
+ struct cdtext_info_block* lp_block;
+
+ lp_block = malloc(sizeof(struct cdtext_info_block));
+ if(!lp_block)
+ {
+ return (struct cdtext_info_block*)0;
+ }
+ memset(lp_block, 0, sizeof(struct cdtext_info_block));
+
+ memamount = count_of_tracks * sizeof(cdtext_string);
+
+ lp_block->name = malloc(memamount);
+ if(!lp_block->name)
+ return (struct cdtext_info_block*)free_cdtext_info_block(lp_block);
+ memset(lp_block->name, 0, memamount);
+
+ lp_block->performer = malloc(memamount);
+ if(!lp_block->performer)
+ return (struct cdtext_info_block*)free_cdtext_info_block(lp_block);
+ memset(lp_block->performer, 0, memamount);
+
+ lp_block->songwriter = malloc(memamount);
+ if(!lp_block->songwriter)
+ return (struct cdtext_info_block*)free_cdtext_info_block(lp_block);
+ memset(lp_block->songwriter, 0, memamount);
+
+ lp_block->composer = malloc(memamount);
+ if(!lp_block->composer)
+ return (struct cdtext_info_block*)free_cdtext_info_block(lp_block);
+ memset(lp_block->composer, 0, memamount);
+
+ lp_block->arranger = malloc(memamount);
+ if(!lp_block->arranger)
+ return (struct cdtext_info_block*)free_cdtext_info_block(lp_block);
+ memset(lp_block->arranger, 0, memamount);
+
+ lp_block->message = malloc(memamount);
+ if(!lp_block->message)
+ return (struct cdtext_info_block*)free_cdtext_info_block(lp_block);
+ memset(lp_block->message, 0, memamount);
+
+ lp_block->UPC_EAN_ISRC_code = malloc(memamount);
+ if(!lp_block->UPC_EAN_ISRC_code)
+ return (struct cdtext_info_block*)free_cdtext_info_block(lp_block);
+ memset(lp_block->UPC_EAN_ISRC_code, 0, memamount);
+
+ return lp_block;
+}
+
+void get_data_from_cdtext_pack(
+ const struct cdtext_pack_data_header *pack,
+ const struct cdtext_pack_data_header *pack_previous,
+ cdtext_string *p_componente)
+{
+
+ int arr = pack->header_field_id2_tracknumber;
+ int i;
+ int language_block;
+ int unicode;
+
+ language_block = (pack->header_field_id4_block_no >> 4) & 0x07;
+ unicode = pack->header_field_id4_block_no & 0x80;
+
+ if(!unicode)
+ {
+ for(i = 0; i < DATAFIELD_LENGHT_IN_PACK; i++)
+ {
+ if(pack->text_data_field[i] == 0x00) /* end marker */
+ {
+ arr++;
+ }
+ else if(pack->text_data_field[i] == 0x09) /* repeat last marker */
+ {
+ /* ASSERT(arr > 0) */
+ strcat((char*)(p_componente[arr]), (char*)(p_componente[arr-1]));
+ arr++;
+ }
+ else
+ {
+ strncat((char*)(p_componente[arr]), (char*)(&(pack->text_data_field[i])), 1);
+ }
+ }
+ }
+#ifdef libunicode
+ else /* doublebytes ;-) */
+ {
+ for(i = 0; i < DATAFIELD_LENGHT_IN_PACK; i += 2)
+ {
+ if((Uchar)(pack->text_data_field[i]) == 0x0000) /* end marker */
+ {
+ arr++;
+ }
+ else if((Uchar)(pack->text_data_field[i]) == 0x0909) /* repeat last marker */
+ {
+ /* ASSERT(arr > 0) */
+ strcat((char*)(p_componente[arr]), (char*)(p_componente[arr-1]));
+ arr++;
+ }
+ else
+ {
+ strncat((char*)(p_componente[arr]), u_uc_to_utf8((Uchar*)(&(pack->text_data_field[i]))), 1);
+ }
+ }
+ }
+#else
+ else {
+ wm_lib_message(WM_MSG_LEVEL_ERROR | WM_MSG_CLASS, "can't handle unicode");
+ }
+#endif
+}
+
+struct cdtext_info*
+get_glob_cdtext(struct wm_drive *d, int redo)
+{
+ /* alloc cdtext_info */
+
+ unsigned char *buffer;
+ int buffer_length;
+ int ret;
+ int i;
+ struct cdtext_pack_data_header *pack, *pack_previous;
+ cdtext_string *p_componente;
+ struct cdtext_info_block *lp_block;
+ if(!d->proto || d->proto->gen_get_cdtext == NULL || d->proto->gen_get_trackcount == NULL) {
+ return NULL;
+ }
+
+ if(!redo && wm_cdtext_info.valid) {
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS, "CDTEXT DEBUG: recycle cdtext\n");
+ return &wm_cdtext_info;
+ } else
+ free_cdtext_info(&wm_cdtext_info);
+
+ lp_block = 0;
+ p_componente = 0;
+ buffer = 0;
+ buffer_length = 0;
+
+ ret = (d->proto->gen_get_cdtext)(d, &buffer, &buffer_length);
+ if(!ret)
+ {
+ (d->proto->gen_get_trackcount)(d, &(wm_cdtext_info.count_of_entries));
+ if( wm_cdtext_info.count_of_entries < 0 )
+ wm_cdtext_info.count_of_entries = 1;
+ else
+ wm_cdtext_info.count_of_entries++;
+
+ i = 0;
+
+ pack = 0; /* NULL pointer*/
+ while(i < buffer_length)
+ {
+ pack_previous = pack;
+ pack = (struct cdtext_pack_data_header*)(buffer+i);
+ /* to implement: check_crc(pack); */
+
+ /* only for valid packs */
+ if(pack->header_field_id1_typ_of_pack >= 0x80 && pack->header_field_id1_typ_of_pack < 0x90)
+ {
+ int code, j;
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "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",
+ i,
+ pack->header_field_id1_typ_of_pack,
+ pack->header_field_id2_tracknumber,
+ pack->header_field_id3_sequence,
+ pack->header_field_id4_block_no,
+ pack->text_data_field[0],
+ pack->text_data_field[1],
+ pack->text_data_field[2],
+ pack->text_data_field[3],
+ pack->text_data_field[4],
+ pack->text_data_field[5],
+ pack->text_data_field[6],
+ pack->text_data_field[7],
+ pack->text_data_field[8],
+ pack->text_data_field[9],
+ pack->text_data_field[10],
+ pack->text_data_field[11],
+ pack->crc_byte1,
+ pack->crc_byte2);
+ wm_cdtext_info.count_of_valid_packs++;
+
+ code = (pack->header_field_id4_block_no >> 4) & 0x07;
+ if(0 == lp_block || lp_block->block_code != code) /* find or create one new block */
+ {
+ lp_block = 0;
+ for(j = 0; j < MAX_LANGUAGE_BLOCKS && wm_cdtext_info.blocks[j] != 0 && 0 == lp_block; j++)
+ {
+ if(wm_cdtext_info.blocks[j]->block_code == code)
+ {
+ lp_block = wm_cdtext_info.blocks[j];
+ }
+ }
+
+ if(MAX_LANGUAGE_BLOCKS <= j)
+ {
+ free_cdtext_info(&wm_cdtext_info);
+ wm_lib_message(WM_MSG_LEVEL_ERROR | WM_MSG_CLASS,
+ "CDTEXT ERROR: more as 8 languageblocks defined\n");
+ return NULL;
+ }
+
+ if(0 == lp_block)
+ {
+ /* make next new block */
+ lp_block = malloc_cdtext_info_block(wm_cdtext_info.count_of_entries);
+ if(0 == lp_block)
+ {
+ wm_lib_message(WM_MSG_LEVEL_ERROR | WM_MSG_CLASS,
+ "CDTEXT ERROR: out of memory, can't create a new language block\n");
+ free_cdtext_info(&wm_cdtext_info);
+ return NULL /*ENOMEM*/;
+ }
+ else
+ {
+ wm_cdtext_info.blocks[j] = lp_block;
+ wm_cdtext_info.blocks[j]->block_code = code;
+ wm_cdtext_info.blocks[j]->block_unicode = pack->header_field_id4_block_no & 0x80;
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "CDTEXT INFO: created a new language block; code %i, %s characters\n", code, lp_block->block_unicode?"doublebyte":"singlebyte");
+/*
+ unsigned char block_encoding; not jet!
+ cdtext_string* block_encoding_text;
+*/
+ }
+ }
+ }
+ }
+
+ switch(pack->header_field_id1_typ_of_pack)
+ {
+ case 0x80:
+ p_componente = (lp_block->name);
+ get_data_from_cdtext_pack(pack, pack_previous, p_componente);
+ break;
+ case 0x81:
+ p_componente = (lp_block->performer);
+ get_data_from_cdtext_pack(pack, pack_previous, p_componente);
+ break;
+ case 0x82:
+ p_componente = (lp_block->songwriter);
+ get_data_from_cdtext_pack(pack, pack_previous, p_componente);
+ break;
+ case 0x83:
+ p_componente = (lp_block->composer);
+ get_data_from_cdtext_pack(pack, pack_previous, p_componente);
+ break;
+ case 0x84:
+ p_componente = (lp_block->arranger);
+ get_data_from_cdtext_pack(pack, pack_previous, p_componente);
+ break;
+ case 0x85:
+ p_componente = (lp_block->message);
+ get_data_from_cdtext_pack(pack, pack_previous, p_componente);
+ break;
+ case 0x86:
+ memcpy((char*)(lp_block->binary_disc_identification_info),
+ (char*)(pack->text_data_field), DATAFIELD_LENGHT_IN_PACK);
+ break;
+ case 0x87:
+ memcpy((char*)(lp_block->binary_genreidentification_info),
+ (char*)(pack->text_data_field), DATAFIELD_LENGHT_IN_PACK);
+ break;
+ case 0x88:
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "CDTEXT INFO: PACK with code 0x88 (TOC)\n");
+ break;
+ case 0x89:
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "CDTEXT INFO: PACK with code 0x89 (second TOC)\n");
+ break;
+ case 0x8A:
+ case 0x8B:
+ case 0x8C:
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "CDTEXT INFO: PACK with code 0x%02X (reserved)\n", pack->header_field_id1_typ_of_pack);
+ break;
+ case 0x8D:
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "CDTEXT INFO: PACK with code 0x8D (for content provider only)\n");
+ break;
+ case 0x8E:
+ p_componente = (lp_block->UPC_EAN_ISRC_code);
+ get_data_from_cdtext_pack(pack, pack_previous, p_componente);
+ break;
+ case 0x8F:
+ memcpy((char*)(lp_block->binary_size_information),
+ (char*)(pack->text_data_field), DATAFIELD_LENGHT_IN_PACK);
+ break;
+ default:
+ wm_lib_message(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS,
+ "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",
+ i,
+ pack->header_field_id1_typ_of_pack,
+ pack->header_field_id2_tracknumber,
+ pack->header_field_id3_sequence,
+ pack->header_field_id4_block_no,
+ pack->text_data_field[0],
+ pack->text_data_field[1],
+ pack->text_data_field[2],
+ pack->text_data_field[3],
+ pack->text_data_field[4],
+ pack->text_data_field[5],
+ pack->text_data_field[6],
+ pack->text_data_field[7],
+ pack->text_data_field[8],
+ pack->text_data_field[9],
+ pack->text_data_field[10],
+ pack->text_data_field[11],
+ pack->crc_byte1,
+ pack->crc_byte2);
+ wm_cdtext_info.count_of_invalid_packs++;
+ }
+ i += sizeof(struct cdtext_pack_data_header);
+ } /* while */
+ }
+
+ if(0 == ret && wm_cdtext_info.count_of_valid_packs > 0)
+ wm_cdtext_info.valid = 1;
+
+ return &wm_cdtext_info;
+}
+
+void free_cdtext(void)
+{
+ if (wm_cdtext_info.valid)
+ free_cdtext_info(&wm_cdtext_info);
+}