Changeset 456 for bmp-musepack
- Timestamp:
- 11/07/09 23:31:32 (15 years ago)
- Location:
- bmp-musepack/trunk
- Files:
-
- 1 added
- 4 deleted
- 3 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
bmp-musepack/trunk/COPYING
r34 r456 1 Copyright (c) 2005 , The Musepack Development Team1 Copyright (c) 2005-2009, The Musepack Development Team 2 2 All rights reserved. 3 3 -
bmp-musepack/trunk/ChangeLog
r34 r456 1 1.3 2 Changes for libmpcdec 1.3.0 (sv8 support) 3 Changes for Audacious 2.1.0 4 Moved to cmake build system 5 1 6 1.2 2 7 General code refactoring … … 7 12 Safer multithreading 8 13 Updated for libmpcdec-1.2 9 14 10 15 1.1.2 11 16 port to new C libmusepack 12 17 13 18 1.1 14 19 Autotools building process 15 20 %d now display full date tag 16 21 17 1.1-alpha10 22 1.1-alpha10 18 23 Equalizer works now 19 24 Fixed a small Bug with skipping broken tracks … … 45 50 fixed tag reading 46 51 47 1.1-alpha: 52 1.1-alpha: 48 53 rewrite from scratch using musepack lib -
bmp-musepack/trunk/INSTALL
r34 r456 1 Bmp-musepack plugin1 Audacious-musepack plugin 2 2 Required: 3 3 Taglib headers and libs >= 1.4 4 4 GTK-2.0 headers and libs 5 Bmp-0.9.7headers and binaries6 libmpcdec >= 1. 25 Audacious-2.1.0 headers and binaries 6 libmpcdec >= 1.3.0 7 7 To install: 8 run "./configure && make" as user 9 run "make install" as root 8 mkdir build 9 cd build 10 cmake .. 11 make 12 make install -
bmp-musepack/trunk/libmpc.cpp
r455 r456 1 1 /* 2 * Copyright (c) 2005 , The Musepack Development Team2 * Copyright (c) 2005-2009, The Musepack Development Team 3 3 * All rights reserved. 4 4 * … … 33 33 */ 34 34 35 35 36 #include "libmpc.h" 36 37 37 #define FORCED_THREAD_STACKSIZE 1024 * 1000 38 38 #define REMOVE_NONEXISTANT_TAG(x) if (!*x) { x = NULL; } 39 #define VERSION "1.3" 40 #define PACKAGE "aud_mpc" 39 41 40 42 using TagLib::MPC::File; … … 43 45 using TagLib::APE::ItemListMap; 44 46 45 InputPlugin MpcPlugin = {46 NULL, //File Handle FILE* handle47 NULL, //Filename char* filename48 NULL, //Name of Plugin char* filename49 mpcOpenPlugin, //Open Plugin [CALLBACK]50 mpcAboutBox, //Show About box [CALLBACK]51 mpcConfigBox, //Show Configure box [CALLBACK]52 mpcIsOurFile, //Check if it's our file [CALLBACK]53 NULL, //Scan the directory [UNUSED]54 mpcPlay, //Play [CALLBACK]55 mpcStop, //Stop [CALLBACK]56 mpcPause, //Pause [CALLBACK]57 mpcSeek, //Seek [CALLBACK]58 mpcSetEq, //Set EQ [CALLBACK]59 mpcGetTime, //Get Time [CALLBACK]60 NULL, //Get Volume [UNUSED]61 NULL, //Set Volume [UNUSED]62 mpcClosePlugin, //Close Plugin [CALLBACK]63 NULL, //Obsolete [UNUSED]64 NULL, //Visual plugins add_vis_pcm(int time, AFormat fmt, int nch, int length, void *ptr)65 NULL, //Set Info Settings set_info(char *title, int length, int rate, int freq, int nch)66 NULL, //set Info Text set_info_text(char* text)67 mpcGetSongInfo, //Get Title String callback [CALLBACK]68 mpcFileInfoBox, //Show File Info Box [CALLBACK]69 NULL, //Output Plugin Handle OutputPlugin output70 };71 72 extern "C"73 InputPlugin* get_iplugin_info()74 {75 MpcPlugin.description = g_strdup_printf("Musepack Audio Plugin %s", VERSION);76 return &MpcPlugin;77 }78 79 47 static PluginConfig pluginConfig = {0}; 80 48 static Widgets widgets = {0}; … … 82 50 static TrackInfo track = {0}; 83 51 84 static pthread_t threadHandle; 85 static pthread_attr_t threadAttr; 86 static pthread_mutex_t threadMutex; 87 static pthread_mutexattr_t threadMutexAttr; 52 static GThread *threadHandle; 53 static GStaticMutex threadMutex = G_STATIC_MUTEX_INIT; 54 55 /* 56 * VFS callback implementation, adapted from mpc_reader.c. 57 * This _IS_ very sick, but it works. -nenolod 58 */ 59 static mpc_int32_t 60 aud_vfs_fread_impl(mpc_reader *d, void *ptr, mpc_int32_t size) 61 { 62 VFSFile *file = (VFSFile *) d->data; 63 64 return (mpc_int32_t) aud_vfs_fread(ptr, 1, size, file); 65 } 66 67 static mpc_bool_t 68 aud_vfs_fseek_impl(mpc_reader *d, mpc_int32_t offset) 69 { 70 VFSFile *file = (VFSFile *) d->data; 71 72 return d->canseek(d) ? aud_vfs_fseek(file, offset, SEEK_SET) == 0 : FALSE; 73 } 74 75 static mpc_int32_t 76 aud_vfs_ftell_impl(mpc_reader *d) 77 { 78 VFSFile *file = (VFSFile *) d->data; 79 80 return aud_vfs_ftell(file); 81 } 82 83 static mpc_int32_t 84 aud_vfs_getsize_impl(mpc_reader *d) 85 { 86 int f_pos, f_size; 87 VFSFile *file = (VFSFile *) d->data; 88 89 f_pos = aud_vfs_ftell(file); 90 aud_vfs_fseek(file, 0, SEEK_END); 91 f_size = aud_vfs_ftell(file); 92 aud_vfs_fseek(file, f_pos, SEEK_SET); 93 94 return f_size; 95 } 96 97 static mpc_bool_t 98 aud_vfs_canseek_impl(mpc_reader *d) 99 { 100 return TRUE; // FIXME : can we really always seek ? 101 } 102 103 /* 104 * This sets up an mpc_reader object to read from VFS instead of libc. 105 * Essentially, we use this instead of the normal constructor. 106 * - nenolod 107 */ 108 void 109 mpc_reader_setup_file_vfs(mpc_reader *p_reader, VFSFile *input) 110 { 111 p_reader->seek = aud_vfs_fseek_impl; 112 p_reader->read = aud_vfs_fread_impl; 113 p_reader->tell = aud_vfs_ftell_impl; 114 p_reader->get_size = aud_vfs_getsize_impl; 115 p_reader->canseek = aud_vfs_canseek_impl; 116 p_reader->data = input; // no worries, it gets cast back -nenolod 117 aud_vfs_fseek(input, 0, SEEK_SET); 118 } 88 119 89 120 static void mpcOpenPlugin() 90 121 { 91 pthread_mutexattr_init(&threadMutexAttr); 92 pthread_mutex_init(&threadMutex, &threadMutexAttr); 93 pthread_attr_init(&threadAttr); 94 pthread_attr_setstacksize(&threadAttr, FORCED_THREAD_STACKSIZE); 95 96 ConfigDb *cfg; 97 cfg = bmp_cfg_db_open(); 98 bmp_cfg_db_get_bool(cfg, "musepack", "clipPrevention", &pluginConfig.clipPrevention); 99 bmp_cfg_db_get_bool(cfg, "musepack", "albumGain", &pluginConfig.albumGain); 100 bmp_cfg_db_get_bool(cfg, "musepack", "dynamicBitrate", &pluginConfig.dynamicBitrate); 101 bmp_cfg_db_get_bool(cfg, "musepack", "replaygain", &pluginConfig.replaygain); 102 bmp_cfg_db_close(cfg); 122 mcs_handle_t *cfg; 123 cfg = aud_cfg_db_open(); 124 aud_cfg_db_get_bool(cfg, "musepack", "clipPrevention", &pluginConfig.clipPrevention); 125 aud_cfg_db_get_bool(cfg, "musepack", "albumGain", &pluginConfig.albumGain); 126 aud_cfg_db_get_bool(cfg, "musepack", "dynamicBitrate", &pluginConfig.dynamicBitrate); 127 aud_cfg_db_get_bool(cfg, "musepack", "replaygain", &pluginConfig.replaygain); 128 aud_cfg_db_close(cfg); 103 129 } 104 130 … … 110 136 else 111 137 { 112 char* titleText = g_strdup_printf( "Musepack Decoder Plugin %s", VERSION);113 const char* contentText = "Plugin code by\nBenoit Amiaux\nMartin Spuler\nKuniklo\n\nGet latest version at http://musepack.net\n";114 const char* buttonText = "Nevermind";115 aboutBox = xmms_show_message(titleText, contentText, buttonText, FALSE, NULL, NULL);138 char* titleText = g_strdup_printf(_("Musepack Decoder Plugin %s"), VERSION); 139 const char* contentText = _("Plugin code by\nBenoit Amiaux\nMartin Spuler\nKuniklo\nNicolas Botti\n\nGet latest version at http://musepack.net\n"); 140 const char* buttonText = _("Nevermind"); 141 aboutBox = audacious_info_dialog(titleText, contentText, buttonText, FALSE, NULL, NULL); 116 142 widgets.aboutBox = aboutBox; 117 gtk_signal_connect(GTK_OBJECT(aboutBox), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &widgets.aboutBox); 118 } 143 g_signal_connect(G_OBJECT(aboutBox), "destroy", G_CALLBACK(gtk_widget_destroyed), &widgets.aboutBox); 144 } 145 } 146 147 static void toggleSwitch(GtkWidget* p_Widget, gpointer p_Data) 148 { 149 gtk_widget_set_sensitive(GTK_WIDGET(p_Data), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_Widget))); 119 150 } 120 151 … … 129 160 gtk_window_set_type_hint(GTK_WINDOW(configBox), GDK_WINDOW_TYPE_HINT_DIALOG); 130 161 widgets.configBox = configBox; 131 g tk_signal_connect(GTK_OBJECT(configBox), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &widgets.configBox);132 gtk_window_set_title(GTK_WINDOW(configBox), "Musepack Decoder Configuration");133 gtk_window_set_ policy(GTK_WINDOW(configBox), FALSE, FALSE, FALSE);134 gtk_container_ border_width(GTK_CONTAINER(configBox), 10);162 g_signal_connect(G_OBJECT(configBox), "destroy", G_CALLBACK(gtk_widget_destroyed), &widgets.configBox); 163 gtk_window_set_title(GTK_WINDOW(configBox), _("Musepack Decoder Configuration")); 164 gtk_window_set_resizable(GTK_WINDOW(configBox), FALSE); 165 gtk_container_set_border_width(GTK_CONTAINER(configBox), 10); 135 166 136 167 GtkWidget* notebook = gtk_notebook_new(); … … 140 171 141 172 //General Settings Tab 142 GtkWidget* generalSet = gtk_frame_new( "General Settings");143 gtk_container_ border_width(GTK_CONTAINER(generalSet), 5);173 GtkWidget* generalSet = gtk_frame_new(_("General Settings")); 174 gtk_container_set_border_width(GTK_CONTAINER(generalSet), 5); 144 175 145 176 GtkWidget* gSvbox = gtk_vbox_new(FALSE, 10); 146 gtk_container_ border_width(GTK_CONTAINER(gSvbox), 5);177 gtk_container_set_border_width(GTK_CONTAINER(gSvbox), 5); 147 178 gtk_container_add(GTK_CONTAINER(generalSet), gSvbox); 148 179 149 GtkWidget* bitrateCheck = gtk_check_button_new_with_label( "Enable Dynamic Bitrate Display");180 GtkWidget* bitrateCheck = gtk_check_button_new_with_label(_("Enable Dynamic Bitrate Display")); 150 181 widgets.bitrateCheck = bitrateCheck; 151 182 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bitrateCheck), pluginConfig.dynamicBitrate); 152 183 gtk_box_pack_start(GTK_BOX(gSvbox), bitrateCheck, FALSE, FALSE, 0); 153 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), generalSet, gtk_label_new( "Plugin"));184 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), generalSet, gtk_label_new(_("Plugin"))); 154 185 155 186 //ReplayGain Settings Tab 156 GtkWidget* replaygainSet = gtk_frame_new( "ReplayGain Settings");157 gtk_container_ border_width(GTK_CONTAINER(replaygainSet), 5);187 GtkWidget* replaygainSet = gtk_frame_new(_("ReplayGain Settings")); 188 gtk_container_set_border_width(GTK_CONTAINER(replaygainSet), 5); 158 189 159 190 GtkWidget* rSVbox = gtk_vbox_new(FALSE, 10); 160 gtk_container_ border_width(GTK_CONTAINER(rSVbox), 5);191 gtk_container_set_border_width(GTK_CONTAINER(rSVbox), 5); 161 192 gtk_container_add(GTK_CONTAINER(replaygainSet), rSVbox); 162 193 163 GtkWidget* clippingCheck = gtk_check_button_new_with_label( "Enable Clipping Prevention");194 GtkWidget* clippingCheck = gtk_check_button_new_with_label(_("Enable Clipping Prevention")); 164 195 widgets.clippingCheck = clippingCheck; 165 196 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(clippingCheck), pluginConfig.clipPrevention); 166 197 gtk_box_pack_start(GTK_BOX(rSVbox), clippingCheck, FALSE, FALSE, 0); 167 198 168 GtkWidget* replaygainCheck = gtk_check_button_new_with_label( "Enable ReplayGain");199 GtkWidget* replaygainCheck = gtk_check_button_new_with_label(_("Enable ReplayGain")); 169 200 widgets.replaygainCheck = replaygainCheck; 170 201 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(replaygainCheck), pluginConfig.replaygain); 171 202 gtk_box_pack_start(GTK_BOX(rSVbox), replaygainCheck, FALSE, FALSE, 0); 172 203 173 GtkWidget* replaygainType = gtk_frame_new( "ReplayGain Type");204 GtkWidget* replaygainType = gtk_frame_new(_("ReplayGain Type")); 174 205 gtk_box_pack_start(GTK_BOX(rSVbox), replaygainType, FALSE, FALSE, 0); 175 g tk_signal_connect(GTK_OBJECT(replaygainCheck), "toggled", GTK_SIGNAL_FUNC(toggleSwitch), replaygainType);206 g_signal_connect(G_OBJECT(replaygainCheck), "toggled", G_CALLBACK(toggleSwitch), replaygainType); 176 207 177 208 GtkWidget* rgVbox = gtk_vbox_new(FALSE, 5); … … 179 210 gtk_container_add(GTK_CONTAINER(replaygainType), rgVbox); 180 211 181 GtkWidget* trackCheck = gtk_radio_button_new_with_label(NULL, "Use Track Gain");212 GtkWidget* trackCheck = gtk_radio_button_new_with_label(NULL, _("Use Track Gain")); 182 213 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(trackCheck), !pluginConfig.albumGain); 183 214 gtk_box_pack_start(GTK_BOX(rgVbox), trackCheck, FALSE, FALSE, 0); 184 215 185 GtkWidget* albumCheck = gtk_radio_button_new_with_label(gtk_radio_button_g roup(GTK_RADIO_BUTTON(trackCheck)), "Use Album Gain");216 GtkWidget* albumCheck = gtk_radio_button_new_with_label(gtk_radio_button_get_group(GTK_RADIO_BUTTON(trackCheck)), _("Use Album Gain")); 186 217 widgets.albumCheck = albumCheck; 187 218 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(albumCheck), pluginConfig.albumGain); 188 219 gtk_box_pack_start(GTK_BOX(rgVbox), albumCheck, FALSE, FALSE, 0); 189 220 gtk_widget_set_sensitive(replaygainType, pluginConfig.replaygain); 190 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), replaygainSet, gtk_label_new( "ReplayGain"));221 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), replaygainSet, gtk_label_new(_("ReplayGain"))); 191 222 192 223 //Buttons 193 224 GtkWidget* buttonBox = gtk_hbutton_box_new(); 194 225 gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END); 195 gtk_b utton_box_set_spacing(GTK_BUTTON_BOX(buttonBox), 5);226 gtk_box_set_spacing(GTK_BOX(buttonBox), 5); 196 227 gtk_box_pack_start(GTK_BOX(vbox), buttonBox, FALSE, FALSE, 0); 197 228 198 GtkWidget* okButton = gtk_button_new_with_label( "Ok");199 g tk_signal_connect(GTK_OBJECT(okButton), "clicked", GTK_SIGNAL_FUNC(saveConfigBox), NULL);229 GtkWidget* okButton = gtk_button_new_with_label(_("Ok")); 230 g_signal_connect(G_OBJECT(okButton), "clicked", G_CALLBACK(saveConfigBox), NULL); 200 231 GTK_WIDGET_SET_FLAGS(okButton, GTK_CAN_DEFAULT); 201 232 gtk_box_pack_start(GTK_BOX(buttonBox), okButton, TRUE, TRUE, 0); 202 233 203 GtkWidget* cancelButton = gtk_button_new_with_label( "Cancel");204 g tk_signal_connect_object(GTK_OBJECT(cancelButton), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(widgets.configBox));234 GtkWidget* cancelButton = gtk_button_new_with_label(_("Cancel")); 235 g_signal_connect_swapped(G_OBJECT(cancelButton), "clicked", G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(widgets.configBox)); 205 236 GTK_WIDGET_SET_FLAGS(cancelButton, GTK_CAN_DEFAULT); 206 237 gtk_widget_grab_default(cancelButton); … … 211 242 } 212 243 213 static void toggleSwitch(GtkWidget* p_Widget, gpointer p_Data)214 {215 gtk_widget_set_sensitive(GTK_WIDGET(p_Data), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_Widget)));216 }217 218 244 static void saveConfigBox(GtkWidget* p_Widget, gpointer p_Data) 219 245 { 220 ConfigDb* cfg;246 mcs_handle_t* cfg; 221 247 GtkToggleButton* tb; 222 248 … … 230 256 pluginConfig.albumGain = gtk_toggle_button_get_active(tb); 231 257 232 cfg = bmp_cfg_db_open();233 234 bmp_cfg_db_set_bool(cfg, "musepack", "clipPrevention", pluginConfig.clipPrevention);235 bmp_cfg_db_set_bool(cfg, "musepack", "albumGain", pluginConfig.albumGain);236 bmp_cfg_db_set_bool(cfg, "musepack", "dynamicBitrate", pluginConfig.dynamicBitrate);237 bmp_cfg_db_set_bool(cfg, "musepack", "replaygain", pluginConfig.replaygain);238 239 bmp_cfg_db_close(cfg);258 cfg = aud_cfg_db_open(); 259 260 aud_cfg_db_set_bool(cfg, "musepack", "clipPrevention", pluginConfig.clipPrevention); 261 aud_cfg_db_set_bool(cfg, "musepack", "albumGain", pluginConfig.albumGain); 262 aud_cfg_db_set_bool(cfg, "musepack", "dynamicBitrate", pluginConfig.dynamicBitrate); 263 aud_cfg_db_set_bool(cfg, "musepack", "replaygain", pluginConfig.replaygain); 264 265 aud_cfg_db_close(cfg); 240 266 241 267 gtk_widget_destroy (widgets.configBox); 242 268 } 243 269 244 static int mpcIsOurFile(char* p_Filename) 245 { 246 char* ext; 247 ext = strrchr(p_Filename, '.'); 248 if(ext) 249 return !(strcasecmp(ext, ".mpc") && strcasecmp(ext, ".mpp") && strcasecmp(ext, ".mp+")); 250 return FALSE; 251 } 252 253 static void mpcPlay(char* p_Filename) 270 static gint mpcIsOurFD(gchar* p_Filename, VFSFile* file) 271 { 272 gchar magic[4]; 273 aud_vfs_fread(magic, 1, 4, file); 274 if (memcmp(magic, "MP+", 3) == 0) 275 return 1; 276 if (memcmp(magic, "MPCK", 4) == 0) 277 return 1; 278 return 0; 279 } 280 281 static void mpcPlay(InputPlayback *data) 254 282 { 255 283 mpcDecoder.offset = -1; … … 257 285 mpcDecoder.isOutput = false; 258 286 mpcDecoder.isPause = false; 259 pthread_create(&threadHandle, &threadAttr, decodeStream, (void *) g_strdup(p_Filename)); 260 } 261 262 static void mpcStop() 263 { 264 setAlive(false); 287 threadHandle = g_thread_self(); 288 decodeStream(data); 289 } 290 291 static void mpcStop(InputPlayback *data) 292 { 293 mpcDecoder.isAlive = false; 265 294 if (threadHandle) 266 295 { 267 pthread_join(threadHandle, NULL);296 g_thread_join(threadHandle); 268 297 if (mpcDecoder.isOutput) 269 298 { 270 MpcPlugin.output->buffer_free();271 MpcPlugin.output->close_audio();299 data->output->buffer_free(); 300 data->output->close_audio(); 272 301 mpcDecoder.isOutput = false; 273 302 } … … 275 304 } 276 305 277 static void mpcPause(short p_Pause) 306 inline static void lockAcquire() 307 { 308 g_static_mutex_lock(&threadMutex); 309 } 310 311 inline static void lockRelease() 312 { 313 g_static_mutex_unlock(&threadMutex); 314 } 315 316 static void mpcPause(InputPlayback *data, short p_Pause) 278 317 { 279 318 lockAcquire(); 280 319 mpcDecoder.isPause = p_Pause; 281 MpcPlugin.output->pause(p_Pause);320 data->output->pause(p_Pause); 282 321 lockRelease(); 283 322 } 284 323 285 static void mpcSeek (int p_Offset)324 static void mpcSeekm(InputPlayback *data, gulong ms_offset) 286 325 { 287 326 lockAcquire(); 288 mpcDecoder.offset = static_cast<double> (p_Offset); 289 MpcPlugin.output->flush(1000 * p_Offset); 327 mpcDecoder.offset = ms_offset; 290 328 lockRelease(); 291 329 } 292 330 293 static void mpcSetEq(int on, float preamp, float* eq) 294 { 295 pluginConfig.isEq = static_cast<bool> (on); 296 init_iir(on, preamp, eq); 297 } 298 299 static int mpcGetTime() 300 { 301 if(!isAlive()) 302 return -1; 303 return MpcPlugin.output->output_time(); 304 } 305 306 static void mpcClosePlugin() 307 { 308 pthread_mutex_destroy(&threadMutex); 309 pthread_mutexattr_destroy(&threadMutexAttr); 310 pthread_attr_destroy(&threadAttr); 311 } 312 313 static void mpcGetSongInfo(char* p_Filename, char** p_Title, int* p_Length) 314 { 315 mpc_reader reader; 316 mpc_demux * demux; 317 if (mpc_reader_init_stdio(&reader, p_Filename) == MPC_STATUS_OK && (demux = mpc_demux_init(&reader))) { 318 MpcInfo tags = getTags(p_Filename); 319 *p_Title = mpcGenerateTitle(tags, p_Filename); 320 freeTags(tags); 321 mpc_streaminfo info; 322 mpc_demux_get_info(demux, &info); 323 *p_Length = static_cast<int> (1000 * mpc_streaminfo_get_length(&info)); 324 mpc_demux_exit(demux); 325 mpc_reader_exit_stdio(&reader); 326 } else { 327 char* temp = g_strdup_printf("[xmms-musepack] mpcGetSongInfo is unable to open %s\n", p_Filename); 328 perror(temp); 329 free(temp); 330 } 331 } 332 333 static void freeTags(MpcInfo& tags) 334 { 335 free(tags.title); 336 free(tags.artist); 337 free(tags.album); 338 free(tags.comment); 339 free(tags.genre); 340 free(tags.date); 341 } 342 343 static MpcInfo getTags(const char* p_Filename) 344 { 345 File oFile(p_Filename, false); 331 static void mpcSeek(InputPlayback *data, int p_Offset) 332 { 333 mpcSeekm(data, 1000 * p_Offset); 334 } 335 336 static MpcInfo getTags(const gchar* p_Filename) 337 { 338 gchar *pRealFilename = g_filename_from_uri(p_Filename, NULL, NULL); 339 File oFile(pRealFilename ? pRealFilename : p_Filename, false); 340 g_free(pRealFilename); 346 341 Tag* poTag = oFile.tag(); 347 342 MpcInfo tags = {0}; 348 343 tags.title = g_strdup(poTag->title().toCString(true)); 344 REMOVE_NONEXISTANT_TAG(tags.title); 349 345 tags.artist = g_strdup(poTag->artist().toCString(true)); 346 REMOVE_NONEXISTANT_TAG(tags.artist); 350 347 tags.album = g_strdup(poTag->album().toCString(true)); 348 REMOVE_NONEXISTANT_TAG(tags.album); 351 349 tags.genre = g_strdup(poTag->genre().toCString(true)); 350 REMOVE_NONEXISTANT_TAG(tags.genre); 352 351 tags.comment = g_strdup(poTag->comment().toCString(true)); 352 REMOVE_NONEXISTANT_TAG(tags.comment); 353 353 tags.year = poTag->year(); 354 354 tags.track = poTag->track(); 355 #if 0 355 356 TagLib::APE::Tag* ape = oFile.APETag(false); 356 357 if(ape) … … 366 367 } 367 368 } 369 #endif 368 370 return tags; 371 } 372 373 static void removeTags(GtkWidget * w, gpointer data) 374 { 375 File oFile(gtk_entry_get_text(GTK_ENTRY(widgets.fileEntry))); 376 oFile.remove(); 377 oFile.save(); 378 closeInfoBox(NULL, NULL); 379 } 380 381 static void saveTags(GtkWidget* w, gpointer data) 382 { 383 File oFile(gtk_entry_get_text(GTK_ENTRY(widgets.fileEntry))); 384 Tag* poTag = oFile.tag(); 385 386 gchar* cAlbum = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.albumEntry))); 387 gchar* cArtist = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.artistEntry))); 388 gchar* cTitle = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.titleEntry))); 389 gchar* cGenre = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.genreEntry))); 390 gchar* cComment = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.commentEntry))); 391 392 const String album = String(cAlbum, TagLib::String::UTF8); 393 const String artist = String(cArtist, TagLib::String::UTF8); 394 const String title = String(cTitle, TagLib::String::UTF8); 395 const String genre = String(cGenre, TagLib::String::UTF8); 396 const String comment = String(cComment, TagLib::String::UTF8); 397 398 poTag->setAlbum(album); 399 poTag->setArtist(artist); 400 poTag->setTitle(title); 401 poTag->setGenre(genre); 402 poTag->setComment(comment); 403 poTag->setYear(atoi(gtk_entry_get_text(GTK_ENTRY(widgets.yearEntry)))); 404 poTag->setTrack(atoi(gtk_entry_get_text(GTK_ENTRY(widgets.trackEntry)))); 405 406 g_free(cAlbum); 407 g_free(cArtist); 408 g_free(cTitle); 409 g_free(cGenre); 410 g_free(cComment); 411 412 oFile.save(); 413 closeInfoBox(NULL, NULL); 414 } 415 416 static void freeTags(MpcInfo& tags) 417 { 418 g_free(tags.title); 419 g_free(tags.artist); 420 g_free(tags.album); 421 g_free(tags.comment); 422 g_free(tags.genre); 423 g_free(tags.date); 424 } 425 426 static Tuple *mpcGetTuple(gchar* p_Filename, VFSFile *input) 427 { 428 Tuple *tuple = 0; 429 bool close_input = false; 430 431 if (input == 0) { 432 input = aud_vfs_fopen(p_Filename, "rb"); 433 if (input == 0) { 434 gchar* temp = g_strdup_printf("[xmms-musepack] mpcGetTuple is unable to open %s\n", p_Filename); 435 perror(temp); 436 g_free(temp); 437 return 0; 438 } 439 close_input = true; 440 } 441 442 tuple = aud_tuple_new_from_filename(p_Filename); 443 444 mpc_streaminfo info; 445 mpc_reader reader; 446 mpc_reader_setup_file_vfs(&reader, input); 447 mpc_demux * demux = mpc_demux_init(&reader); 448 mpc_demux_get_info(demux, &info); 449 mpc_demux_exit(demux); 450 451 aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, static_cast<int> (1000 * mpc_streaminfo_get_length(&info))); 452 453 // gchar *scratch = g_strdup_printf("Musepack v%d (encoder %s)", info.stream_version, info.encoder); 454 // aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, scratch); 455 // g_free(scratch); 456 457 // scratch = g_strdup_printf("lossy (%s)", info.profile_name); 458 // aud_tuple_associate_string(tuple, FIELD_QUALITY, NULL, scratch); 459 // g_free(scratch); 460 461 aud_tuple_associate_int(tuple, FIELD_BITRATE, NULL, static_cast<int> (info.average_bitrate / 1000)); 462 463 MpcInfo tags = getTags(p_Filename); 464 465 // aud_tuple_associate_string(tuple, FIELD_DATE, NULL, tags.date); 466 // aud_tuple_associate_string(tuple, FIELD_TITLE, NULL, tags.title); 467 // aud_tuple_associate_string(tuple, FIELD_ARTIST, NULL, tags.artist); 468 // aud_tuple_associate_string(tuple, FIELD_ALBUM, NULL, tags.album); 469 // aud_tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, tags.track); 470 // aud_tuple_associate_int(tuple, FIELD_YEAR, NULL, tags.year); 471 // aud_tuple_associate_string(tuple, FIELD_GENRE, NULL, tags.genre); 472 // aud_tuple_associate_string(tuple, FIELD_COMMENT, NULL, tags.comment); 473 474 freeTags(tags); 475 476 if (close_input) 477 aud_vfs_fclose(input); 478 479 return tuple; 480 } 481 482 static Tuple *mpcProbeForTuple(gchar* p_Filename, VFSFile *input) 483 { 484 return mpcGetTuple(p_Filename, input); 485 } 486 487 static Tuple *mpcGetSongTuple(gchar* p_Filename) 488 { 489 return mpcGetTuple(p_Filename, 0); 490 } 491 492 static char* mpcGenerateTitle(const MpcInfo& p_Tags, gchar* p_Filename) 493 { 494 Tuple* tuple = mpcGetSongTuple(p_Filename); 495 496 gchar* title = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); 497 498 aud_tuple_free((void *) tuple); 499 return title; 500 } 501 502 static void mpcGtkPrintLabel(GtkWidget* widget, const char* format,...) 503 { 504 va_list args; 505 506 va_start(args, format); 507 gchar* temp = g_strdup_vprintf(format, args); 508 va_end(args); 509 510 gtk_label_set_text(GTK_LABEL(widget), temp); 511 g_free(temp); 512 } 513 514 static GtkWidget* mpcGtkTagLabel(const char* p_Text, int a, int b, int c, int d, GtkWidget* p_Box) 515 { 516 GtkWidget* label = gtk_label_new(p_Text); 517 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); 518 gtk_table_attach(GTK_TABLE(p_Box), label, a, b, c, d, GTK_FILL, GTK_FILL, 5, 5); 519 return label; 520 } 521 522 static GtkWidget* mpcGtkTagEntry(int a, int b, int c, int d, int p_Size, GtkWidget* p_Box) 523 { 524 GtkWidget* entry; 525 entry = gtk_entry_new(); 526 if(p_Size) 527 gtk_entry_set_max_length(GTK_ENTRY(entry), p_Size); 528 529 gtk_table_attach(GTK_TABLE(p_Box), entry, a, b, c, d, 530 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND | GTK_SHRINK), 531 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND | GTK_SHRINK), 0, 5); 532 return entry; 533 } 534 535 static GtkWidget* mpcGtkLabel(GtkWidget* p_Box) 536 { 537 GtkWidget* label = gtk_label_new(""); 538 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); 539 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); 540 gtk_box_pack_start(GTK_BOX(p_Box), label, FALSE, FALSE, 0); 541 return label; 542 } 543 544 static GtkWidget* mpcGtkButton(const char* p_Text, GtkWidget* p_Box) 545 { 546 GtkWidget* button = gtk_button_new_with_label(p_Text); 547 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); 548 gtk_box_pack_start(GTK_BOX(p_Box), button, TRUE, TRUE, 0); 549 return button; 369 550 } 370 551 … … 380 561 gtk_window_set_type_hint(GTK_WINDOW(infoBox), GDK_WINDOW_TYPE_HINT_DIALOG); 381 562 widgets.infoBox = infoBox; 382 gtk_window_set_ policy(GTK_WINDOW(infoBox), FALSE, FALSE, FALSE);383 g tk_signal_connect(GTK_OBJECT(infoBox), "destroy", GTK_SIGNAL_FUNC(closeInfoBox), NULL);563 gtk_window_set_resizable(GTK_WINDOW(infoBox), FALSE); 564 g_signal_connect(G_OBJECT(infoBox), "destroy", G_CALLBACK(closeInfoBox), NULL); 384 565 gtk_container_set_border_width(GTK_CONTAINER(infoBox), 10); 385 566 … … 390 571 gtk_box_pack_start(GTK_BOX(iVbox), filenameHbox, FALSE, TRUE, 0); 391 572 392 GtkWidget* fileLabel = gtk_label_new( "Filename:");573 GtkWidget* fileLabel = gtk_label_new(_("Filename:")); 393 574 gtk_box_pack_start(GTK_BOX(filenameHbox), fileLabel, FALSE, TRUE, 0); 394 575 … … 405 586 406 587 //Tag labels 407 GtkWidget* tagFrame = gtk_frame_new( "Musepack Tag");588 GtkWidget* tagFrame = gtk_frame_new(_("Musepack Tag")); 408 589 gtk_box_pack_start(GTK_BOX(leftBox), tagFrame, FALSE, FALSE, 0); 409 590 gtk_widget_set_sensitive(tagFrame, TRUE); … … 413 594 gtk_container_add(GTK_CONTAINER(tagFrame), iTable); 414 595 415 mpcGtkTagLabel( "Title:", 0, 1, 0, 1, iTable);596 mpcGtkTagLabel(_("Title:"), 0, 1, 0, 1, iTable); 416 597 GtkWidget* titleEntry = mpcGtkTagEntry(1, 4, 0, 1, 0, iTable); 417 598 widgets.titleEntry = titleEntry; 418 599 419 mpcGtkTagLabel( "Artist:", 0, 1, 1, 2, iTable);600 mpcGtkTagLabel(_("Artist:"), 0, 1, 1, 2, iTable); 420 601 GtkWidget* artistEntry = mpcGtkTagEntry(1, 4, 1, 2, 0, iTable); 421 602 widgets.artistEntry = artistEntry; 422 603 423 mpcGtkTagLabel( "Album:", 0, 1, 2, 3, iTable);604 mpcGtkTagLabel(_("Album:"), 0, 1, 2, 3, iTable); 424 605 GtkWidget* albumEntry = mpcGtkTagEntry(1, 4, 2, 3, 0, iTable); 425 606 widgets.albumEntry = albumEntry; 426 607 427 mpcGtkTagLabel( "Comment:", 0, 1, 3, 4, iTable);608 mpcGtkTagLabel(_("Comment:"), 0, 1, 3, 4, iTable); 428 609 GtkWidget* commentEntry = mpcGtkTagEntry(1, 4, 3, 4, 0, iTable); 429 610 widgets.commentEntry = commentEntry; 430 611 431 mpcGtkTagLabel( "Year:", 0, 1, 4, 5, iTable);612 mpcGtkTagLabel(_("Year:"), 0, 1, 4, 5, iTable); 432 613 GtkWidget* yearEntry = mpcGtkTagEntry(1, 2, 4, 5, 4, iTable); 433 614 widgets.yearEntry = yearEntry; 434 gtk_widget_set_ usize(yearEntry, 4, -1);435 436 mpcGtkTagLabel( "Track:", 2, 3, 4, 5, iTable);615 gtk_widget_set_size_request(yearEntry, 4, -1); 616 617 mpcGtkTagLabel(_("Track:"), 2, 3, 4, 5, iTable); 437 618 GtkWidget* trackEntry = mpcGtkTagEntry(3, 4, 4, 5, 4, iTable); 438 619 widgets.trackEntry = trackEntry; 439 gtk_widget_set_ usize(trackEntry, 3, -1);440 441 mpcGtkTagLabel( "Genre:", 0, 1, 5, 6, iTable);620 gtk_widget_set_size_request(trackEntry, 3, -1); 621 622 mpcGtkTagLabel(_("Genre:"), 0, 1, 5, 6, iTable); 442 623 GtkWidget* genreEntry = mpcGtkTagEntry(1, 4, 5, 6, 0, iTable); 443 624 widgets.genreEntry = genreEntry; 444 gtk_widget_set_ usize(genreEntry, 20, -1);625 gtk_widget_set_size_request(genreEntry, 20, -1); 445 626 446 627 //Buttons 447 628 GtkWidget* buttonBox = gtk_hbutton_box_new(); 448 629 gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END); 449 gtk_b utton_box_set_spacing(GTK_BUTTON_BOX(buttonBox), 5);630 gtk_box_set_spacing(GTK_BOX(buttonBox), 5); 450 631 gtk_box_pack_start(GTK_BOX(leftBox), buttonBox, FALSE, FALSE, 0); 451 632 452 GtkWidget* saveButton = mpcGtkButton( "Save", buttonBox);453 g tk_signal_connect(GTK_OBJECT(saveButton), "clicked", GTK_SIGNAL_FUNC(saveTags), NULL);454 455 GtkWidget* removeButton = mpcGtkButton( "Remove Tag", buttonBox);456 g tk_signal_connect_object(GTK_OBJECT(removeButton), "clicked", GTK_SIGNAL_FUNC(removeTags), NULL);457 458 GtkWidget* cancelButton = mpcGtkButton( "Cancel", buttonBox);459 g tk_signal_connect_object(GTK_OBJECT(cancelButton), "clicked", GTK_SIGNAL_FUNC(closeInfoBox), NULL);633 GtkWidget* saveButton = mpcGtkButton(_("Save"), buttonBox); 634 g_signal_connect(G_OBJECT(saveButton), "clicked", G_CALLBACK(saveTags), NULL); 635 636 GtkWidget* removeButton = mpcGtkButton(_("Remove Tag"), buttonBox); 637 g_signal_connect_swapped(G_OBJECT(removeButton), "clicked", G_CALLBACK(removeTags), NULL); 638 639 GtkWidget* cancelButton = mpcGtkButton(_("Cancel"), buttonBox); 640 g_signal_connect_swapped(G_OBJECT(cancelButton), "clicked", G_CALLBACK(closeInfoBox), NULL); 460 641 gtk_widget_grab_default(cancelButton); 461 642 462 643 //File information 463 GtkWidget* infoFrame = gtk_frame_new( "Musepack Info");644 GtkWidget* infoFrame = gtk_frame_new(_("Musepack Info")); 464 645 gtk_box_pack_start(GTK_BOX(iHbox), infoFrame, FALSE, FALSE, 0); 465 646 … … 471 652 GtkWidget* streamLabel = mpcGtkLabel(infoVbox); 472 653 GtkWidget* encoderLabel = mpcGtkLabel(infoVbox); 473 654 GtkWidget* profileLabel = mpcGtkLabel(infoVbox); 474 655 GtkWidget* pnsLabel = mpcGtkLabel(infoVbox); 475 656 GtkWidget* gaplessLabel = mpcGtkLabel(infoVbox); … … 484 665 GtkWidget* albumGainLabel = mpcGtkLabel(infoVbox); 485 666 486 mpc_reader reader;487 mpc_demux * demux; 488 if (mpc_reader_init_stdio(&reader, p_Filename) == MPC_STATUS_OK && (demux = mpc_demux_init(&reader))){667 VFSFile *input = aud_vfs_fopen(p_Filename, "rb"); 668 if(input) 669 { 489 670 mpc_streaminfo info; 671 mpc_reader reader; 672 mpc_reader_setup_file_vfs(&reader, input); 673 mpc_demux * demux = mpc_demux_init(&reader); 490 674 mpc_demux_get_info(demux, &info); 491 492 int time = static_cast<int> (mpc_streaminfo_get_length(&info)); 493 int minutes = time / 60; 494 int seconds = time % 60; 495 496 mpcGtkPrintLabel(streamLabel, "Streamversion %d", info.stream_version); 497 mpcGtkPrintLabel(encoderLabel, "Encoder: \%s", info.encoder); 498 mpcGtkPrintLabel(profileLabel, "Profile: \%s (q=%0.2f)", info.profile_name, info.profile - 5); 499 mpcGtkPrintLabel(pnsLabel, "PNS: \%s", info.pns == 0xFF ? "unknow" : info.pns ? "on" : "off"); 500 mpcGtkPrintLabel(gaplessLabel, "Gapless: \%s", info.is_true_gapless ? "on" : "off"); 501 mpcGtkPrintLabel(bitrateLabel, "Average bitrate: \%6.1f kbps", info.average_bitrate * 1.e-3); 502 mpcGtkPrintLabel(rateLabel, "Samplerate: \%d Hz", info.sample_freq); 503 mpcGtkPrintLabel(channelsLabel, "Channels: \%d", info.channels); 504 mpcGtkPrintLabel(lengthLabel, "Length: \%d:\%.2d (%u samples)", minutes, seconds, (mpc_uint32_t)mpc_streaminfo_get_length_samples(&info)); 505 mpcGtkPrintLabel(fileSizeLabel, "File size: \%d Bytes", info.total_file_length); 506 mpcGtkPrintLabel(trackPeakLabel, "Track Peak: \%2.2f dB", info.peak_title / 256.); 507 mpcGtkPrintLabel(trackGainLabel, "Track Gain: \%2.2f dB", info.gain_title / 256.); 508 mpcGtkPrintLabel(albumPeakLabel, "Album Peak: \%2.2f dB", info.peak_album / 256.); 509 mpcGtkPrintLabel(albumGainLabel, "Album Gain: \%2.2f dB", info.gain_album / 256.); 675 mpc_demux_exit(demux); 676 677 gint time = static_cast<int> (mpc_streaminfo_get_length(&info)); 678 gint minutes = time / 60; 679 gint seconds = time % 60; 680 681 mpcGtkPrintLabel(streamLabel, _("Streamversion %d"), info.stream_version); 682 mpcGtkPrintLabel(encoderLabel, _("Encoder: \%s"), info.encoder); 683 mpcGtkPrintLabel(profileLabel, _("Profile: \%s (q=%0.2f)"), info.profile_name, info.profile - 5); 684 mpcGtkPrintLabel(pnsLabel, _("PNS: \%s"), info.pns == 0xFF ? _("unknow") : info.pns ? _("on") : _("off")); 685 mpcGtkPrintLabel(gaplessLabel, _("Gapless: \%s"), info.is_true_gapless ? _("on") : _("off")); 686 mpcGtkPrintLabel(bitrateLabel, _("Average bitrate: \%6.1f kbps"), info.average_bitrate * 1.e-3); 687 mpcGtkPrintLabel(rateLabel, _("Samplerate: \%d Hz"), info.sample_freq); 688 mpcGtkPrintLabel(channelsLabel, _("Channels: \%d"), info.channels); 689 mpcGtkPrintLabel(lengthLabel, _("Length: \%d:\%.2d (%u samples)"), minutes, seconds, (mpc_uint32_t)mpc_streaminfo_get_length_samples(&info)); 690 mpcGtkPrintLabel(fileSizeLabel, _("File size: \%d Bytes"), info.total_file_length); 691 mpcGtkPrintLabel(trackPeakLabel, _("Track Peak: \%2.2f dB"), info.peak_title / 256.); 692 mpcGtkPrintLabel(trackGainLabel, _("Track Gain: \%2.2f dB"), info.gain_title / 256.); 693 mpcGtkPrintLabel(albumPeakLabel, _("Album Peak: \%2.2f dB"), info.peak_album / 256.); 694 mpcGtkPrintLabel(albumGainLabel, _("Album Gain: \%2.2f dB"), info.gain_album / 256.); 510 695 511 696 MpcInfo tags = getTags(p_Filename); … … 515 700 gtk_entry_set_text(GTK_ENTRY(commentEntry), tags.comment); 516 701 gtk_entry_set_text(GTK_ENTRY(genreEntry), tags.genre); 517 char* entry = g_strdup_printf ("%d", tags.track);702 gchar* entry = g_strdup_printf ("%d", tags.track); 518 703 gtk_entry_set_text(GTK_ENTRY(trackEntry), entry); 519 free(entry);704 g_free(entry); 520 705 entry = g_strdup_printf ("%d", tags.year); 521 706 gtk_entry_set_text(GTK_ENTRY(yearEntry), entry); 522 free(entry);707 g_free(entry); 523 708 entry = g_filename_display_name(p_Filename); 524 709 gtk_entry_set_text(GTK_ENTRY(fileEntry), entry); 525 free(entry);710 g_free(entry); 526 711 freeTags(tags); 527 mpc_demux_exit(demux); 528 mpc_reader_exit_stdio(&reader); 712 aud_vfs_fclose(input); 529 713 } 530 714 else 531 715 { 532 char* temp = g_strdup_printf("[xmms-musepack] mpcFileInfoBox is unable to read tags from %s", p_Filename);716 gchar* temp = g_strdup_printf("[xmms-musepack] mpcFileInfoBox is unable to read tags from %s", p_Filename); 533 717 perror(temp); 534 free(temp);718 g_free(temp); 535 719 } 536 720 537 char* name = g_filename_display_basename(p_Filename);538 char* text = g_strdup_printf("File Info - %s", name);539 free(name);721 gchar* name = g_filename_display_basename(p_Filename); 722 gchar* text = g_strdup_printf(_("File Info - %s"), name); 723 g_free(name); 540 724 gtk_window_set_title(GTK_WINDOW(infoBox), text); 541 free(text);725 g_free(text); 542 726 543 727 gtk_widget_show_all(infoBox); 544 728 } 545 }546 547 static void mpcGtkPrintLabel(GtkWidget* widget, char* format,...)548 {549 va_list args;550 551 va_start(args, format);552 char* temp = g_strdup_vprintf(format, args);553 va_end(args);554 555 gtk_label_set_text(GTK_LABEL(widget), temp);556 free(temp);557 }558 559 static GtkWidget* mpcGtkTagLabel(char* p_Text, int a, int b, int c, int d, GtkWidget* p_Box)560 {561 GtkWidget* label = gtk_label_new(p_Text);562 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);563 gtk_table_attach(GTK_TABLE(p_Box), label, a, b, c, d, GTK_FILL, GTK_FILL, 5, 5);564 return label;565 }566 567 static GtkWidget* mpcGtkTagEntry(int a, int b, int c, int d, int p_Size, GtkWidget* p_Box)568 {569 GtkWidget* entry;570 if(p_Size == 0)571 entry = gtk_entry_new();572 else573 entry = gtk_entry_new_with_max_length(p_Size);574 gtk_table_attach(GTK_TABLE(p_Box), entry, a, b, c, d,575 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND | GTK_SHRINK),576 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND | GTK_SHRINK), 0, 5);577 return entry;578 }579 580 static GtkWidget* mpcGtkLabel(GtkWidget* p_Box)581 {582 GtkWidget* label = gtk_label_new("");583 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);584 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);585 gtk_box_pack_start(GTK_BOX(p_Box), label, FALSE, FALSE, 0);586 return label;587 }588 589 static GtkWidget* mpcGtkButton(char* p_Text, GtkWidget* p_Box)590 {591 GtkWidget* button = gtk_button_new_with_label(p_Text);592 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);593 gtk_box_pack_start(GTK_BOX(p_Box), button, TRUE, TRUE, 0);594 return button;595 }596 597 static void removeTags(GtkWidget * w, gpointer data)598 {599 File oFile(gtk_entry_get_text(GTK_ENTRY(widgets.fileEntry)));600 oFile.remove();601 oFile.save();602 closeInfoBox(NULL, NULL);603 }604 605 static void saveTags(GtkWidget* w, gpointer data)606 {607 File oFile(gtk_entry_get_text(GTK_ENTRY(widgets.fileEntry)));608 Tag* poTag = oFile.tag();609 610 char* cAlbum = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.albumEntry)));611 char* cArtist = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.artistEntry)));612 char* cTitle = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.titleEntry)));613 char* cGenre = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.genreEntry)));614 char* cComment = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.commentEntry)));615 616 const String album = String(cAlbum, TagLib::String::UTF8);617 const String artist = String(cArtist, TagLib::String::UTF8);618 const String title = String(cTitle, TagLib::String::UTF8);619 const String genre = String(cGenre, TagLib::String::UTF8);620 const String comment = String(cComment, TagLib::String::UTF8);621 622 poTag->setAlbum(album);623 poTag->setArtist(artist);624 poTag->setTitle(title);625 poTag->setGenre(genre);626 poTag->setComment(comment);627 poTag->setYear(atoi(gtk_entry_get_text(GTK_ENTRY(widgets.yearEntry))));628 poTag->setTrack(atoi(gtk_entry_get_text(GTK_ENTRY(widgets.trackEntry))));629 630 free(cAlbum);631 free(cArtist);632 free(cTitle);633 free(cGenre);634 free(cComment);635 636 oFile.save();637 closeInfoBox(NULL, NULL);638 729 } 639 730 … … 644 735 } 645 736 646 static char* mpcGenerateTitle(const MpcInfo& p_Tags, const char* p_Filename) 647 { 648 TitleInput* input; 649 //From titlestring.h 650 input = g_new0(TitleInput, 1); 651 input->__size = XMMS_TITLEINPUT_SIZE; 652 input->__version = XMMS_TITLEINPUT_VERSION; 653 //end 654 655 input->file_name = g_filename_display_basename(p_Filename); 656 input->file_path = g_path_get_dirname(p_Filename); 657 input->file_ext = "mpc"; 658 input->date = g_strdup(p_Tags.date); 659 input->track_name = g_strdup(p_Tags.title); 660 input->performer = g_strdup(p_Tags.artist); 661 input->album_name = g_strdup(p_Tags.album); 662 input->track_number = p_Tags.track; 663 input->year = p_Tags.year; 664 input->genre = g_strdup(p_Tags.genre); 665 input->comment = g_strdup(p_Tags.comment); 666 667 char* title = xmms_get_titlestring (xmms_get_gentitle_format(), input); 668 if(!title) 669 title = g_strdup(input->file_name); 670 else if (!*title) 671 title = g_strdup(input->file_name); 672 673 free(input->file_name); 674 free(input->file_path); 675 free(input->track_name); 676 free(input->performer); 677 free(input->album_name); 678 free(input->genre); 679 free(input->comment); 680 free(input->date); 681 g_free(input); 682 return title; 683 } 684 685 static void* endThread(char* p_FileName, FILE* p_FileHandle, bool release) 686 { 687 free(p_FileName); 737 static void* endThread(gchar* p_FileName, VFSFile * p_FileHandle, bool release) 738 { 688 739 if(release) 689 740 lockRelease(); … … 691 742 { 692 743 perror(mpcDecoder.isError); 693 free(mpcDecoder.isError);744 g_free(mpcDecoder.isError); 694 745 mpcDecoder.isError = NULL; 695 746 } 696 setAlive(false);747 mpcDecoder.isAlive = false; 697 748 if(p_FileHandle) 698 fclose(p_FileHandle);749 aud_vfs_fclose(p_FileHandle); 699 750 if(track.display) 700 751 { 701 free(track.display);752 g_free(track.display); 702 753 track.display = NULL; 703 754 } 704 pthread_exit(NULL);705 755 return 0; 706 756 } 707 757 708 static void* decodeStream(void* data) 758 static int processBuffer(InputPlayback *playback, 759 MPC_SAMPLE_FORMAT* sampleBuffer, char* xmmsBuffer, mpc_demux* demux) 760 { 761 mpc_frame_info info; 762 763 info.buffer = sampleBuffer; 764 mpc_demux_decode(demux, &info); 765 766 if (info.bits == -1) return -1; // end of stream 767 768 copyBuffer(sampleBuffer, xmmsBuffer, info.samples * track.channels); 769 770 if (pluginConfig.dynamicBitrate) 771 { 772 track.bitrate = static_cast<int> (info.bits * track.sampleFreq / 1152); 773 } 774 775 playback->pass_audio(playback, FMT_S16_LE, track.channels, info.samples * 2 * track.channels, xmmsBuffer, NULL); 776 return info.samples; 777 } 778 779 static void* decodeStream(InputPlayback *data) 709 780 { 710 781 lockAcquire(); 711 const char* filename = static_cast<const char*> (data); 712 mpc_reader reader; 713 if (mpc_reader_init_stdio(&reader, filename) != MPC_STATUS_OK) { 782 gchar* filename = data->filename; 783 VFSFile *input = aud_vfs_fopen(filename, "rb"); 784 if (!input) 785 { 714 786 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to open %s", filename); 715 return endThread(filename, 0, true); 787 return endThread(filename, input, true); 788 } 789 790 mpc_reader reader; 791 mpc_reader_setup_file_vfs(&reader, input); 792 793 mpc_demux * demux = mpc_demux_init(&reader); 794 if (demux == 0) 795 { 796 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to initialize demuxer on %s", filename); 797 return endThread(filename, input, true); 716 798 } 717 799 718 mpc_demux * demux = 0; 719 demux = mpc_demux_init(&reader); 720 721 if ( demux == 0 ) { 722 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to initialize decoder on %s", filename); 723 mpc_reader_exit_stdio(&reader); 724 return endThread(filename, 0, true); 725 } 726 727 mpc_streaminfo info; 800 mpc_streaminfo info; 728 801 mpc_demux_get_info(demux, &info); 729 MpcInfo tags = getTags(filename); 730 track.display = mpcGenerateTitle(tags, filename); 731 track.length = static_cast<int> (1000 * mpc_streaminfo_get_length(&info)); 732 track.bitrate = static_cast<int> (info.average_bitrate); 733 track.sampleFreq = info.sample_freq; 734 track.channels = info.channels; 802 803 MpcInfo tags = getTags(filename); 804 track.display = mpcGenerateTitle(tags, filename); 805 track.length = static_cast<int> (1000 * mpc_streaminfo_get_length(&info)); 806 track.bitrate = static_cast<int> (info.average_bitrate); 807 track.sampleFreq = info.sample_freq; 808 track.channels = info.channels; 735 809 freeTags(tags); 736 810 737 MpcPlugin.set_info(track.display, track.length, track.bitrate, track.sampleFreq, track.channels); 738 739 setReplaygain(demux); 811 data->set_params(data, track.display, track.length, track.bitrate, track.sampleFreq, track.channels); 812 813 mpc_set_replay_level(demux, MPC_OLD_GAIN_REF, pluginConfig.replaygain, 814 pluginConfig.albumGain, pluginConfig.clipPrevention); 740 815 741 816 MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH]; 742 817 char xmmsBuffer[MPC_DECODER_BUFFER_LENGTH * 4]; 743 818 744 if (!MpcPlugin.output->open_audio(FMT_S16_LE, track.sampleFreq, track.channels)) 745 { 746 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to open an audio output"); 747 mpc_reader_exit_stdio(&reader); 748 return endThread(filename, 0, true); 749 } 750 else 751 { 752 mpcDecoder.isOutput = true; 753 } 754 819 if (!data->output->open_audio(FMT_S16_LE, track.sampleFreq, track.channels)) 820 { 821 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to open an audio output"); 822 return endThread(filename, input, true); 823 } 824 825 mpcDecoder.isOutput = true; 755 826 lockRelease(); 756 827 757 int counter = 2 * track.sampleFreq / 3; 828 data->set_pb_ready(data); 829 data->playing = TRUE; 830 831 gint counter = 2 * track.sampleFreq / 3; 758 832 int status = 0; 759 while (isAlive()) 760 { 761 if (getOffset() != -1) 833 while (mpcDecoder.isAlive) 834 { 835 lockAcquire(); 836 837 if (mpcDecoder.offset != -1) 762 838 { 763 mpc_demux_seek_s econd(demux, mpcDecoder.offset);764 setOffset(-1);765 status = 0;839 mpc_demux_seek_sample(demux, mpcDecoder.offset * track.sampleFreq / 1000); 840 data->output->flush(mpcDecoder.offset); 841 mpcDecoder.offset = -1; 766 842 } 767 843 768 lockAcquire(); 769 short iPlaying = MpcPlugin.output->buffer_playing()? 1 : 0; 770 int iFree = MpcPlugin.output->buffer_free(); 771 if (!mpcDecoder.isPause && iFree >= ((1152 * 4) << iPlaying) && status != -1) 844 short iPlaying = data->output->buffer_playing()? 1 : 0; 845 gint iFree = data->output->buffer_free(); 846 if (!mpcDecoder.isPause && iFree >= ((1152 * 4) << iPlaying) && status != -1) 772 847 { 773 status = processBuffer(sampleBuffer, xmmsBuffer, *demux); 774 lockRelease(); 775 776 if(pluginConfig.dynamicBitrate) { 777 counter -= status; 778 if(counter < 0) { 779 MpcPlugin.set_info(track.display, track.length, track.bitrate, track.sampleFreq, track.channels); 780 counter = 2 * track.sampleFreq / 3; 781 } 782 } 848 status = processBuffer(data, sampleBuffer, xmmsBuffer, demux); 849 lockRelease(); 850 851 if(pluginConfig.dynamicBitrate) 852 { 853 counter -= status; 854 if(counter < 0) 855 { 856 data->set_params(data, track.display, track.length, track.bitrate, track.sampleFreq, track.channels); 857 counter = 2 * track.sampleFreq / 3; 858 } 859 } 783 860 } 784 861 else 785 862 { 786 863 lockRelease(); 787 864 if (mpcDecoder.isPause == FALSE && status == -1 && 788 MpcPlugin.output->buffer_playing() == FALSE)865 data->output->buffer_playing() == FALSE) 789 866 break; 790 xmms_usleep(100000);791 792 867 g_usleep(60000); 868 } 869 } 793 870 mpc_demux_exit(demux); 794 mpc_reader_exit_stdio(&reader); 795 return endThread(filename, 0, false); 796 } 797 798 static int processBuffer(MPC_SAMPLE_FORMAT* sampleBuffer, char* xmmsBuffer, mpc_demux& demux) 799 { 800 mpc_frame_info info; 801 802 info.buffer = sampleBuffer; 803 mpc_demux_decode(&demux, &info); 804 805 if (info.bits == -1) return -1; // end of stream 806 807 copyBuffer(sampleBuffer, xmmsBuffer, info.samples * track.channels); 808 809 if (pluginConfig.dynamicBitrate) 810 { 811 track.bitrate = static_cast<int> (info.bits * track.sampleFreq / 1152); 812 } 813 814 if (pluginConfig.isEq) 815 { 816 iir(xmmsBuffer, 4 * info.samples); 817 } 818 819 MpcPlugin.add_vis_pcm(MpcPlugin.output->written_time(), FMT_S16_LE, track.channels, info.samples * 2 * track.channels, xmmsBuffer); 820 MpcPlugin.output->write_audio(xmmsBuffer, info.samples * 2 * track.channels); 821 return info.samples; 822 } 823 824 static void setReplaygain(mpc_demux * d) 825 { 826 mpc_set_replay_level(d, MPC_OLD_GAIN_REF, pluginConfig.replaygain, 827 !pluginConfig.albumGain, pluginConfig.clipPrevention); 828 } 829 830 inline static void lockAcquire() 831 { 832 pthread_mutex_lock(&threadMutex); 833 } 834 835 inline static void lockRelease() 836 { 837 pthread_mutex_unlock(&threadMutex); 838 } 839 840 inline static bool isAlive() 841 { 842 lockAcquire(); 843 bool isAlive = mpcDecoder.isAlive; 844 lockRelease(); 845 return isAlive; 846 } 847 848 inline static bool isPause() 849 { 850 lockAcquire(); 851 bool isPause = mpcDecoder.isPause; 852 lockRelease(); 853 return isPause; 854 } 855 856 inline static void setAlive(bool isAlive) 857 { 858 lockAcquire(); 859 mpcDecoder.isAlive = isAlive; 860 lockRelease(); 861 } 862 863 inline static double getOffset() 864 { 865 lockAcquire(); 866 double offset = mpcDecoder.offset; 867 lockRelease(); 868 return offset; 869 } 870 871 inline static void setOffset(double offset) 872 { 873 lockAcquire(); 874 mpcDecoder.offset = offset; 875 lockRelease(); 876 } 871 return endThread(filename, input, false); 872 } 873 874 const gchar *mpc_fmts[] = { "mpc", NULL }; 875 876 InputPlugin MpcPlugin = { 877 0, // handle 878 0, // filename 879 (gchar *)"Musepack Audio Plugin", // description 880 mpcOpenPlugin, // init 881 0, // cleanup 882 mpcAboutBox, // about : Show About box 883 mpcConfigBox, // configure : Show Configure box 884 TRUE, // enabled 885 0, // is_our_file 886 0, // scan_dir 887 mpcPlay, // play_file 888 mpcStop, // stop 889 mpcPause, // pause 890 mpcSeek, // seek 891 0, // get_time 892 0, // get_volume 893 0, // set_volume 894 0, // get_vis_type 895 0, // add_vis_pcm 896 0, // set_info 897 0, // set_info_text 898 0, // get_song_info : Get Title String callback 899 mpcFileInfoBox, // file_info_box : Show File Info Box 900 mpcGetSongTuple, // get_song_tuple : Acquire tuple for song 901 mpcIsOurFD, // is_our_file_from_vfs 902 (gchar **)mpc_fmts, // vfs_extensions 903 904 /* Added in Audacious 1.4.0 */ 905 mpcSeekm, // void (*mseek) (InputPlayback * playback, gulong millisecond); 906 mpcProbeForTuple, // Tuple *(*probe_for_tuple)(gchar *uri, VFSFile *fd); 907 908 /* Added in Audacious 1.4.1 */ 909 // gboolean have_subtune; 910 911 /* Added in Audacious 1.5.0 */ 912 // gboolean (*update_song_tuple)(Tuple *tuple, VFSFile *fd); 913 }; 914 915 InputPlugin *mpc_iplist[] = { &MpcPlugin, NULL }; 916 917 DECLARE_PLUGIN(musepack, NULL, NULL, mpc_iplist, NULL, NULL, NULL, NULL,NULL); -
bmp-musepack/trunk/libmpc.h
r455 r456 1 /*2 * Copyright (c) 2005, The Musepack Development Team3 * All rights reserved.4 *5 * Redistribution and use in source and binary forms, with or without6 * modification, are permitted provided that the following conditions are7 * met:8 *9 * * Redistributions of source code must retain the above copyright10 * notice, this list of conditions and the following disclaimer.11 *12 * * Redistributions in binary form must reproduce the above13 * copyright notice, this list of conditions and the following14 * disclaimer in the documentation and/or other materials provided15 * with the distribution.16 *17 * * Neither the name of the The Musepack Development Team nor the18 * names of its contributors may be used to endorse or promote19 * products derived from this software without specific prior20 * written permission.21 *22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33 */34 35 1 #ifndef XMMS_MUSEPACK 36 2 #define XMMS_MUSEPACK … … 40 6 { 41 7 #include <audacious/plugin.h> 42 #include <audacious/util.h> 43 #include <audacious/configdb.h> 44 #include <audacious/strings.h> 8 #include <audacious/output.h> 9 #include <audacious/i18n.h> 45 10 } 46 11 … … 49 14 #include <stdio.h> 50 15 #include <stdlib.h> 51 #include <pthread.h>52 16 #include <unistd.h> 53 17 #include <math.h> … … 65 29 #include <taglib/mpcfile.h> 66 30 67 #include "equalizer.h" 68 69 #ifndef M_LN10 70 #define M_LN10 2.3025850929940456840179914546843642 71 #endif 72 73 typedef struct PluginConfig 31 struct PluginConfig 74 32 { 75 33 gboolean clipPrevention; … … 77 35 gboolean replaygain; 78 36 gboolean albumGain; 79 gboolean isEq;80 37 }; 81 38 82 typedefstruct Widgets39 struct Widgets 83 40 { 84 41 GtkWidget* aboutBox; … … 99 56 }; 100 57 101 typedefstruct MpcDecoder58 struct MpcDecoder 102 59 { 103 char*isError;104 doubleoffset;60 gchar* isError; 61 long long offset; 105 62 bool isOutput; 106 63 bool isAlive; … … 108 65 }; 109 66 110 typedefstruct TrackInfo67 struct TrackInfo 111 68 { 112 int bitrate;113 char* display;114 int length;115 int sampleFreq;116 int channels;69 gint bitrate; 70 gchar* display; 71 gint length; 72 gint sampleFreq; 73 gint channels; 117 74 }; 118 75 119 typedefstruct MpcInfo76 struct MpcInfo 120 77 { 121 char* title;122 char* artist;123 char* album;124 char* comment;125 char* genre;126 char* date;127 unsigned track;128 unsigned year;78 gchar* title; 79 gchar* artist; 80 gchar* album; 81 gchar* comment; 82 gchar* genre; 83 gchar* date; 84 unsigned track; 85 unsigned year; 129 86 }; 130 87 131 extern "C" InputPlugin * get_iplugin_info(void);132 133 static void mpcOpenPlugin();134 static void mpcAboutBox();135 static void mpcConfigBox();136 88 static void toggleSwitch(GtkWidget*, gpointer); 137 89 static void saveConfigBox(GtkWidget*, gpointer); 138 static int mpcIsOurFile(char*);139 static void mpcPlay(char*);140 static void mpcStop();141 static void mpcPause(short);142 static void mpcSeek(int);143 static void mpcSetEq(int, float, float*);144 static int mpcGetTime();145 static void mpcClosePlugin();146 static void mpcGetSongInfo(char*, char**, int*);147 static void freeTags(MpcInfo&);148 static MpcInfo getTags(const char*);149 static void mpcFileInfoBox(char*);150 static void mpcGtkPrintLabel(GtkWidget*, char*, ...);151 static GtkWidget* mpcGtkTagLabel(char*, int, int, int, int, GtkWidget*);152 static GtkWidget* mpcGtkTagEntry(int, int, int, int, int, GtkWidget*);153 static GtkWidget* mpcGtkLabel(GtkWidget*);154 static GtkWidget* mpcGtkButton(char*, GtkWidget*);155 static void removeTags(GtkWidget*, gpointer);156 static void saveTags(GtkWidget*, gpointer);157 90 static void closeInfoBox(GtkWidget*, gpointer); 158 static char* mpcGenerateTitle(const MpcInfo&, const char*); 159 static void lockAcquire(); 160 static void lockRelease(); 161 static void* decodeStream(void*); 162 static int processBuffer(MPC_SAMPLE_FORMAT*, char*, mpc_demux&); 163 static void* endThread(char*, FILE*, bool); 164 static bool isAlive(); 165 static void setAlive(bool); 166 static double getOffset(); 167 static void setOffset(double); 168 static bool isPause(); 169 static void setReplaygain(mpc_demux *); 91 static void* decodeStream(InputPlayback*); 170 92 171 93 #ifdef MPC_FIXED_POINT … … 186 108 int clipMax = (1 << (pSize - 1)) - 1; 187 109 int floatScale = 1 << (pSize - 1); 188 for (unsigned n = 0; n < pLength; n++)110 for (unsigned n = 0; n < 2 * pLength; n++) 189 111 { 190 112 int val;
Note: See TracChangeset
for help on using the changeset viewer.