/* $Id$ */ /* * Cantus Tag Editor * Copyright © 2002-2004 by Samuel Abels * Copyright © 2007 by Tim Huetz * * 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 3 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, see **/ #ifdef HAVE_CONFIG_H # include #endif #include //#define _DEBUG_ #if defined( __cplusplus ) extern "C" { #endif /****************************************************************************** * Plugin specifications. ******************************************************************************/ #define PLUGINNAME "ID3V1 in-/output plugin" #define PLUGINLABEL _("ID3V1 Tag") #define PLUGINDESCR "Cantus ID3V1 plugin relase 0.1, (c) by Samuel Abels" #define MAJVERSION 0 #define MINVERSION 1 #define COMPATLEVEL 1 const gchar *pattern[] = { "*.mp3", NULL }; /****************************************************************************** * Plugin-internal variables and types. ******************************************************************************/ Tag tag; CantusHash *plugindata; enum ACTIONS { // A bitmask for action type definitions. READ = 1, WRITE = 2 }; typedef struct { // Type for the mapping between hash keys and tag struct. const gchar *name; void *value; gint type; gint action; gint length; } OptVal; OptVal pairs[] = { // The mapping between hash keys and tag struct. { "ID3V1:Artist", tag.artist, G_TYPE_CHAR, READ | WRITE, 1024 }, { "ID3V1:Song", tag.title, G_TYPE_CHAR, READ | WRITE, 1024 }, { "ID3V1:Album", tag.album, G_TYPE_CHAR, READ | WRITE, 1024 }, { "ID3V1:Track", tag.track, G_TYPE_CHAR, READ | WRITE, 20 }, { "ID3V1:Year", tag.year, G_TYPE_CHAR, READ | WRITE, 5 }, { "ID3V1:Genre", tag.genre, G_TYPE_CHAR, READ | WRITE, 512 }, { "ID3V1:Comment", tag.comment, G_TYPE_CHAR, READ | WRITE, 1024 }, { "ID3V1:Size", &tag.size, G_TYPE_INT, READ, 4 }, { NULL, NULL, 0, 0 } }; /****************************************************************************** * Plugin constructor/destructor. ******************************************************************************/ /* Purpose: Plugin initializer. */ gint plugin_init(CantusHash *pplugindata) { #ifdef _DEBUG_ printf("id3v1(): Hello, I am the ID3V1 plugin's initializer.\n"); #endif plugindata = pplugindata; cantushash_set_char(plugindata, "Plugin:Name", PLUGINNAME); cantushash_set_char(plugindata, "Plugin:Label", PLUGINLABEL); cantushash_set_char(plugindata, "Plugin:Description", PLUGINDESCR); cantushash_set_int(plugindata, "Plugin:MajorVersion", MAJVERSION); cantushash_set_int(plugindata, "Plugin:MinorVersion", MINVERSION); cantushash_set_int(plugindata, "Plugin:CompatibilityLevel", COMPATLEVEL); cantushash_set_pointer(plugindata, "Plugin:Pattern", pattern); memset(&tag, 0, sizeof(Tag)); return 0; } /* Purpose: Plugin destructor. */ gint plugin_destroy(void) { #ifdef _DEBUG_ printf("id3v1(): Hello, I am the ID3V1 plugin's destructor.\n"); #endif return 0; } /* Purpose: Returns TRUE if the plugin is responsible for handling this * filetype, otherwise FALSE. */ gboolean plugin_handles(const gchar *filename) { #ifdef _DEBUG_ printf("id3v1(): Hello, I am the ID3V1 plugin's plugin_handles() func.\n"); #endif return TRUE; } /****************************************************************************** * Plugin input/output functions. ******************************************************************************/ /* Purpose: Will be called to read a file's information into a hash. * Returns an errorcode < 0, or 0. */ gint plugin_read(const gchar *filename, CantusHash *info) { #ifdef _DEBUG_ printf("id3v1(): Hello, I am the ID3V1 plugin's read() function.\n"); #endif // Read the tag. int err = get_id3v1_tag(&tag, filename); if (err == 1) // Fatal error. return 1; if (err != 0) // Not so fatal errors. return 0; #ifdef _DEBUG_ printf("id3v1(): read(): Successfully read %s\n", filename); #endif // Mark the tag as "unchanged". cantushash_set_bool(info, "ID3V1:Changed", FALSE); // Store it in the hash. int i = -1; while (pairs[++i].name) { if (pairs[i].action & READ != READ) continue; #ifdef _DEBUG_ printf("id3v1(): read(): Handling %s/%s\n", pairs[i].name, pairs[i].value); #endif switch (pairs[i].type) { case G_TYPE_CHAR: cantushash_set_char(info, pairs[i].name, (const gchar*)pairs[i].value); break; case G_TYPE_INT: cantushash_set_int(info, pairs[i].name, *(int*)pairs[i].value); break; default: g_assert_not_reached(); } } return 0; } /* Purpose: Will be called to write a file's information from a hash to the * filesystem. */ gint plugin_write(const gchar *filename, CantusHash *info) { #ifdef _DEBUG_ printf("id3v1(): plugin_write(): Called.\n"); #endif const gchar *field = NULL; // Unchanged? Then return. if (!cantushash_get_bool(info, "ID3V1:Changed")) return 0; // Copy the fields from the hash into the tag struct. memset(&tag, 0, sizeof(Tag)); int i = -1; while (pairs[++i].name) { if (pairs[i].action & WRITE != WRITE) continue; switch (pairs[i].type) { case G_TYPE_CHAR: field = cantushash_get_char(info, pairs[i].name); if (field) strncpy((gchar*)pairs[i].value, field, pairs[i].length); break; case G_TYPE_INT: *(int*)(pairs[i].value) = cantushash_get_int(info, pairs[i].name); break; default: g_assert_not_reached(); } } // Write the tag. return(set_id3v1_tag(&tag, filename) == 1 ? 1 : 0); } /****************************************************************************** * Plugin GUI functions. ******************************************************************************/ /* Returns the widget tree to show as edit-area. * NULL as a return value is forbidden! * If this function returns NULL, the plugin will be deactivated. */ GtkWidget *plugin_get_uiwidget(gboolean vertical) { TagEditor *tageditor = new TagEditor(plugindata); return tageditor->editarea_build(vertical); } #if defined( __cplusplus ) } #endif