Mercurial > audlegacy
view Plugins/Input/mpg123/id3_frame_text.c @ 238:580529c7e0c5 trunk
[svn] Add gdk_flush() to widget_draw_quick().
author | nenolod |
---|---|
date | Sat, 26 Nov 2005 19:04:04 -0800 |
parents | 08973a746a3e |
children | 18cb7405b5e9 |
line wrap: on
line source
/********************************************************************* * * Copyright (C) 1999, 2001, 2002, Espen Skoglund * Department of Computer Science, University of Tromsų * * Filename: id3_frame_text.c * Description: Code for handling ID3 text frames. * Author: Espen Skoglund <espensk@stud.cs.uit.no> * Created at: Fri Feb 5 23:50:33 1999 * * $Id: id3_frame_text.c,v 1.7 2004/08/21 13:04:47 descender Exp $ * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #include "config.h" #include <stdarg.h> #include <stdlib.h> #include <string.h> #include "xmms-id3.h" #include "id3_header.h" /* * Function id3_get_encoding (frame) * * Return text encoding for frame, or -1 if frame does not have any * text encoding. * */ gint8 id3_get_encoding(struct id3_frame * frame) { guint8 encoding; /* Type check */ if (!id3_frame_is_text(frame) && frame->fr_desc->fd_id != ID3_WXXX && frame->fr_desc->fd_id != ID3_IPLS && frame->fr_desc->fd_id != ID3_USLT && frame->fr_desc->fd_id != ID3_SYLT && frame->fr_desc->fd_id != ID3_COMM && frame->fr_desc->fd_id != ID3_APIC && frame->fr_desc->fd_id != ID3_GEOB && frame->fr_desc->fd_id != ID3_USER && frame->fr_desc->fd_id != ID3_OWNE && frame->fr_desc->fd_id != ID3_COMR) return -1; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return -1; ID3_FRAME_DEFINE_CURSOR(frame); ID3_FRAME_READ_OR_RETVAL(encoding, -1); return encoding; } /* * Function id3_set_encoding (frame, encoding) * * Set text encoding for frame. Return 0 upon success, or -1 if an * error occured. * */ int id3_set_encoding(struct id3_frame *frame, gint8 encoding) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T' && frame->fr_desc->fd_id != ID3_WXXX && frame->fr_desc->fd_id != ID3_IPLS && frame->fr_desc->fd_id != ID3_USLT && frame->fr_desc->fd_id != ID3_SYLT && frame->fr_desc->fd_id != ID3_COMM && frame->fr_desc->fd_id != ID3_APIC && frame->fr_desc->fd_id != ID3_GEOB && frame->fr_desc->fd_id != ID3_USER && frame->fr_desc->fd_id != ID3_OWNE && frame->fr_desc->fd_id != ID3_COMR) return -1; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return -1; /* Changing the encoding of frames is not supported yet */ if (*(gint8 *) frame->fr_data != encoding) return -1; /* Set encoding */ *(gint8 *) frame->fr_data = encoding; return 0; } /* Get size of string in bytes including null. */ gsize id3_string_size(guint8 encoding, const void* text, gsize max_size) { switch ( encoding ) { case ID3_ENCODING_ISO_8859_1: case ID3_ENCODING_UTF8: { const guint8* text8 = text; while ( (max_size >= sizeof(*text8)) && (*text8 != 0) ) { ++text8; max_size -= sizeof(*text8); } if (max_size >= sizeof(*text8)) { ++text8; max_size -= sizeof(*text8); } return text8 - (guint8*)text; } case ID3_ENCODING_UTF16: case ID3_ENCODING_UTF16BE: { const guint16* text16 = (guint16*)text; while ( (max_size > 0) && (*text16 != 0) ) { ++text16; max_size -= sizeof(*text16); } if (max_size > 0) { ++text16; max_size -= sizeof(*text16); } return (guint8*)text16 - (guint8*)text; } default: return 0; } } /* Returns a newly-allocated UTF-8 string in the locale's encoding. max_size specifies the maximum size of 'text', including terminating nulls. */ gchar* id3_string_decode(guint8 encoding, const void* text, gsize max_size) { /* Otherwise, we'll end up passing -1 to functions, eliminating safety benefits. */ if (max_size <= 0) return NULL; switch( encoding ) { case ID3_ENCODING_ISO_8859_1: { return g_locale_to_utf8((const gchar*)text, max_size, NULL, NULL, NULL); } case ID3_ENCODING_UTF8: { if (g_utf8_validate((const gchar*)text, max_size, NULL)) return g_strndup((const gchar*)text, max_size); else return NULL; } case ID3_ENCODING_UTF16: { gsize size_bytes = id3_string_size(encoding, text, max_size); gchar* utf8 = g_convert((const gchar*)text, size_bytes, "UTF-8", "UTF-16", NULL, NULL, NULL); /* If conversion passes on the BOM as-is, we strip it. */ if (g_utf8_get_char(utf8) == 0xfeff) { gchar* new_utf8 = g_strdup(utf8+3); g_free(utf8); utf8 = new_utf8; } return utf8; } case ID3_ENCODING_UTF16BE: { gsize size_bytes = id3_string_size(encoding, text, max_size); return g_convert((const gchar*)text, size_bytes, "UTF-8", "UTF-16BE", NULL, NULL, NULL); } default: return NULL; } } /* * Function id3_get_text (frame) * * Return string contents of frame. * */ char * id3_get_text(struct id3_frame *frame) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T' && frame->fr_desc->fd_id != ID3_COMM) return NULL; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return NULL; if (frame->fr_desc->fd_id == ID3_TXXX || frame->fr_desc->fd_id == ID3_COMM) { /* * This is a user defined text frame. Skip the description. */ switch (*(guint8 *) frame->fr_data) { case ID3_ENCODING_ISO_8859_1: { char *text = (char *) frame->fr_data + 1; while (*text != 0) text++; return g_strdup(++text); } case ID3_ENCODING_UTF16: { char *text16 = (char *) frame->fr_data + 1; while (*text16 != 0 || *(text16 + 1) != 0) text16 += 2; return id3_utf16_to_ascii(text16 + 2); } default: return NULL; } } if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1) return g_strdup((char *) frame->fr_data + 1); else return id3_utf16_to_ascii(((char *) frame->fr_data + 1)); } /* * Function id3_get_text_desc (frame) * * Get description part of a text frame. * */ char * id3_get_text_desc(struct id3_frame *frame) { guint8 encoding; /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T') return NULL; /* If predefined text frame, return description. */ if (frame->fr_desc->fd_id != ID3_TXXX) return frame->fr_desc->fd_description; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return NULL; ID3_FRAME_DEFINE_CURSOR(frame); ID3_FRAME_READ_OR_RETVAL(encoding, NULL); return id3_string_decode(encoding, cursor, length); } /* * Function id3_get_text_number (frame) * * Return string contents of frame translated to a positive * integer, or -1 if an error occured. * */ int id3_get_text_number(struct id3_frame *frame) { guint8 encoding; int number = 0; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return -1; ID3_FRAME_DEFINE_CURSOR(frame); ID3_FRAME_READ_OR_RETVAL(encoding, number); gchar* number_str = id3_string_decode(encoding, cursor, length); if (number_str != NULL) { sscanf(number_str, "%d", &number); g_free(number_str); } return number; } /* * Function id3_set_text (frame, text) * * Set text for the indicated frame (only ISO-8859-1 is currently * supported). Return 0 upon success, or -1 if an error occured. * */ int id3_set_text(struct id3_frame *frame, char *text) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T') return -1; /* * Release memory occupied by previous data. */ id3_frame_clear_data(frame); /* * Allocate memory for new data. */ frame->fr_raw_size = strlen(text) + 1; frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1); /* * Copy contents. */ *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1; memcpy((char *) frame->fr_raw_data + 1, text, frame->fr_raw_size); frame->fr_altered = 1; frame->fr_owner->id3_altered = 1; frame->fr_data = frame->fr_raw_data; frame->fr_size = frame->fr_raw_size; return 0; } /* * Function id3_set_text_number (frame, number) * * Set number for the indicated frame (only ISO-8859-1 is currently * supported). Return 0 upon success, or -1 if an error occured. * */ int id3_set_text_number(struct id3_frame *frame, int number) { char buf[64]; int pos; char *text; /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T') return -1; /* * Release memory occupied by previous data. */ id3_frame_clear_data(frame); /* * Create a string with a reversed number. */ pos = 0; while (number > 0 && pos < 64) { buf[pos++] = (number % 10) + '0'; number /= 10; } if (pos == 64) return -1; if (pos == 0) buf[pos++] = '0'; /* * Allocate memory for new data. */ frame->fr_raw_size = pos + 1; frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1); /* * Insert contents. */ *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1; text = (char *) frame->fr_raw_data + 1; strcpy(text, buf); frame->fr_altered = 1; frame->fr_owner->id3_altered = 1; frame->fr_data = frame->fr_raw_data; frame->fr_size = frame->fr_raw_size; return 0; } gboolean id3_frame_is_text(struct id3_frame * frame) { if (frame && frame->fr_desc && (frame->fr_desc->fd_idstr[0] == 'T' || frame->fr_desc->fd_idstr[0] == 'W')) return TRUE; return FALSE; }