Mercurial > audlegacy-plugins
annotate src/musepack/libmpc.cxx @ 1438:dc3e28d3b92a
mpc: convert, wma: fixes
author | William Pitcock <nenolod@atheme-project.org> |
---|---|
date | Fri, 10 Aug 2007 09:19:44 -0500 |
parents | 761e17b23e0c |
children | 195b5657303e |
rev | line source |
---|---|
232 | 1 #include "libmpc.h" |
2 | |
3 #define FORCED_THREAD_STACKSIZE 1024 * 1000 | |
4 #define REMOVE_NONEXISTANT_TAG(x) if (!*x) { x = NULL; } | |
5 | |
6 using TagLib::MPC::File; | |
7 using TagLib::Tag; | |
8 using TagLib::String; | |
9 using TagLib::APE::ItemListMap; | |
10 | |
1044
b1128efde471
[svn] - get rid of all warnings gcc 4.2.0 emits with my build configuration.
yaz
parents:
659
diff
changeset
|
11 const gchar *mpc_fmts[] = { "mpc", NULL }; |
372
a157306caf03
[svn] - finalize the plugin-side of the extension-assist ABI
nenolod
parents:
368
diff
changeset
|
12 |
232 | 13 InputPlugin MpcPlugin = { |
14 NULL, //File Handle FILE* handle | |
15 NULL, //Filename char* filename | |
1185 | 16 (gchar *)"Musepack Audio Plugin", |
232 | 17 mpcOpenPlugin, //Open Plugin [CALLBACK] |
18 mpcAboutBox, //Show About box [CALLBACK] | |
19 mpcConfigBox, //Show Configure box [CALLBACK] | |
260
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
20 mpcIsOurFile, //Check if it's our file [CALLBACK] |
232 | 21 NULL, //Scan the directory [UNUSED] |
22 mpcPlay, //Play [CALLBACK] | |
23 mpcStop, //Stop [CALLBACK] | |
24 mpcPause, //Pause [CALLBACK] | |
25 mpcSeek, //Seek [CALLBACK] | |
26 NULL, //Set EQ [CALLBACK] | |
27 mpcGetTime, //Get Time [CALLBACK] | |
28 NULL, //Get Volume [UNUSED] | |
29 NULL, //Set Volume [UNUSED] | |
30 NULL, //Close Plugin [UNUSED] | |
31 NULL, //Obsolete [UNUSED] | |
32 NULL, //Visual plugins add_vis_pcm(int time, AFormat fmt, int nch, int length, void *ptr) | |
33 NULL, //Set Info Settings set_info(char *title, int length, int rate, int freq, int nch) | |
34 NULL, //set Info Text set_info_text(char* text) | |
35 mpcGetSongInfo, //Get Title String callback [CALLBACK] | |
36 mpcFileInfoBox, //Show File Info Box [CALLBACK] | |
37 NULL, //Output Plugin Handle OutputPlugin output | |
254 | 38 mpcGetSongTuple,//Acquire tuple for song [CALLBACK] |
39 NULL, | |
40 NULL, | |
41 mpcIsOurFD, | |
1044
b1128efde471
[svn] - get rid of all warnings gcc 4.2.0 emits with my build configuration.
yaz
parents:
659
diff
changeset
|
42 (gchar **)mpc_fmts |
232 | 43 }; |
44 | |
1079 | 45 InputPlugin *mpc_iplist[] = { &MpcPlugin, NULL }; |
46 | |
1395
761e17b23e0c
added Discovery plugin type
Cristi Magherusan <majeru@atheme-project.org>
parents:
1357
diff
changeset
|
47 DECLARE_PLUGIN(musepack, NULL, NULL, mpc_iplist, NULL, NULL, NULL, NULL,NULL); |
232 | 48 |
49 static PluginConfig pluginConfig = {0}; | |
50 static Widgets widgets = {0}; | |
51 static MpcDecoder mpcDecoder = {0}; | |
52 static TrackInfo track = {0}; | |
53 | |
54 static GThread *threadHandle; | |
55 GStaticMutex threadMutex = G_STATIC_MUTEX_INIT; | |
56 | |
57 /* | |
58 * VFS callback implementation, adapted from mpc_reader.c. | |
59 * This _IS_ very sick, but it works. -nenolod | |
60 */ | |
61 static mpc_int32_t | |
62 vfs_fread_impl(void *data, void *ptr, mpc_int32_t size) | |
63 { | |
64 mpc_reader_file *d = (mpc_reader_file *) data; | |
65 VFSFile *file = (VFSFile *) d->file; | |
66 | |
67 return (mpc_int32_t) vfs_fread(ptr, 1, size, file); | |
68 } | |
69 | |
70 static mpc_bool_t | |
71 vfs_fseek_impl(void *data, mpc_int32_t offset) | |
72 { | |
73 mpc_reader_file *d = (mpc_reader_file *) data; | |
74 VFSFile *file = (VFSFile *) d->file; | |
75 | |
76 return d->is_seekable ? vfs_fseek(file, offset, SEEK_SET) == 0 : FALSE; | |
77 } | |
78 | |
79 static mpc_int32_t | |
80 vfs_ftell_impl(void *data) | |
81 { | |
82 mpc_reader_file *d = (mpc_reader_file *) data; | |
83 VFSFile *file = (VFSFile *) d->file; | |
84 | |
85 return vfs_ftell(file); | |
86 } | |
87 | |
88 static mpc_int32_t | |
89 vfs_getsize_impl(void *data) | |
90 { | |
91 mpc_reader_file *d = (mpc_reader_file *) data; | |
92 | |
93 return d->file_size; | |
94 } | |
95 | |
96 static mpc_bool_t | |
97 vfs_canseek_impl(void *data) | |
98 { | |
99 mpc_reader_file *d = (mpc_reader_file *) data; | |
100 | |
101 return d->is_seekable; | |
102 } | |
103 | |
104 /* | |
105 * This sets up an mpc_reader_file object to read from VFS instead of libc. | |
106 * Essentially, we use this instead of the normal constructor. | |
107 * - nenolod | |
108 */ | |
109 void | |
110 mpc_reader_setup_file_vfs(mpc_reader_file *p_reader, VFSFile *input) | |
111 { | |
112 p_reader->reader.seek = vfs_fseek_impl; | |
113 p_reader->reader.read = vfs_fread_impl; | |
114 p_reader->reader.tell = vfs_ftell_impl; | |
115 p_reader->reader.get_size = vfs_getsize_impl; | |
116 p_reader->reader.canseek = vfs_canseek_impl; | |
117 p_reader->reader.data = p_reader; | |
118 | |
119 p_reader->file = (FILE *) input; // no worries, it gets cast back -nenolod | |
120 p_reader->is_seekable = TRUE; // XXX streams | |
121 | |
122 vfs_fseek(input, 0, SEEK_END); | |
123 p_reader->file_size = vfs_ftell(input); | |
124 vfs_fseek(input, 0, SEEK_SET); | |
125 } | |
126 | |
127 static void mpcOpenPlugin() | |
128 { | |
129 ConfigDb *cfg; | |
130 cfg = bmp_cfg_db_open(); | |
131 bmp_cfg_db_get_bool(cfg, "musepack", "clipPrevention", &pluginConfig.clipPrevention); | |
132 bmp_cfg_db_get_bool(cfg, "musepack", "albumGain", &pluginConfig.albumGain); | |
133 bmp_cfg_db_get_bool(cfg, "musepack", "dynamicBitrate", &pluginConfig.dynamicBitrate); | |
134 bmp_cfg_db_get_bool(cfg, "musepack", "replaygain", &pluginConfig.replaygain); | |
135 bmp_cfg_db_close(cfg); | |
136 } | |
137 | |
138 static void mpcAboutBox() | |
139 { | |
140 GtkWidget* aboutBox = widgets.aboutBox; | |
141 if (aboutBox) | |
142 gdk_window_raise(aboutBox->window); | |
143 else | |
144 { | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
145 char* titleText = g_strdup_printf(_("Musepack Decoder Plugin 1.2")); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
146 const char* contentText = _("Plugin code by\nBenoit Amiaux\nMartin Spuler\nKuniklo\n\nGet latest version at http://musepack.net\n"); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
147 const char* buttonText = _("Nevermind"); |
232 | 148 aboutBox = xmms_show_message(titleText, contentText, buttonText, FALSE, NULL, NULL); |
149 widgets.aboutBox = aboutBox; | |
150 g_signal_connect(G_OBJECT(aboutBox), "destroy", G_CALLBACK(gtk_widget_destroyed), &widgets.aboutBox); | |
151 } | |
152 } | |
153 | |
154 static void mpcConfigBox() | |
155 { | |
156 GtkWidget* configBox = widgets.configBox; | |
157 if(configBox) | |
158 gdk_window_raise(configBox->window); | |
159 else | |
160 { | |
161 configBox = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
162 gtk_window_set_type_hint(GTK_WINDOW(configBox), GDK_WINDOW_TYPE_HINT_DIALOG); | |
163 widgets.configBox = configBox; | |
164 g_signal_connect(G_OBJECT(configBox), "destroy", G_CALLBACK(gtk_widget_destroyed), &widgets.configBox); | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
165 gtk_window_set_title(GTK_WINDOW(configBox), _("Musepack Decoder Configuration")); |
232 | 166 gtk_window_set_policy(GTK_WINDOW(configBox), FALSE, FALSE, FALSE); |
167 gtk_container_border_width(GTK_CONTAINER(configBox), 10); | |
168 | |
169 GtkWidget* notebook = gtk_notebook_new(); | |
170 GtkWidget* vbox = gtk_vbox_new(FALSE, 10); | |
171 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); | |
172 gtk_container_add(GTK_CONTAINER(configBox), vbox); | |
173 | |
174 //General Settings Tab | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
175 GtkWidget* generalSet = gtk_frame_new(_("General Settings")); |
232 | 176 gtk_container_border_width(GTK_CONTAINER(generalSet), 5); |
177 | |
178 GtkWidget* gSvbox = gtk_vbox_new(FALSE, 10); | |
179 gtk_container_border_width(GTK_CONTAINER(gSvbox), 5); | |
180 gtk_container_add(GTK_CONTAINER(generalSet), gSvbox); | |
181 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
182 GtkWidget* bitrateCheck = gtk_check_button_new_with_label(_("Enable Dynamic Bitrate Display")); |
232 | 183 widgets.bitrateCheck = bitrateCheck; |
184 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bitrateCheck), pluginConfig.dynamicBitrate); | |
185 gtk_box_pack_start(GTK_BOX(gSvbox), bitrateCheck, FALSE, FALSE, 0); | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
186 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), generalSet, gtk_label_new(_("Plugin"))); |
232 | 187 |
188 //ReplayGain Settings Tab | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
189 GtkWidget* replaygainSet = gtk_frame_new(_("ReplayGain Settings")); |
232 | 190 gtk_container_border_width(GTK_CONTAINER(replaygainSet), 5); |
191 | |
192 GtkWidget* rSVbox = gtk_vbox_new(FALSE, 10); | |
193 gtk_container_border_width(GTK_CONTAINER(rSVbox), 5); | |
194 gtk_container_add(GTK_CONTAINER(replaygainSet), rSVbox); | |
195 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
196 GtkWidget* clippingCheck = gtk_check_button_new_with_label(_("Enable Clipping Prevention")); |
232 | 197 widgets.clippingCheck = clippingCheck; |
198 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(clippingCheck), pluginConfig.clipPrevention); | |
199 gtk_box_pack_start(GTK_BOX(rSVbox), clippingCheck, FALSE, FALSE, 0); | |
200 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
201 GtkWidget* replaygainCheck = gtk_check_button_new_with_label(_("Enable ReplayGain")); |
232 | 202 widgets.replaygainCheck = replaygainCheck; |
203 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(replaygainCheck), pluginConfig.replaygain); | |
204 gtk_box_pack_start(GTK_BOX(rSVbox), replaygainCheck, FALSE, FALSE, 0); | |
205 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
206 GtkWidget* replaygainType = gtk_frame_new(_("ReplayGain Type")); |
232 | 207 gtk_box_pack_start(GTK_BOX(rSVbox), replaygainType, FALSE, FALSE, 0); |
208 g_signal_connect(G_OBJECT(replaygainCheck), "toggled", G_CALLBACK(toggleSwitch), replaygainType); | |
209 | |
210 GtkWidget* rgVbox = gtk_vbox_new(FALSE, 5); | |
211 gtk_container_set_border_width(GTK_CONTAINER(rgVbox), 5); | |
212 gtk_container_add(GTK_CONTAINER(replaygainType), rgVbox); | |
213 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
214 GtkWidget* trackCheck = gtk_radio_button_new_with_label(NULL, _("Use Track Gain")); |
232 | 215 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(trackCheck), !pluginConfig.albumGain); |
216 gtk_box_pack_start(GTK_BOX(rgVbox), trackCheck, FALSE, FALSE, 0); | |
217 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
218 GtkWidget* albumCheck = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(trackCheck)), _("Use Album Gain")); |
232 | 219 widgets.albumCheck = albumCheck; |
220 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(albumCheck), pluginConfig.albumGain); | |
221 gtk_box_pack_start(GTK_BOX(rgVbox), albumCheck, FALSE, FALSE, 0); | |
222 gtk_widget_set_sensitive(replaygainType, pluginConfig.replaygain); | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
223 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), replaygainSet, gtk_label_new(_("ReplayGain"))); |
232 | 224 |
225 //Buttons | |
226 GtkWidget* buttonBox = gtk_hbutton_box_new(); | |
227 gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END); | |
228 gtk_button_box_set_spacing(GTK_BUTTON_BOX(buttonBox), 5); | |
229 gtk_box_pack_start(GTK_BOX(vbox), buttonBox, FALSE, FALSE, 0); | |
230 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
231 GtkWidget* okButton = gtk_button_new_with_label(_("Ok")); |
232 | 232 g_signal_connect(G_OBJECT(okButton), "clicked", G_CALLBACK(saveConfigBox), NULL); |
233 GTK_WIDGET_SET_FLAGS(okButton, GTK_CAN_DEFAULT); | |
234 gtk_box_pack_start(GTK_BOX(buttonBox), okButton, TRUE, TRUE, 0); | |
235 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
236 GtkWidget* cancelButton = gtk_button_new_with_label(_("Cancel")); |
232 | 237 g_signal_connect_swapped(G_OBJECT(cancelButton), "clicked", G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(widgets.configBox)); |
238 GTK_WIDGET_SET_FLAGS(cancelButton, GTK_CAN_DEFAULT); | |
239 gtk_widget_grab_default(cancelButton); | |
240 gtk_box_pack_start(GTK_BOX(buttonBox), cancelButton, TRUE, TRUE, 0); | |
241 | |
242 gtk_widget_show_all(configBox); | |
243 } | |
244 } | |
245 | |
246 static void toggleSwitch(GtkWidget* p_Widget, gpointer p_Data) | |
247 { | |
248 gtk_widget_set_sensitive(GTK_WIDGET(p_Data), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_Widget))); | |
249 } | |
250 | |
251 static void saveConfigBox(GtkWidget* p_Widget, gpointer p_Data) | |
252 { | |
253 ConfigDb* cfg; | |
254 GtkToggleButton* tb; | |
255 | |
256 tb = GTK_TOGGLE_BUTTON(widgets.replaygainCheck); | |
257 pluginConfig.replaygain = gtk_toggle_button_get_active(tb); | |
258 tb = GTK_TOGGLE_BUTTON(widgets.clippingCheck); | |
259 pluginConfig.clipPrevention = gtk_toggle_button_get_active(tb); | |
260 tb = GTK_TOGGLE_BUTTON(widgets.bitrateCheck); | |
261 pluginConfig.dynamicBitrate = gtk_toggle_button_get_active(tb); | |
262 tb = GTK_TOGGLE_BUTTON(widgets.albumCheck); | |
263 pluginConfig.albumGain = gtk_toggle_button_get_active(tb); | |
264 | |
265 cfg = bmp_cfg_db_open(); | |
266 | |
267 bmp_cfg_db_set_bool(cfg, "musepack", "clipPrevention", pluginConfig.clipPrevention); | |
268 bmp_cfg_db_set_bool(cfg, "musepack", "albumGain", pluginConfig.albumGain); | |
269 bmp_cfg_db_set_bool(cfg, "musepack", "dynamicBitrate", pluginConfig.dynamicBitrate); | |
270 bmp_cfg_db_set_bool(cfg, "musepack", "replaygain", pluginConfig.replaygain); | |
271 | |
272 bmp_cfg_db_close(cfg); | |
273 | |
274 gtk_widget_destroy (widgets.configBox); | |
275 } | |
276 | |
260
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
277 static int mpcIsOurFile(char* p_Filename) |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
278 { |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
279 VFSFile *file; |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
280 gchar magic[3]; |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
281 if ((file = vfs_fopen(p_Filename, "rb"))) { |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
282 vfs_fread(magic, 1, 3, file); |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
283 if (!memcmp(magic, "MP+", 3)) { |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
284 vfs_fclose(file); |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
285 return 1; |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
286 } |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
287 vfs_fclose(file); |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
288 } |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
289 return 0; |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
290 } |
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
291 |
254 | 292 static int mpcIsOurFD(char* p_Filename, VFSFile* file) |
232 | 293 { |
254 | 294 gchar magic[3]; |
295 vfs_fread(magic, 1, 3, file); | |
260
4f7b72c88319
[svn] So input.c wants to have the old-style function available...
chainsaw
parents:
254
diff
changeset
|
296 if (!memcmp(magic, "MP+", 3)) |
254 | 297 return 1; |
298 return 0; | |
232 | 299 } |
300 | |
567 | 301 static void mpcPlay(InputPlayback *data) |
232 | 302 { |
303 mpcDecoder.offset = -1; | |
304 mpcDecoder.isAlive = true; | |
305 mpcDecoder.isOutput = false; | |
306 mpcDecoder.isPause = false; | |
1357
cf46ed0ee590
musepack: new threading model
William Pitcock <nenolod@atheme-project.org>
parents:
1304
diff
changeset
|
307 threadHandle = g_thread_self(); |
cf46ed0ee590
musepack: new threading model
William Pitcock <nenolod@atheme-project.org>
parents:
1304
diff
changeset
|
308 decodeStream((void *) g_strdup(data->filename)); |
232 | 309 } |
310 | |
567 | 311 static void mpcStop(InputPlayback *data) |
232 | 312 { |
313 setAlive(false); | |
314 if (threadHandle) | |
315 { | |
316 g_thread_join(threadHandle); | |
317 if (mpcDecoder.isOutput) | |
318 { | |
567 | 319 data->output->buffer_free(); |
320 data->output->close_audio(); | |
232 | 321 mpcDecoder.isOutput = false; |
322 } | |
323 } | |
324 } | |
325 | |
567 | 326 static void mpcPause(InputPlayback *data, short p_Pause) |
232 | 327 { |
328 lockAcquire(); | |
329 mpcDecoder.isPause = p_Pause; | |
567 | 330 data->output->pause(p_Pause); |
232 | 331 lockRelease(); |
332 } | |
333 | |
567 | 334 static void mpcSeek(InputPlayback *data, int p_Offset) |
232 | 335 { |
336 lockAcquire(); | |
337 mpcDecoder.offset = static_cast<double> (p_Offset); | |
567 | 338 data->output->flush(1000 * p_Offset); |
232 | 339 lockRelease(); |
340 } | |
341 | |
567 | 342 static int mpcGetTime(InputPlayback *data) |
232 | 343 { |
344 if(!isAlive()) | |
345 return -1; | |
567 | 346 return data->output->output_time(); |
232 | 347 } |
348 | |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
349 static Tuple *mpcGetSongTuple(char* p_Filename) |
232 | 350 { |
351 VFSFile *input = vfs_fopen(p_Filename, "rb"); | |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
352 Tuple *tuple = NULL; |
232 | 353 |
354 if(input) | |
355 { | |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
356 tuple = tuple_new_from_filename(p_Filename); |
232 | 357 |
358 MpcInfo tags = getTags(p_Filename); | |
359 | |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
360 tuple_associate_string(tuple, "date", tags.date); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
361 tuple_associate_string(tuple, "title", tags.title); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
362 tuple_associate_string(tuple, "artist", tags.artist); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
363 tuple_associate_string(tuple, "album", tags.album); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
364 tuple_associate_int(tuple, "track-number", tags.track); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
365 tuple_associate_int(tuple, "year", tags.year); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
366 tuple_associate_string(tuple, "genre", tags.genre); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
367 tuple_associate_string(tuple, "comment", tags.comment); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
368 |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
369 tuple_associate_string(tuple, "codec", "Musepack"); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
370 tuple_associate_string(tuple, "quality", "lossy"); |
232 | 371 |
372 freeTags(tags); | |
373 | |
374 mpc_streaminfo info; | |
375 mpc_reader_file reader; | |
376 mpc_reader_setup_file_vfs(&reader, input); | |
377 mpc_streaminfo_read(&info, &reader.reader); | |
378 | |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
379 tuple_associate_int(tuple, "length", static_cast<int> (1000 * mpc_streaminfo_get_length(&info))); |
232 | 380 vfs_fclose(input); |
381 } | |
382 else | |
383 { | |
384 char* temp = g_strdup_printf("[xmms-musepack] mpcGetSongInfo is unable to open %s\n", p_Filename); | |
385 perror(temp); | |
386 free(temp); | |
387 } | |
388 | |
389 return tuple; | |
390 } | |
391 | |
392 static void mpcGetSongInfo(char* p_Filename, char** p_Title, int* p_Length) | |
393 { | |
394 VFSFile *input = vfs_fopen(p_Filename, "rb"); | |
395 if(input) | |
396 { | |
397 MpcInfo tags = getTags(p_Filename); | |
398 *p_Title = mpcGenerateTitle(tags, p_Filename); | |
399 freeTags(tags); | |
400 mpc_streaminfo info; | |
401 mpc_reader_file reader; | |
402 mpc_reader_setup_file_vfs(&reader, input); | |
403 mpc_streaminfo_read(&info, &reader.reader); | |
404 *p_Length = static_cast<int> (1000 * mpc_streaminfo_get_length(&info)); | |
405 vfs_fclose(input); | |
406 } | |
407 else | |
408 { | |
409 char* temp = g_strdup_printf("[xmms-musepack] mpcGetSongInfo is unable to open %s\n", p_Filename); | |
410 perror(temp); | |
411 free(temp); | |
412 } | |
413 } | |
414 | |
415 static void freeTags(MpcInfo& tags) | |
416 { | |
417 free(tags.title); | |
418 free(tags.artist); | |
419 free(tags.album); | |
420 free(tags.comment); | |
421 free(tags.genre); | |
422 free(tags.date); | |
423 } | |
424 | |
425 static MpcInfo getTags(const char* p_Filename) | |
426 { | |
427 File oFile(p_Filename, false); | |
428 Tag* poTag = oFile.tag(); | |
429 MpcInfo tags = {0}; | |
430 tags.title = g_strdup(poTag->title().toCString(true)); | |
431 REMOVE_NONEXISTANT_TAG(tags.title); | |
432 tags.artist = g_strdup(poTag->artist().toCString(true)); | |
433 REMOVE_NONEXISTANT_TAG(tags.artist); | |
434 tags.album = g_strdup(poTag->album().toCString(true)); | |
435 REMOVE_NONEXISTANT_TAG(tags.album); | |
436 tags.genre = g_strdup(poTag->genre().toCString(true)); | |
437 REMOVE_NONEXISTANT_TAG(tags.genre); | |
438 tags.comment = g_strdup(poTag->comment().toCString(true)); | |
439 REMOVE_NONEXISTANT_TAG(tags.comment); | |
440 tags.year = poTag->year(); | |
441 tags.track = poTag->track(); | |
659
d1a03def0021
[svn] - disable broken APETag support for now, can cause crashes
nenolod
parents:
567
diff
changeset
|
442 #if 0 |
232 | 443 TagLib::APE::Tag* ape = oFile.APETag(false); |
444 if(ape) | |
445 { | |
446 ItemListMap map = ape->itemListMap(); | |
447 if(map.contains("YEAR")) | |
448 { | |
449 tags.date = g_strdup(map["YEAR"].toString().toCString(true)); | |
450 } | |
451 else | |
452 { | |
453 tags.date = g_strdup_printf("%d", tags.year); | |
454 } | |
455 } | |
659
d1a03def0021
[svn] - disable broken APETag support for now, can cause crashes
nenolod
parents:
567
diff
changeset
|
456 #endif |
232 | 457 return tags; |
458 } | |
459 | |
460 static void mpcFileInfoBox(char* p_Filename) | |
461 { | |
462 GtkWidget* infoBox = widgets.infoBox; | |
463 | |
464 if(infoBox) | |
465 gdk_window_raise(infoBox->window); | |
466 else | |
467 { | |
468 infoBox = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
469 gtk_window_set_type_hint(GTK_WINDOW(infoBox), GDK_WINDOW_TYPE_HINT_DIALOG); | |
470 widgets.infoBox = infoBox; | |
471 gtk_window_set_policy(GTK_WINDOW(infoBox), FALSE, FALSE, FALSE); | |
472 g_signal_connect(G_OBJECT(infoBox), "destroy", G_CALLBACK(closeInfoBox), NULL); | |
473 gtk_container_set_border_width(GTK_CONTAINER(infoBox), 10); | |
474 | |
475 GtkWidget* iVbox = gtk_vbox_new(FALSE, 10); | |
476 gtk_container_add(GTK_CONTAINER(infoBox), iVbox); | |
477 | |
478 GtkWidget* filenameHbox = gtk_hbox_new(FALSE, 5); | |
479 gtk_box_pack_start(GTK_BOX(iVbox), filenameHbox, FALSE, TRUE, 0); | |
480 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
481 GtkWidget* fileLabel = gtk_label_new(_("Filename:")); |
232 | 482 gtk_box_pack_start(GTK_BOX(filenameHbox), fileLabel, FALSE, TRUE, 0); |
483 | |
484 GtkWidget* fileEntry = gtk_entry_new(); | |
485 widgets.fileEntry = fileEntry; | |
486 gtk_editable_set_editable(GTK_EDITABLE(fileEntry), FALSE); | |
487 gtk_box_pack_start(GTK_BOX(filenameHbox), fileEntry, TRUE, TRUE, 0); | |
488 | |
489 GtkWidget* iHbox = gtk_hbox_new(FALSE, 10); | |
490 gtk_box_pack_start(GTK_BOX(iVbox), iHbox, FALSE, TRUE, 0); | |
491 | |
492 GtkWidget* leftBox = gtk_vbox_new(FALSE, 10); | |
493 gtk_box_pack_start(GTK_BOX(iHbox), leftBox, FALSE, FALSE, 0); | |
494 | |
495 //Tag labels | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
496 GtkWidget* tagFrame = gtk_frame_new(_("Musepack Tag")); |
232 | 497 gtk_box_pack_start(GTK_BOX(leftBox), tagFrame, FALSE, FALSE, 0); |
498 gtk_widget_set_sensitive(tagFrame, TRUE); | |
499 | |
500 GtkWidget* iTable = gtk_table_new(5, 5, FALSE); | |
501 gtk_container_set_border_width(GTK_CONTAINER(iTable), 5); | |
502 gtk_container_add(GTK_CONTAINER(tagFrame), iTable); | |
503 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
504 mpcGtkTagLabel(_("Title:"), 0, 1, 0, 1, iTable); |
232 | 505 GtkWidget* titleEntry = mpcGtkTagEntry(1, 4, 0, 1, 0, iTable); |
506 widgets.titleEntry = titleEntry; | |
507 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
508 mpcGtkTagLabel(_("Artist:"), 0, 1, 1, 2, iTable); |
232 | 509 GtkWidget* artistEntry = mpcGtkTagEntry(1, 4, 1, 2, 0, iTable); |
510 widgets.artistEntry = artistEntry; | |
511 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
512 mpcGtkTagLabel(_("Album:"), 0, 1, 2, 3, iTable); |
232 | 513 GtkWidget* albumEntry = mpcGtkTagEntry(1, 4, 2, 3, 0, iTable); |
514 widgets.albumEntry = albumEntry; | |
515 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
516 mpcGtkTagLabel(_("Comment:"), 0, 1, 3, 4, iTable); |
232 | 517 GtkWidget* commentEntry = mpcGtkTagEntry(1, 4, 3, 4, 0, iTable); |
518 widgets.commentEntry = commentEntry; | |
519 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
520 mpcGtkTagLabel(_("Year:"), 0, 1, 4, 5, iTable); |
232 | 521 GtkWidget* yearEntry = mpcGtkTagEntry(1, 2, 4, 5, 4, iTable); |
522 widgets.yearEntry = yearEntry; | |
523 gtk_widget_set_usize(yearEntry, 4, -1); | |
524 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
525 mpcGtkTagLabel(_("Track:"), 2, 3, 4, 5, iTable); |
232 | 526 GtkWidget* trackEntry = mpcGtkTagEntry(3, 4, 4, 5, 4, iTable); |
527 widgets.trackEntry = trackEntry; | |
528 gtk_widget_set_usize(trackEntry, 3, -1); | |
529 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
530 mpcGtkTagLabel(_("Genre:"), 0, 1, 5, 6, iTable); |
232 | 531 GtkWidget* genreEntry = mpcGtkTagEntry(1, 4, 5, 6, 0, iTable); |
532 widgets.genreEntry = genreEntry; | |
533 gtk_widget_set_usize(genreEntry, 20, -1); | |
534 | |
535 //Buttons | |
536 GtkWidget* buttonBox = gtk_hbutton_box_new(); | |
537 gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END); | |
538 gtk_button_box_set_spacing(GTK_BUTTON_BOX(buttonBox), 5); | |
539 gtk_box_pack_start(GTK_BOX(leftBox), buttonBox, FALSE, FALSE, 0); | |
540 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
541 GtkWidget* saveButton = mpcGtkButton(_("Save"), buttonBox); |
232 | 542 g_signal_connect(G_OBJECT(saveButton), "clicked", G_CALLBACK(saveTags), NULL); |
543 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
544 GtkWidget* removeButton = mpcGtkButton(_("Remove Tag"), buttonBox); |
232 | 545 g_signal_connect_swapped(G_OBJECT(removeButton), "clicked", G_CALLBACK(removeTags), NULL); |
546 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
547 GtkWidget* cancelButton = mpcGtkButton(_("Cancel"), buttonBox); |
232 | 548 g_signal_connect_swapped(G_OBJECT(cancelButton), "clicked", G_CALLBACK(closeInfoBox), NULL); |
549 gtk_widget_grab_default(cancelButton); | |
550 | |
551 //File information | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
552 GtkWidget* infoFrame = gtk_frame_new(_("Musepack Info")); |
232 | 553 gtk_box_pack_start(GTK_BOX(iHbox), infoFrame, FALSE, FALSE, 0); |
554 | |
555 GtkWidget* infoVbox = gtk_vbox_new(FALSE, 5); | |
556 gtk_container_add(GTK_CONTAINER(infoFrame), infoVbox); | |
557 gtk_container_set_border_width(GTK_CONTAINER(infoVbox), 10); | |
558 gtk_box_set_spacing(GTK_BOX(infoVbox), 0); | |
559 | |
560 GtkWidget* streamLabel = mpcGtkLabel(infoVbox); | |
561 GtkWidget* encoderLabel = mpcGtkLabel(infoVbox); | |
562 GtkWidget* profileLabel = mpcGtkLabel(infoVbox); | |
563 GtkWidget* bitrateLabel = mpcGtkLabel(infoVbox); | |
564 GtkWidget* rateLabel = mpcGtkLabel(infoVbox); | |
565 GtkWidget* channelsLabel = mpcGtkLabel(infoVbox); | |
566 GtkWidget* lengthLabel = mpcGtkLabel(infoVbox); | |
567 GtkWidget* fileSizeLabel = mpcGtkLabel(infoVbox); | |
568 GtkWidget* trackPeakLabel = mpcGtkLabel(infoVbox); | |
569 GtkWidget* trackGainLabel = mpcGtkLabel(infoVbox); | |
570 GtkWidget* albumPeakLabel = mpcGtkLabel(infoVbox); | |
571 GtkWidget* albumGainLabel = mpcGtkLabel(infoVbox); | |
572 | |
573 VFSFile *input = vfs_fopen(p_Filename, "rb"); | |
574 if(input) | |
575 { | |
576 mpc_streaminfo info; | |
577 mpc_reader_file reader; | |
578 mpc_reader_setup_file_vfs(&reader, input); | |
579 mpc_streaminfo_read(&info, &reader.reader); | |
580 | |
581 int time = static_cast<int> (mpc_streaminfo_get_length(&info)); | |
582 int minutes = time / 60; | |
583 int seconds = time % 60; | |
584 | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
585 mpcGtkPrintLabel(streamLabel, _("Streamversion %d"), info.stream_version); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
586 mpcGtkPrintLabel(encoderLabel, _("Encoder: %s"), info.encoder); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
587 mpcGtkPrintLabel(profileLabel, _("Profile: %s"), info.profile_name); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
588 mpcGtkPrintLabel(bitrateLabel, _("Average bitrate: %6.1f kbps"), info.average_bitrate * 1.e-3); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
589 mpcGtkPrintLabel(rateLabel, _("Samplerate: %d Hz"), info.sample_freq); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
590 mpcGtkPrintLabel(channelsLabel, _("Channels: %d"), info.channels); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
591 mpcGtkPrintLabel(lengthLabel, _("Length: %d:\%.2d"), minutes, seconds); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
592 mpcGtkPrintLabel(fileSizeLabel, _("File size: %d Bytes"), info.total_file_length); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
593 mpcGtkPrintLabel(trackPeakLabel, _("Track Peak: %5u"), info.peak_title); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
594 mpcGtkPrintLabel(trackGainLabel, _("Track Gain: %-+2.2f dB"), 0.01 * info.gain_title); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
595 mpcGtkPrintLabel(albumPeakLabel, _("Album Peak: %5u"), info.peak_album); |
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
596 mpcGtkPrintLabel(albumGainLabel, _("Album Gain: %-+5.2f dB"), 0.01 * info.gain_album); |
232 | 597 |
598 MpcInfo tags = getTags(p_Filename); | |
599 gtk_entry_set_text(GTK_ENTRY(titleEntry), tags.title); | |
600 gtk_entry_set_text(GTK_ENTRY(artistEntry), tags.artist); | |
601 gtk_entry_set_text(GTK_ENTRY(albumEntry), tags.album); | |
602 gtk_entry_set_text(GTK_ENTRY(commentEntry), tags.comment); | |
603 gtk_entry_set_text(GTK_ENTRY(genreEntry), tags.genre); | |
604 char* entry = g_strdup_printf ("%d", tags.track); | |
605 gtk_entry_set_text(GTK_ENTRY(trackEntry), entry); | |
606 free(entry); | |
607 entry = g_strdup_printf ("%d", tags.year); | |
608 gtk_entry_set_text(GTK_ENTRY(yearEntry), entry); | |
609 free(entry); | |
610 entry = g_filename_display_name(p_Filename); | |
611 gtk_entry_set_text(GTK_ENTRY(fileEntry), entry); | |
612 free(entry); | |
613 freeTags(tags); | |
614 vfs_fclose(input); | |
615 } | |
616 else | |
617 { | |
618 char* temp = g_strdup_printf("[xmms-musepack] mpcFileInfoBox is unable to read tags from %s", p_Filename); | |
619 perror(temp); | |
620 free(temp); | |
621 } | |
622 | |
623 char* name = g_filename_display_basename(p_Filename); | |
1304
f34112ab9101
As usual, "i18n" modifications.
Stany HENRY <StrassBoy@gmail.com>
parents:
1185
diff
changeset
|
624 char* text = g_strdup_printf(_("File Info - %s"), name); |
232 | 625 free(name); |
626 gtk_window_set_title(GTK_WINDOW(infoBox), text); | |
627 free(text); | |
628 | |
629 gtk_widget_show_all(infoBox); | |
630 } | |
631 } | |
632 | |
1044
b1128efde471
[svn] - get rid of all warnings gcc 4.2.0 emits with my build configuration.
yaz
parents:
659
diff
changeset
|
633 static void mpcGtkPrintLabel(GtkWidget* widget, const char* format,...) |
232 | 634 { |
635 va_list args; | |
636 | |
637 va_start(args, format); | |
638 char* temp = g_strdup_vprintf(format, args); | |
639 va_end(args); | |
640 | |
641 gtk_label_set_text(GTK_LABEL(widget), temp); | |
642 free(temp); | |
643 } | |
644 | |
1044
b1128efde471
[svn] - get rid of all warnings gcc 4.2.0 emits with my build configuration.
yaz
parents:
659
diff
changeset
|
645 static GtkWidget* mpcGtkTagLabel(const char* p_Text, int a, int b, int c, int d, GtkWidget* p_Box) |
232 | 646 { |
647 GtkWidget* label = gtk_label_new(p_Text); | |
648 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); | |
649 gtk_table_attach(GTK_TABLE(p_Box), label, a, b, c, d, GTK_FILL, GTK_FILL, 5, 5); | |
650 return label; | |
651 } | |
652 | |
653 static GtkWidget* mpcGtkTagEntry(int a, int b, int c, int d, int p_Size, GtkWidget* p_Box) | |
654 { | |
655 GtkWidget* entry; | |
656 if(p_Size == 0) | |
657 entry = gtk_entry_new(); | |
658 else | |
659 entry = gtk_entry_new_with_max_length(p_Size); | |
660 gtk_table_attach(GTK_TABLE(p_Box), entry, a, b, c, d, | |
661 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND | GTK_SHRINK), | |
662 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND | GTK_SHRINK), 0, 5); | |
663 return entry; | |
664 } | |
665 | |
666 static GtkWidget* mpcGtkLabel(GtkWidget* p_Box) | |
667 { | |
668 GtkWidget* label = gtk_label_new(""); | |
669 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
670 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); | |
671 gtk_box_pack_start(GTK_BOX(p_Box), label, FALSE, FALSE, 0); | |
672 return label; | |
673 } | |
674 | |
1044
b1128efde471
[svn] - get rid of all warnings gcc 4.2.0 emits with my build configuration.
yaz
parents:
659
diff
changeset
|
675 static GtkWidget* mpcGtkButton(const char* p_Text, GtkWidget* p_Box) |
232 | 676 { |
677 GtkWidget* button = gtk_button_new_with_label(p_Text); | |
678 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); | |
679 gtk_box_pack_start(GTK_BOX(p_Box), button, TRUE, TRUE, 0); | |
680 return button; | |
681 } | |
682 | |
683 static void removeTags(GtkWidget * w, gpointer data) | |
684 { | |
685 File oFile(gtk_entry_get_text(GTK_ENTRY(widgets.fileEntry))); | |
686 oFile.remove(); | |
687 oFile.save(); | |
688 closeInfoBox(NULL, NULL); | |
689 } | |
690 | |
691 static void saveTags(GtkWidget* w, gpointer data) | |
692 { | |
693 File oFile(gtk_entry_get_text(GTK_ENTRY(widgets.fileEntry))); | |
694 Tag* poTag = oFile.tag(); | |
695 | |
696 char* cAlbum = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.albumEntry))); | |
697 char* cArtist = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.artistEntry))); | |
698 char* cTitle = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.titleEntry))); | |
699 char* cGenre = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.genreEntry))); | |
700 char* cComment = g_strdup(gtk_entry_get_text(GTK_ENTRY(widgets.commentEntry))); | |
701 | |
702 const String album = String(cAlbum, TagLib::String::UTF8); | |
703 const String artist = String(cArtist, TagLib::String::UTF8); | |
704 const String title = String(cTitle, TagLib::String::UTF8); | |
705 const String genre = String(cGenre, TagLib::String::UTF8); | |
706 const String comment = String(cComment, TagLib::String::UTF8); | |
707 | |
708 poTag->setAlbum(album); | |
709 poTag->setArtist(artist); | |
710 poTag->setTitle(title); | |
711 poTag->setGenre(genre); | |
712 poTag->setComment(comment); | |
713 poTag->setYear(atoi(gtk_entry_get_text(GTK_ENTRY(widgets.yearEntry)))); | |
714 poTag->setTrack(atoi(gtk_entry_get_text(GTK_ENTRY(widgets.trackEntry)))); | |
715 | |
716 free(cAlbum); | |
717 free(cArtist); | |
718 free(cTitle); | |
719 free(cGenre); | |
720 free(cComment); | |
721 | |
722 oFile.save(); | |
723 closeInfoBox(NULL, NULL); | |
724 } | |
725 | |
726 static void closeInfoBox(GtkWidget* w, gpointer data) | |
727 { | |
728 gtk_widget_destroy(widgets.infoBox); | |
729 widgets.infoBox = NULL; | |
730 } | |
731 | |
732 static char* mpcGenerateTitle(const MpcInfo& p_Tags, char* p_Filename) | |
733 { | |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
734 Tuple* tuple = mpcGetSongTuple(p_Filename); |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
735 |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
736 char* title = tuple_formatter_process_string(tuple, cfg.gentitle_format); |
232 | 737 |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
738 if (!*title) |
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
739 title = g_strdup(tuple_get_string(tuple, "file-name")); |
232 | 740 |
1438
dc3e28d3b92a
mpc: convert, wma: fixes
William Pitcock <nenolod@atheme-project.org>
parents:
1395
diff
changeset
|
741 mowgli_object_unref((void *) tuple); |
232 | 742 return title; |
743 } | |
744 | |
745 static void* endThread(char* p_FileName, VFSFile * p_FileHandle, bool release) | |
746 { | |
747 free(p_FileName); | |
748 if(release) | |
749 lockRelease(); | |
750 if(mpcDecoder.isError) | |
751 { | |
752 perror(mpcDecoder.isError); | |
753 free(mpcDecoder.isError); | |
754 mpcDecoder.isError = NULL; | |
755 } | |
756 setAlive(false); | |
757 if(p_FileHandle) | |
758 vfs_fclose(p_FileHandle); | |
759 if(track.display) | |
760 { | |
761 free(track.display); | |
762 track.display = NULL; | |
763 } | |
764 return 0; | |
765 } | |
766 | |
767 static void* decodeStream(void* data) | |
768 { | |
769 lockAcquire(); | |
770 char* filename = static_cast<char*> (data); | |
771 VFSFile *input = vfs_fopen(filename, "rb"); | |
772 if (!input) | |
773 { | |
774 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to open %s", filename); | |
775 return endThread(filename, input, true); | |
776 } | |
777 | |
778 mpc_reader_file reader; | |
779 mpc_reader_setup_file_vfs(&reader, input); | |
780 | |
781 mpc_streaminfo info; | |
782 if (mpc_streaminfo_read(&info, &reader.reader) != ERROR_CODE_OK) | |
783 { | |
784 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to read %s", filename); | |
785 return endThread(filename, input, true); | |
786 } | |
787 | |
788 MpcInfo tags = getTags(filename); | |
789 track.display = mpcGenerateTitle(tags, filename); | |
790 track.length = static_cast<int> (1000 * mpc_streaminfo_get_length(&info)); | |
791 track.bitrate = static_cast<int> (info.average_bitrate); | |
792 track.sampleFreq = info.sample_freq; | |
793 track.channels = info.channels; | |
794 freeTags(tags); | |
795 | |
796 MpcPlugin.set_info(track.display, track.length, track.bitrate, track.sampleFreq, track.channels); | |
797 | |
798 mpc_decoder decoder; | |
799 mpc_decoder_setup(&decoder, &reader.reader); | |
800 if (!mpc_decoder_initialize(&decoder, &info)) | |
801 { | |
802 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to initialize decoder on %s", filename); | |
803 return endThread(filename, input, true); | |
804 } | |
805 | |
806 setReplaygain(info, decoder); | |
807 | |
808 MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH]; | |
809 char xmmsBuffer[MPC_DECODER_BUFFER_LENGTH * 4]; | |
810 | |
811 if (!MpcPlugin.output->open_audio(FMT_S16_LE, track.sampleFreq, track.channels)) | |
812 { | |
813 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] decodeStream is unable to open an audio output"); | |
814 return endThread(filename, input, true); | |
815 } | |
816 else | |
817 { | |
818 mpcDecoder.isOutput = true; | |
819 } | |
820 | |
821 lockRelease(); | |
822 | |
823 int counter = 2 * track.sampleFreq / 3; | |
824 while (isAlive()) | |
825 { | |
826 if (getOffset() != -1) | |
827 { | |
828 mpc_decoder_seek_seconds(&decoder, mpcDecoder.offset); | |
829 setOffset(-1); | |
830 } | |
831 | |
832 lockAcquire(); | |
833 short iPlaying = MpcPlugin.output->buffer_playing()? 1 : 0; | |
834 int iFree = MpcPlugin.output->buffer_free(); | |
835 if (!mpcDecoder.isPause && iFree >= ((1152 * 4) << iPlaying)) | |
836 { | |
837 unsigned status = processBuffer(sampleBuffer, xmmsBuffer, decoder); | |
838 if (status == (unsigned) (-1)) | |
839 { | |
840 mpcDecoder.isError = g_strdup_printf("[xmms-musepack] error from internal decoder on %s", filename); | |
841 return endThread(filename, input, true); | |
842 } | |
843 if (status == 0 && iPlaying == 0) | |
844 return endThread(filename, input, true); | |
845 | |
846 lockRelease(); | |
847 | |
848 if(pluginConfig.dynamicBitrate) | |
849 { | |
850 counter -= status; | |
851 if(counter < 0) | |
852 { | |
853 MpcPlugin.set_info(track.display, track.length, track.bitrate, track.sampleFreq, track.channels); | |
854 counter = 2 * track.sampleFreq / 3; | |
855 } | |
856 } | |
857 } | |
858 else | |
859 { | |
860 lockRelease(); | |
861 xmms_usleep(10000); | |
862 } | |
863 } | |
864 return endThread(filename, input, false); | |
865 } | |
866 | |
867 static int processBuffer(MPC_SAMPLE_FORMAT* sampleBuffer, char* xmmsBuffer, mpc_decoder& decoder) | |
868 { | |
869 mpc_uint32_t vbrAcc = 0; | |
870 mpc_uint32_t vbrUpd = 0; | |
871 | |
872 unsigned status = mpc_decoder_decode(&decoder, sampleBuffer, &vbrAcc, &vbrUpd); | |
873 copyBuffer(sampleBuffer, xmmsBuffer, status); | |
874 | |
875 if (pluginConfig.dynamicBitrate) | |
876 { | |
877 track.bitrate = static_cast<int> (vbrUpd * track.sampleFreq / 1152); | |
878 } | |
879 | |
880 produce_audio(MpcPlugin.output->written_time(), FMT_S16_LE, track.channels, status * 4, xmmsBuffer, NULL); | |
881 return status; | |
882 } | |
883 | |
884 static void setReplaygain(mpc_streaminfo& info, mpc_decoder& decoder) | |
885 { | |
886 if(!pluginConfig.replaygain && !pluginConfig.clipPrevention) | |
887 return; | |
888 | |
889 int peak = pluginConfig.albumGain ? info.peak_album : info.peak_title; | |
890 double gain = pluginConfig.albumGain ? info.gain_album : info.gain_title; | |
891 | |
892 if(!peak) | |
893 peak = 32767; | |
894 if(!gain) | |
895 gain = 1.; | |
896 | |
897 double clip = 32767. / peak; | |
898 gain = exp((M_LN10 / 2000.) * gain); | |
899 | |
900 if(pluginConfig.clipPrevention && !pluginConfig.replaygain) | |
901 gain = clip; | |
902 else if(pluginConfig.replaygain && pluginConfig.clipPrevention) | |
903 if(clip < gain) | |
904 gain = clip; | |
905 | |
906 mpc_decoder_scale_output(&decoder, gain); | |
907 } | |
908 | |
909 inline static void lockAcquire() | |
910 { | |
911 g_static_mutex_lock(&threadMutex); | |
912 } | |
913 | |
914 inline static void lockRelease() | |
915 { | |
916 g_static_mutex_unlock(&threadMutex); | |
917 } | |
918 | |
919 inline static bool isAlive() | |
920 { | |
921 lockAcquire(); | |
922 bool isAlive = mpcDecoder.isAlive; | |
923 lockRelease(); | |
924 return isAlive; | |
925 } | |
926 | |
927 inline static bool isPause() | |
928 { | |
929 lockAcquire(); | |
930 bool isPause = mpcDecoder.isPause; | |
931 lockRelease(); | |
932 return isPause; | |
933 } | |
934 | |
935 inline static void setAlive(bool isAlive) | |
936 { | |
937 lockAcquire(); | |
938 mpcDecoder.isAlive = isAlive; | |
939 lockRelease(); | |
940 } | |
941 | |
942 inline static double getOffset() | |
943 { | |
944 lockAcquire(); | |
945 double offset = mpcDecoder.offset; | |
946 lockRelease(); | |
947 return offset; | |
948 } | |
949 | |
950 inline static void setOffset(double offset) | |
951 { | |
952 lockAcquire(); | |
953 mpcDecoder.offset = offset; | |
954 lockRelease(); | |
955 } |