Mercurial > audlegacy
annotate Plugins/Input/adplug/adplug-xmms.cc @ 1103:8bdcd65a57b7 trunk
[svn] Updating of some deprecated GTK functions.
author | nemo |
---|---|
date | Tue, 23 May 2006 16:05:38 -0700 |
parents | f804ff3a4899 |
children | b63b5c47efd9 |
rev | line source |
---|---|
359 | 1 /* |
2 AdPlug/XMMS - AdPlug XMMS Plugin | |
3 Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> | |
4 | |
5 AdPlug/XMMS is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 of the License, or (at your option) any later version. | |
9 | |
10 This plugin is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this plugin; if not, write to the Free Software | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 | |
20 #include <algorithm> | |
21 #include <sstream> | |
22 #include <stdlib.h> | |
23 #include <stdio.h> | |
24 #include <sys/types.h> | |
25 #include <gtk/gtk.h> | |
865 | 26 #include <glib/gi18n.h> |
359 | 27 #include "adplug.h" |
28 #include "emuopl.h" | |
29 #include "silentopl.h" | |
30 #include "players.h" | |
31 #include "audacious/plugin.h" | |
32 #include "libaudacious/util.h" | |
33 #include "libaudacious/configdb.h" | |
414
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
34 extern "C" { |
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
35 #include "audacious/output.h" |
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
36 } |
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
37 |
359 | 38 |
39 /***** Defines *****/ | |
40 | |
41 // Version string | |
849 | 42 #define ADPLUG_NAME "AdPlug (AdLib Sound Player)" |
359 | 43 |
44 // Sound buffer size in samples | |
45 #define SNDBUFSIZE 512 | |
46 | |
47 // AdPlug's 8 and 16 bit audio formats | |
48 #define FORMAT_8 FMT_U8 | |
49 #define FORMAT_16 FMT_S16_NE | |
50 | |
51 // Default file name of AdPlug's database file | |
52 #define ADPLUGDB_FILE "adplug.db" | |
53 | |
54 // Default AdPlug user's configuration subdirectory | |
55 #define ADPLUG_CONFDIR ".adplug" | |
56 | |
57 /***** Global variables *****/ | |
58 | |
59 extern "C" InputPlugin adplug_ip; | |
60 static gboolean audio_error = FALSE; | |
869 | 61 GtkWidget *about_win = NULL; |
359 | 62 |
63 // Configuration (and defaults) | |
64 static struct { | |
65 gint freq; | |
361
db298f2d3dd9
[svn] Detect files by content; remove quick detect.
chainsaw
parents:
359
diff
changeset
|
66 gboolean bit16, stereo, endless; |
359 | 67 CPlayers players; |
361
db298f2d3dd9
[svn] Detect files by content; remove quick detect.
chainsaw
parents:
359
diff
changeset
|
68 } cfg = { 44100l, true, false, false, CAdPlug::players }; |
359 | 69 |
70 // Player variables | |
71 static struct { | |
72 CPlayer *p; | |
73 CAdPlugDatabase *db; | |
74 unsigned int subsong, songlength; | |
75 int seek; | |
76 char filename[PATH_MAX]; | |
77 char *songtitle; | |
78 float time_ms; | |
79 bool playing; | |
80 GThread *play_thread; | |
81 GtkLabel *infobox; | |
82 GtkDialog *infodlg; | |
83 } plr = { 0, 0, 0, 0, -1, "", NULL, 0.0f, false, 0, NULL, NULL }; | |
84 | |
85 /***** Debugging *****/ | |
86 | |
87 #ifdef DEBUG | |
88 | |
89 #include <stdarg.h> | |
90 | |
91 static void dbg_printf(const char *fmt, ...) | |
92 { | |
93 va_list argptr; | |
94 | |
95 va_start(argptr, fmt); | |
96 vfprintf(stderr, fmt, argptr); | |
97 va_end(argptr); | |
98 } | |
99 | |
100 #else | |
101 | |
102 static void dbg_printf(const char *fmt, ...) | |
103 { } | |
104 | |
105 #endif | |
106 | |
107 /***** [Dialog]: Utility functions *****/ | |
108 | |
109 static GtkWidget *make_framed(GtkWidget *what, const gchar *label) | |
110 { | |
111 GtkWidget *framebox = gtk_frame_new(label); | |
112 | |
113 gtk_container_add(GTK_CONTAINER(framebox), what); | |
114 return framebox; | |
115 } | |
116 | |
117 static GtkWidget *print_left(const gchar *text) | |
118 { | |
119 GtkLabel *label = GTK_LABEL(gtk_label_new(text)); | |
120 | |
121 gtk_label_set_justify(label, GTK_JUSTIFY_LEFT); | |
122 gtk_misc_set_padding(GTK_MISC(label), 2, 2); | |
123 return GTK_WIDGET(label); | |
124 } | |
125 | |
126 static void MessageBox(const char *title, const char *text, const char *button) | |
127 { | |
128 char *tmptitle = (char *)malloc(strlen(title) + 1), | |
129 *tmptxt = (char *)malloc(strlen(text) + 1), | |
130 *tmpbutton = (char *)malloc(strlen(button) + 1); | |
131 | |
132 strcpy(tmptitle, title); strcpy(tmptxt, text); strcpy(tmpbutton, button); | |
133 | |
134 GtkWidget *msgbox = xmms_show_message(tmptitle, tmptxt, tmpbutton, FALSE, | |
1103 | 135 G_CALLBACK(gtk_widget_destroyed), &msgbox); |
359 | 136 |
137 free(tmptitle); free(tmptxt); free(tmpbutton); | |
138 } | |
139 | |
140 /***** Dialog boxes *****/ | |
141 | |
142 static void adplug_about(void) | |
143 { | |
865 | 144 if(!about_win) |
145 { | |
146 gchar * about_title = g_strjoin( "" , _("About ") , ADPLUG_NAME , NULL ); | |
147 const gchar * version_text = CAdPlug::get_version().c_str(); | |
148 gchar * about_text = g_strjoin( "" , ADPLUG_NAME , | |
149 _("\nCopyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net>\n\n" | |
150 "This plugin is released under the terms and conditions of the GNU LGPL.\n" | |
151 "See http://www.gnu.org/licenses/lgpl.html for details." | |
152 "\n\nThis plugin uses the AdPlug library, which is copyright (C) Simon Peter, et al.\n" | |
153 "Linked AdPlug library version: ") , | |
154 version_text , NULL ); | |
155 about_win = xmms_show_message( about_title , about_text , _("Ok") , FALSE , NULL , NULL ); | |
1103 | 156 g_signal_connect( G_OBJECT(about_win) , "destroy" , |
157 G_CALLBACK(gtk_widget_destroyed), &about_win ); | |
865 | 158 g_free( about_text ); |
159 g_free( about_title ); | |
160 } | |
161 gtk_widget_show( about_win ); | |
359 | 162 } |
163 | |
164 static void close_config_box_ok(GtkButton *button, GPtrArray *rblist) | |
165 { | |
166 // Apply configuration settings | |
167 cfg.bit16 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 0))); | |
168 cfg.stereo = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 1))); | |
169 | |
170 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 2)))) cfg.freq = 11025; | |
171 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 3)))) cfg.freq = 22050; | |
172 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 4)))) cfg.freq = 44100; | |
173 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 5)))) cfg.freq = 48000; | |
174 | |
175 cfg.endless = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 6))); | |
176 | |
361
db298f2d3dd9
[svn] Detect files by content; remove quick detect.
chainsaw
parents:
359
diff
changeset
|
177 cfg.players = *(CPlayers *)g_ptr_array_index(rblist, 7); |
db298f2d3dd9
[svn] Detect files by content; remove quick detect.
chainsaw
parents:
359
diff
changeset
|
178 delete (CPlayers *)g_ptr_array_index(rblist, 7); |
359 | 179 |
180 g_ptr_array_free(rblist, FALSE); | |
181 } | |
182 | |
183 static void close_config_box_cancel(GtkButton *button, GPtrArray *rblist) | |
184 { | |
361
db298f2d3dd9
[svn] Detect files by content; remove quick detect.
chainsaw
parents:
359
diff
changeset
|
185 delete (CPlayers *)g_ptr_array_index(rblist, 7); |
359 | 186 g_ptr_array_free(rblist, FALSE); |
187 } | |
188 | |
189 static void config_fl_row_select(GtkCList *fl, gint row, gint col, | |
190 GdkEventButton *event, CPlayers *pl) | |
191 { | |
192 pl->push_back((CPlayerDesc *)gtk_clist_get_row_data(fl, row)); | |
193 pl->unique(); | |
194 } | |
195 | |
196 static void config_fl_row_unselect(GtkCList *fl, gint row, gint col, | |
197 GdkEventButton *event, CPlayers *pl) | |
198 { | |
199 pl->remove((CPlayerDesc *)gtk_clist_get_row_data(fl, row)); | |
200 } | |
201 | |
202 static void adplug_config(void) | |
203 { | |
204 GtkDialog *config_dlg = GTK_DIALOG(gtk_dialog_new()); | |
205 GtkNotebook *notebook = GTK_NOTEBOOK(gtk_notebook_new()); | |
206 GtkTable *table; | |
207 GtkTooltips *tooltips = gtk_tooltips_new(); | |
208 GPtrArray *rblist = g_ptr_array_new(); | |
209 | |
210 gtk_window_set_title(GTK_WINDOW(config_dlg), "AdPlug :: Configuration"); | |
211 gtk_window_set_policy(GTK_WINDOW(config_dlg), FALSE, FALSE, TRUE); // Window is auto sized | |
212 gtk_window_set_modal(GTK_WINDOW(config_dlg), TRUE); | |
213 gtk_container_add(GTK_CONTAINER(config_dlg->vbox), GTK_WIDGET(notebook)); | |
214 | |
215 // Add Ok & Cancel buttons | |
216 { | |
217 GtkWidget *button; | |
218 | |
219 button = gtk_button_new_with_label("Ok"); | |
1103 | 220 g_signal_connect(G_OBJECT(button), "clicked", |
221 G_CALLBACK(close_config_box_ok), | |
359 | 222 (gpointer)rblist); |
1103 | 223 g_signal_connect_data(G_OBJECT(button), "clicked", |
224 G_CALLBACK(gtk_widget_destroy), | |
225 GTK_OBJECT(config_dlg),NULL,(GConnectFlags) (G_CONNECT_AFTER|G_CONNECT_SWAPPED)); | |
359 | 226 gtk_container_add(GTK_CONTAINER(config_dlg->action_area), button); |
227 | |
228 button = gtk_button_new_with_label("Cancel"); | |
1103 | 229 g_signal_connect(G_OBJECT(button), "clicked", |
230 G_CALLBACK(close_config_box_cancel), | |
359 | 231 (gpointer)rblist); |
1103 | 232 g_signal_connect_swapped(G_OBJECT(button), "clicked", |
233 G_CALLBACK(gtk_widget_destroy), | |
359 | 234 GTK_OBJECT(config_dlg)); |
235 gtk_container_add(GTK_CONTAINER(config_dlg->action_area), button); | |
236 } | |
237 | |
238 /***** Page 1: General *****/ | |
239 | |
240 table = GTK_TABLE(gtk_table_new(1, 2, TRUE)); | |
241 gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); | |
242 gtk_notebook_append_page(notebook, GTK_WIDGET(table), print_left("General")); | |
243 | |
244 // Add "Sound quality" section | |
245 { | |
246 GtkTable *sqt = GTK_TABLE(gtk_table_new(2, 2, FALSE)); | |
247 GtkVBox *fvb; | |
248 GtkRadioButton *rb; | |
249 | |
250 gtk_table_set_row_spacings(sqt, 5); | |
251 gtk_table_set_col_spacings(sqt, 5); | |
252 gtk_table_attach_defaults(table, make_framed(GTK_WIDGET(sqt), "Sound quality"), | |
253 0, 1, 0, 1); | |
254 | |
255 // Add "Resolution" section | |
256 fvb = GTK_VBOX(gtk_vbox_new(TRUE, 0)); | |
257 gtk_table_attach_defaults(sqt, make_framed(GTK_WIDGET(fvb), "Resolution"), | |
258 0, 1, 0, 1); | |
259 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "8bit")); | |
260 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), !cfg.bit16); | |
261 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
262 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "16bit")); | |
263 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), cfg.bit16); | |
264 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
265 g_ptr_array_add(rblist, (gpointer)rb); | |
266 | |
267 // Add "Channels" section | |
268 fvb = GTK_VBOX(gtk_vbox_new(TRUE, 0)); | |
269 gtk_table_attach_defaults(sqt, make_framed(GTK_WIDGET(fvb), "Channels"), | |
270 0, 1, 1, 2); | |
271 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "Mono")); | |
272 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), !cfg.stereo); | |
273 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
274 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "Stereo")); | |
275 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), cfg.stereo); | |
276 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
277 gtk_tooltips_set_tip(tooltips, GTK_WIDGET(rb), | |
278 "Setting stereo is not recommended, unless you need to. " | |
279 "This won't add any stereo effects to the sound - OPL2 " | |
280 "is just mono - but eats up more CPU power!", NULL); | |
281 g_ptr_array_add(rblist, (gpointer)rb); | |
282 | |
283 // Add "Frequency" section | |
284 fvb = GTK_VBOX(gtk_vbox_new(TRUE, 0)); | |
285 gtk_table_attach_defaults(sqt, make_framed(GTK_WIDGET(fvb), "Frequency"), | |
286 1, 2, 0, 2); | |
287 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "11025")); | |
288 if(cfg.freq == 11025) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE); | |
289 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
290 g_ptr_array_add(rblist, (gpointer)rb); | |
291 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "22050")); | |
292 if(cfg.freq == 22050) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE); | |
293 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
294 g_ptr_array_add(rblist, (gpointer)rb); | |
295 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "44100")); | |
296 if(cfg.freq == 44100) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE); | |
297 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
298 g_ptr_array_add(rblist, (gpointer)rb); | |
299 rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "48000")); | |
300 if(cfg.freq == 48000) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE); | |
301 gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb)); | |
302 g_ptr_array_add(rblist, (gpointer)rb); | |
303 } | |
304 | |
305 // Add "Playback" section | |
306 { | |
307 GtkVBox *vb = GTK_VBOX(gtk_vbox_new(FALSE, 0)); | |
308 GtkCheckButton *cb; | |
309 | |
310 gtk_table_attach_defaults(table, make_framed(GTK_WIDGET(vb), "Playback"), | |
311 1, 2, 0, 1); | |
312 | |
313 cb = GTK_CHECK_BUTTON(gtk_check_button_new_with_label("Detect songend")); | |
314 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb), !cfg.endless); | |
315 gtk_container_add(GTK_CONTAINER(vb), GTK_WIDGET(cb)); | |
316 gtk_tooltips_set_tip(tooltips, GTK_WIDGET(cb), | |
317 "If enabled, XMMS will detect a song's ending, stop " | |
318 "it and advance in the playlist. If disabled, XMMS " | |
319 "won't take notice of a song's ending and loop it all " | |
320 "over again and again.", NULL); | |
321 g_ptr_array_add(rblist, (gpointer)cb); | |
322 } | |
323 | |
324 /***** Page 2: Formats *****/ | |
325 | |
326 table = GTK_TABLE(gtk_table_new(1, 1, TRUE)); | |
327 gtk_notebook_append_page(notebook, GTK_WIDGET(table), print_left("Formats")); | |
328 | |
329 // Add "Format selection" section | |
330 { | |
331 GtkHBox *vb = GTK_HBOX(gtk_hbox_new(FALSE, 0)); | |
332 gtk_table_attach_defaults(table, make_framed(GTK_WIDGET(vb), "Format selection"), | |
333 0, 1, 0, 1); | |
334 // Add scrollable list | |
335 { | |
336 gchar *rowstr[] = {"Format", "Extension"}; | |
337 GtkEventBox *eventbox = GTK_EVENT_BOX(gtk_event_box_new()); | |
338 GtkScrolledWindow *formatswnd = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); | |
339 GtkCList *fl = GTK_CLIST(gtk_clist_new_with_titles(2, rowstr)); | |
340 CPlayers::const_iterator i; | |
341 unsigned int j; | |
342 gtk_clist_set_selection_mode(fl, GTK_SELECTION_MULTIPLE); | |
343 | |
344 // Build list | |
345 for(i = CAdPlug::players.begin(); i != CAdPlug::players.end(); i++) { | |
346 gint rownum; | |
347 | |
348 gchar *rws[2]; | |
349 rws[0] = g_strdup((*i)->filetype.c_str()); | |
350 rws[1] = g_strdup((*i)->get_extension(0)); | |
351 for(j = 1; (*i)->get_extension(j); j++) | |
352 rws[1] = g_strjoin(", ", rws[1], (*i)->get_extension(j), NULL); | |
353 rownum = gtk_clist_append(fl, rws); | |
354 g_free(rws[0]); g_free(rws[1]); | |
355 gtk_clist_set_row_data(fl, rownum, (gpointer)(*i)); | |
356 if(find(cfg.players.begin(), cfg.players.end(), *i) != cfg.players.end()) | |
357 gtk_clist_select_row(fl, rownum, 0); | |
358 } | |
359 | |
360 gtk_clist_columns_autosize(fl); | |
361 gtk_scrolled_window_set_policy(formatswnd, GTK_POLICY_AUTOMATIC, | |
362 GTK_POLICY_AUTOMATIC); | |
363 gpointer pl = (gpointer)new CPlayers(cfg.players); | |
1103 | 364 g_signal_connect(G_OBJECT(fl), "select-row", |
365 G_CALLBACK(config_fl_row_select), pl); | |
366 g_signal_connect(G_OBJECT(fl), "unselect-row", | |
367 G_CALLBACK(config_fl_row_unselect), pl); | |
359 | 368 gtk_container_add(GTK_CONTAINER(formatswnd), GTK_WIDGET(fl)); |
369 gtk_container_add(GTK_CONTAINER(eventbox), GTK_WIDGET(formatswnd)); | |
370 gtk_container_add(GTK_CONTAINER(vb), GTK_WIDGET(eventbox)); | |
371 gtk_tooltips_set_tip(tooltips, GTK_WIDGET(eventbox), | |
372 "Selected file types will be recognized and played " | |
373 "back by this plugin. Deselected types will be " | |
374 "ignored to make room for other plugins to play " | |
375 "these files.", NULL); | |
376 g_ptr_array_add(rblist, pl); | |
377 } | |
378 } | |
379 | |
380 // Show window | |
381 gtk_widget_show_all(GTK_WIDGET(config_dlg)); | |
382 } | |
383 | |
384 static void add_instlist(GtkCList *instlist, const char *t1, const char *t2) | |
385 { | |
386 gchar *rowstr[2]; | |
387 | |
388 rowstr[0] = g_strdup(t1); rowstr[1] = g_strdup(t2); | |
389 gtk_clist_append(instlist, rowstr); | |
390 g_free(rowstr[0]); g_free(rowstr[1]); | |
391 } | |
392 | |
393 static CPlayer *factory(const std::string &filename, Copl *newopl) | |
394 { | |
395 CPlayers::const_iterator i; | |
396 | |
397 dbg_printf("factory(\"%s\",opl): ", filename.c_str()); | |
361
db298f2d3dd9
[svn] Detect files by content; remove quick detect.
chainsaw
parents:
359
diff
changeset
|
398 return CAdPlug::factory(filename, newopl, cfg.players); |
359 | 399 } |
400 | |
401 static void adplug_stop(void); | |
402 static void adplug_play(char *filename); | |
403 | |
404 static void subsong_slider(GtkAdjustment *adj) | |
405 { | |
406 adplug_stop(); | |
407 plr.subsong = (unsigned int)adj->value - 1; | |
408 adplug_play(plr.filename); | |
409 } | |
410 | |
411 static void close_infobox(GtkDialog *infodlg) | |
412 { | |
413 // Forget our references to the instance of the "currently playing song" info | |
414 // box. But only if we're really destroying that one... ;) | |
415 if(infodlg == plr.infodlg) { | |
416 plr.infobox = NULL; | |
417 plr.infodlg = NULL; | |
418 } | |
419 } | |
420 | |
421 static void adplug_info_box(char *filename) | |
422 { | |
423 CSilentopl tmpopl; | |
424 CPlayer *p = (strcmp(filename, plr.filename) || !plr.p) ? | |
425 factory(filename, &tmpopl) : plr.p; | |
426 | |
427 if(!p) return; // bail out if no player could be created | |
428 if(p == plr.p && plr.infodlg) return; // only one info box for active song | |
429 | |
430 std::ostringstream infotext; | |
431 unsigned int i; | |
432 GtkDialog *infobox = GTK_DIALOG(gtk_dialog_new()); | |
433 GtkButton *okay_button = GTK_BUTTON(gtk_button_new_with_label("Ok")); | |
869 | 434 |
435 GtkVBox *box = GTK_VBOX(gtk_vbox_new(TRUE,2)); | |
359 | 436 GtkHBox *hbox = GTK_HBOX(gtk_hbox_new(TRUE, 2)); |
878
f804ff3a4899
[svn] Pending proper layout, make a little less vertical at least.
nemo
parents:
869
diff
changeset
|
437 GtkHBox *hbox2 = GTK_HBOX(gtk_hbox_new(TRUE, 2)); |
359 | 438 |
439 // Build file info box | |
440 gtk_window_set_title(GTK_WINDOW(infobox), "AdPlug :: File Info"); | |
441 gtk_window_set_policy(GTK_WINDOW(infobox), FALSE, FALSE, TRUE); // Window is auto sized | |
869 | 442 |
443 gtk_container_add(GTK_CONTAINER(infobox->vbox), GTK_WIDGET(box)); | |
444 // Former packer layout, for future reproduction | |
445 // gtk_packer_set_default_border_width(packer, 2); | |
446 | |
359 | 447 gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE); |
1103 | 448 g_signal_connect_swapped(G_OBJECT(okay_button), "clicked", |
449 G_CALLBACK(gtk_widget_destroy), | |
359 | 450 GTK_OBJECT(infobox)); |
1103 | 451 g_signal_connect(G_OBJECT(infobox), "destroy", |
452 G_CALLBACK(close_infobox), 0); | |
359 | 453 gtk_container_add(GTK_CONTAINER(infobox->action_area), GTK_WIDGET(okay_button)); |
454 | |
455 // Add filename section | |
869 | 456 // Former packer layout, for future reproduction |
457 // gtk_packer_add_defaults(packer, make_framed(print_left(filename), "Filename"), | |
458 // GTK_SIDE_TOP, GTK_ANCHOR_CENTER, GTK_FILL_X); | |
878
f804ff3a4899
[svn] Pending proper layout, make a little less vertical at least.
nemo
parents:
869
diff
changeset
|
459 gtk_box_pack_end(GTK_BOX(box), GTK_WIDGET(hbox2), TRUE, TRUE, 2); |
869 | 460 gtk_box_pack_end(GTK_BOX(box), make_framed(print_left(filename), "Filename"), TRUE, TRUE, 2); |
359 | 461 |
462 // Add "Song info" section | |
463 infotext << "Title: " << p->gettitle() << std::endl << | |
464 "Author: " << p->getauthor() << std::endl << | |
465 "File Type: " << p->gettype() << std::endl << | |
466 "Subsongs: " << p->getsubsongs() << std::endl << | |
467 "Instruments: " << p->getinstruments(); | |
468 if(plr.p == p) | |
469 infotext << std::ends; | |
470 else { | |
471 infotext << std::endl << "Orders: " << p->getorders() << std::endl << | |
472 "Patterns: " << p->getpatterns() << std::ends; | |
473 } | |
474 gtk_container_add(GTK_CONTAINER(hbox), | |
475 make_framed(print_left(infotext.str().c_str()), "Song")); | |
476 | |
477 // Add "Playback info" section if currently playing | |
478 if(plr.p == p) { | |
479 plr.infobox = GTK_LABEL(gtk_label_new("")); | |
480 gtk_label_set_justify(plr.infobox, GTK_JUSTIFY_LEFT); | |
481 gtk_misc_set_padding(GTK_MISC(plr.infobox), 2, 2); | |
482 gtk_container_add(GTK_CONTAINER(hbox), | |
483 make_framed(GTK_WIDGET(plr.infobox), "Playback")); | |
484 } | |
869 | 485 |
486 // Former packer layout, for future reproduction | |
487 // gtk_packer_add_defaults(packer, GTK_WIDGET(hbox), GTK_SIDE_TOP, | |
488 // GTK_ANCHOR_CENTER, GTK_FILL_X); | |
878
f804ff3a4899
[svn] Pending proper layout, make a little less vertical at least.
nemo
parents:
869
diff
changeset
|
489 gtk_box_pack_end(GTK_BOX(hbox2), GTK_WIDGET(hbox), TRUE, TRUE, 2); |
359 | 490 |
491 // Add instrument names section | |
492 if(p->getinstruments()) { | |
493 GtkScrolledWindow *instwnd = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); | |
494 GtkCList *instnames; | |
495 gchar tmpstr[10]; | |
496 | |
497 { | |
498 gchar *rowstr[] = {"#","Instrument name"}; | |
499 instnames = GTK_CLIST(gtk_clist_new_with_titles(2, rowstr)); | |
500 } | |
501 gtk_clist_set_column_justification(instnames, 0, GTK_JUSTIFY_RIGHT); | |
502 | |
503 for(i=0;i<p->getinstruments();i++) { | |
504 sprintf(tmpstr, "%d", i + 1); | |
505 add_instlist(instnames, tmpstr, p->getinstrument(i).c_str()); | |
506 } | |
507 | |
508 gtk_clist_columns_autosize(instnames); | |
509 gtk_scrolled_window_set_policy(instwnd, GTK_POLICY_AUTOMATIC, | |
510 GTK_POLICY_AUTOMATIC); | |
511 gtk_container_add(GTK_CONTAINER(instwnd), GTK_WIDGET(instnames)); | |
869 | 512 // Former packer layout, for future reproduction |
513 // gtk_packer_add(packer, GTK_WIDGET(instwnd), GTK_SIDE_TOP, | |
514 // GTK_ANCHOR_CENTER, GTK_FILL_X, 0, 0, 0, 0, 50); | |
878
f804ff3a4899
[svn] Pending proper layout, make a little less vertical at least.
nemo
parents:
869
diff
changeset
|
515 gtk_box_pack_end(GTK_BOX(hbox2), GTK_WIDGET(instwnd), TRUE, TRUE, 2); |
359 | 516 } |
517 | |
518 // Add "Song message" section | |
519 if(!p->getdesc().empty()) { | |
520 GtkScrolledWindow *msgwnd = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); | |
869 | 521 GtkTextView *msg = GTK_TEXT_VIEW(gtk_text_view_new()); |
359 | 522 |
523 gtk_scrolled_window_set_policy(msgwnd, GTK_POLICY_AUTOMATIC, | |
524 GTK_POLICY_AUTOMATIC); | |
869 | 525 gtk_text_view_set_editable(msg, FALSE); |
526 gtk_text_view_set_wrap_mode(msg, GTK_WRAP_WORD_CHAR); | |
359 | 527 |
869 | 528 gtk_text_buffer_set_text(gtk_text_view_get_buffer(msg),p->getdesc().c_str(),p->getdesc().length()); |
359 | 529 gtk_container_add(GTK_CONTAINER(msgwnd), GTK_WIDGET(msg)); |
869 | 530 |
531 // Former packer layout, for future reproduction | |
532 // gtk_packer_add(packer, make_framed(GTK_WIDGET(msgwnd), "Song message"), | |
533 // GTK_SIDE_TOP, GTK_ANCHOR_CENTER, GTK_FILL_X, 2, 0, 0, 200, 50); | |
878
f804ff3a4899
[svn] Pending proper layout, make a little less vertical at least.
nemo
parents:
869
diff
changeset
|
534 gtk_box_pack_end(GTK_BOX(hbox2), make_framed(GTK_WIDGET(msgwnd), "Song message"), TRUE, TRUE, 2); |
359 | 535 } |
536 | |
537 // Add subsong slider section | |
538 if(p == plr.p && p->getsubsongs() > 1) { | |
539 GtkAdjustment *adj = GTK_ADJUSTMENT(gtk_adjustment_new(plr.subsong + 1, 1, | |
540 p->getsubsongs() + 1, | |
541 1, 5, 1)); | |
542 GtkHScale *slider = GTK_HSCALE(gtk_hscale_new(adj)); | |
543 | |
1103 | 544 g_signal_connect(G_OBJECT(adj), "value_changed", |
545 G_CALLBACK(subsong_slider), NULL); | |
359 | 546 gtk_range_set_update_policy(GTK_RANGE(slider), GTK_UPDATE_DISCONTINUOUS); |
547 gtk_scale_set_digits(GTK_SCALE(slider), 0); | |
869 | 548 // Former packer layout, for future reproduction |
549 // gtk_packer_add_defaults(packer, make_framed(GTK_WIDGET(slider), "Subsong selection"), | |
550 // GTK_SIDE_TOP, GTK_ANCHOR_CENTER, GTK_FILL_X); | |
878
f804ff3a4899
[svn] Pending proper layout, make a little less vertical at least.
nemo
parents:
869
diff
changeset
|
551 gtk_box_pack_end(GTK_BOX(hbox2), make_framed(GTK_WIDGET(slider), "Subsong selection"), TRUE, TRUE, 2); |
359 | 552 } |
553 | |
554 // Show dialog box | |
555 gtk_widget_show_all(GTK_WIDGET(infobox)); | |
556 if(p == plr.p) { // Remember widget, so we could destroy it later | |
557 plr.infodlg = infobox; | |
558 } else // Delete temporary player | |
559 delete p; | |
560 } | |
561 | |
562 /***** Main player (!! threaded !!) *****/ | |
563 | |
564 static void update_infobox(void) | |
565 { | |
566 std::ostringstream infotext; | |
567 | |
568 // Recreate info string | |
569 infotext << "Order: " << plr.p->getorder() << " / " << plr.p->getorders() << | |
570 std::endl << "Pattern: " << plr.p->getpattern() << " / " << | |
571 plr.p->getpatterns() << std::endl << "Row: " << plr.p->getrow() << | |
572 std::endl << "Speed: " << plr.p->getspeed() << std::endl << "Timer: " << | |
573 plr.p->getrefresh() << "Hz" << std::ends; | |
574 | |
575 GDK_THREADS_ENTER(); | |
576 gtk_label_set_text(plr.infobox, infotext.str().c_str()); | |
577 GDK_THREADS_LEAVE(); | |
578 } | |
579 | |
580 // Define sampsize macro (only usable inside play_loop()!) | |
581 #define sampsize ((bit16 ? 2 : 1) * (stereo ? 2 : 1)) | |
582 | |
583 static void *play_loop(void *filename) | |
584 /* Main playback thread. Takes the filename to play as argument. */ | |
585 { | |
586 dbg_printf("play_loop(\"%s\"): ", (char *)filename); | |
587 CEmuopl opl(cfg.freq, cfg.bit16, cfg.stereo); | |
588 long toadd = 0, i, towrite; | |
589 char *sndbuf, *sndbufpos; | |
590 bool playing = true, // Song self-end indicator. | |
591 bit16 = cfg.bit16, // Duplicate config, so it doesn't affect us if | |
592 stereo = cfg.stereo; // the user changes it while we're playing. | |
593 unsigned long freq = cfg.freq; | |
594 | |
595 // Try to load module | |
596 dbg_printf("factory, "); | |
597 if(!(plr.p = factory((char *)filename, &opl))) { | |
598 dbg_printf("error!\n"); | |
599 MessageBox("AdPlug :: Error", "File could not be opened!", "Ok"); | |
600 plr.playing = false; | |
601 g_thread_exit(NULL); | |
602 } | |
603 | |
604 // Cache song length | |
605 dbg_printf("length, "); | |
606 plr.songlength = plr.p->songlength(plr.subsong); | |
607 | |
608 // cache song title | |
609 dbg_printf("title, "); | |
610 if(!plr.p->gettitle().empty()) { | |
611 plr.songtitle = (char *)malloc(plr.p->gettitle().length() + 1); | |
612 strcpy(plr.songtitle, plr.p->gettitle().c_str()); | |
613 } | |
614 | |
615 // reset to first subsong on new file | |
616 dbg_printf("subsong, "); | |
617 if(strcmp((char *)filename, plr.filename)) { | |
618 strcpy(plr.filename, (char *)filename); | |
619 plr.subsong = 0; | |
620 } | |
621 | |
622 // Allocate audio buffer | |
623 dbg_printf("buffer, "); | |
624 sndbuf = (char *)malloc(SNDBUFSIZE * sampsize); | |
625 | |
626 // Set XMMS main window information | |
627 dbg_printf("xmms, "); | |
628 adplug_ip.set_info(plr.songtitle, plr.songlength, freq * sampsize * 8, | |
629 freq, stereo ? 2 : 1); | |
630 | |
631 // Rewind player to right subsong | |
632 dbg_printf("rewind, "); | |
633 plr.p->rewind(plr.subsong); | |
634 | |
635 // main playback loop | |
636 dbg_printf("loop.\n"); | |
637 while((playing || cfg.endless) && plr.playing) { | |
638 // seek requested ? | |
639 if(plr.seek != -1) { | |
640 // backward seek ? | |
641 if(plr.seek < plr.time_ms) { | |
642 plr.p->rewind(plr.subsong); | |
643 plr.time_ms = 0.0f; | |
644 } | |
645 | |
646 // seek to requested position | |
647 while((plr.time_ms < plr.seek) && plr.p->update()) | |
648 plr.time_ms += 1000 / plr.p->getrefresh(); | |
649 | |
650 // Reset output plugin and some values | |
651 adplug_ip.output->flush((int)plr.time_ms); | |
652 plr.seek = -1; | |
653 } | |
654 | |
655 // fill sound buffer | |
656 towrite = SNDBUFSIZE; sndbufpos = sndbuf; | |
657 while (towrite > 0) { | |
658 while (toadd < 0) { | |
659 toadd += freq; | |
660 playing = plr.p->update(); | |
661 plr.time_ms += 1000 / plr.p->getrefresh(); | |
662 } | |
663 i = MIN(towrite, (long)(toadd / plr.p->getrefresh() + 4) & ~3); | |
664 opl.update((short *)sndbufpos, i); | |
665 sndbufpos += i * sampsize; towrite -= i; | |
666 toadd -= (long)(plr.p->getrefresh() * i); | |
667 } | |
668 | |
414
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
669 // write sound buffer |
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
670 while(adplug_ip.output->buffer_free() < SNDBUFSIZE * sampsize) xmms_usleep(10000); |
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
671 produce_audio(adplug_ip.output->written_time(), |
359 | 672 bit16 ? FORMAT_16 : FORMAT_8, |
414
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
361
diff
changeset
|
673 stereo ? 2 : 1, SNDBUFSIZE * sampsize, sndbuf, NULL); |
359 | 674 |
675 // update infobox, if necessary | |
676 if(plr.infobox && plr.playing) update_infobox(); | |
677 } | |
678 | |
679 // playback finished - deinit | |
680 dbg_printf("play_loop(\"%s\"): ", (char *)filename); | |
681 if(!playing) { // wait for output plugin to finish if song has self-ended | |
682 dbg_printf("wait, "); | |
683 while(adplug_ip.output->buffer_playing()) xmms_usleep(10000); | |
684 } else { // or else, flush its output buffers | |
685 dbg_printf("flush, "); | |
686 adplug_ip.output->buffer_free(); adplug_ip.output->buffer_free(); | |
687 } | |
688 | |
689 // free everything and exit | |
690 dbg_printf("free"); | |
691 delete plr.p; plr.p = 0; | |
692 if(plr.songtitle) { free(plr.songtitle); plr.songtitle = NULL; } | |
693 free(sndbuf); | |
694 plr.playing = false; // important! XMMS won't get a self-ended song without it. | |
695 dbg_printf(".\n"); | |
696 g_thread_exit(NULL); | |
619 | 697 return(NULL); |
359 | 698 } |
699 | |
700 // sampsize macro not useful anymore. | |
701 #undef sampsize | |
702 | |
703 /***** Informational *****/ | |
704 | |
705 static int adplug_is_our_file(char *filename) | |
706 { | |
707 CSilentopl tmpopl; | |
708 CPlayer *p = factory(filename,&tmpopl); | |
709 | |
710 dbg_printf("adplug_is_our_file(\"%s\"): returned ",filename); | |
711 | |
712 if(p) { | |
713 delete p; | |
714 dbg_printf("TRUE\n"); | |
715 return TRUE; | |
716 } | |
717 | |
718 dbg_printf("FALSE\n"); | |
719 return FALSE; | |
720 } | |
721 | |
722 static int adplug_get_time(void) | |
723 { | |
724 if(audio_error) { dbg_printf("adplug_get_time(): returned -2\n"); return -2; } | |
725 if(!plr.playing) { dbg_printf("adplug_get_time(): returned -1\n"); return -1; } | |
726 return adplug_ip.output->output_time(); | |
727 } | |
728 | |
729 static void adplug_song_info(char *filename, char **title, int *length) | |
730 { | |
731 CSilentopl tmpopl; | |
732 CPlayer *p = factory(filename, &tmpopl); | |
733 | |
734 dbg_printf("adplug_song_info(\"%s\", \"%s\", %d): ", filename, *title, *length); | |
735 | |
736 if(p) { | |
737 // allocate and set title string | |
738 if(p->gettitle().empty()) | |
739 *title = 0; | |
740 else { | |
741 *title = (char *)malloc(p->gettitle().length() + 1); | |
742 strcpy(*title, p->gettitle().c_str()); | |
743 } | |
744 | |
745 // get song length | |
746 *length = p->songlength(plr.subsong); | |
747 | |
748 // delete temporary player object | |
749 delete p; | |
750 } | |
751 | |
752 dbg_printf("title = \"%s\", length = %d\n", *title, *length); | |
753 } | |
754 | |
755 /***** Player control *****/ | |
756 | |
757 static void adplug_play(char *filename) | |
758 { | |
759 dbg_printf("adplug_play(\"%s\"): ", filename); | |
760 audio_error = FALSE; | |
761 | |
762 // On new song, re-open "Song info" dialog, if open | |
763 dbg_printf("dialog, "); | |
764 if(plr.infobox && strcmp(filename, plr.filename)) | |
765 gtk_widget_destroy(GTK_WIDGET(plr.infodlg)); | |
766 | |
767 // open output plugin | |
768 dbg_printf("open, "); | |
769 if (!adplug_ip.output->open_audio(cfg.bit16 ? FORMAT_16 : FORMAT_8, cfg.freq, cfg.stereo ? 2 : 1)) { | |
770 audio_error = TRUE; | |
771 return; | |
772 } | |
773 | |
774 // Initialize global player data (this is here to prevent a race condition | |
775 // between adplug_get_time() returning the playback state and adplug_loop() | |
776 // initializing the playback state) | |
777 dbg_printf("init, "); | |
778 plr.playing = true; plr.time_ms = 0.0f; plr.seek = -1; | |
779 | |
780 // start player thread | |
781 dbg_printf("create"); | |
782 plr.play_thread = g_thread_create(play_loop, filename, TRUE, NULL); | |
783 dbg_printf(".\n"); | |
784 } | |
785 | |
786 static void adplug_stop(void) | |
787 { | |
788 dbg_printf("adplug_stop(): join, "); | |
789 plr.playing = false; g_thread_join(plr.play_thread); // stop player thread | |
790 dbg_printf("close"); adplug_ip.output->close_audio(); | |
791 dbg_printf(".\n"); | |
792 } | |
793 | |
794 static void adplug_pause(short paused) | |
795 { | |
796 dbg_printf("adplug_pause(%d)\n", paused); | |
797 adplug_ip.output->pause(paused); | |
798 } | |
799 | |
800 static void adplug_seek(int time) | |
801 { | |
802 dbg_printf("adplug_seek(%d)\n", time); | |
803 plr.seek = time * 1000; // time is in seconds, but we count in ms | |
804 } | |
805 | |
806 /***** Configuration file handling *****/ | |
807 | |
808 #define CFG_VERSION "AdPlug" | |
809 | |
810 static void adplug_init(void) | |
811 { | |
812 dbg_printf("adplug_init(): open, "); | |
813 ConfigDb *db = bmp_cfg_db_open(); | |
814 | |
815 // Read configuration | |
816 dbg_printf("read, "); | |
817 bmp_cfg_db_get_bool(db, CFG_VERSION, "16bit", (gboolean *)&cfg.bit16); | |
818 bmp_cfg_db_get_bool(db, CFG_VERSION, "Stereo", (gboolean *)&cfg.stereo); | |
819 bmp_cfg_db_get_int(db, CFG_VERSION, "Frequency", (gint *)&cfg.freq); | |
820 bmp_cfg_db_get_bool(db, CFG_VERSION, "Endless", (gboolean *)&cfg.endless); | |
821 | |
822 // Read file type exclusion list | |
823 dbg_printf("exclusion, "); | |
824 { | |
825 gchar *cfgstr = "", *exclude; | |
826 gboolean cfgread; | |
827 | |
828 cfgread = bmp_cfg_db_get_string(db, CFG_VERSION, "Exclude", &cfgstr); | |
829 exclude = (char *)malloc(strlen(cfgstr) + 2); strcpy(exclude, cfgstr); | |
830 exclude[strlen(exclude) + 1] = '\0'; | |
831 if(cfgread) free(cfgstr); | |
832 g_strdelimit(exclude, ":", '\0'); | |
833 for(gchar *p = exclude; *p; p += strlen(p) + 1) | |
834 cfg.players.remove(cfg.players.lookup_filetype(p)); | |
835 free(exclude); | |
836 } | |
837 bmp_cfg_db_close(db); | |
838 | |
839 // Load database from disk and hand it to AdPlug | |
840 dbg_printf("database"); | |
841 plr.db = new CAdPlugDatabase; | |
842 | |
843 { | |
844 const char *homedir = getenv("HOME"); | |
845 | |
846 if(homedir) { | |
847 char *userdb = (char *)malloc(strlen(homedir) + strlen(ADPLUG_CONFDIR) + | |
848 strlen(ADPLUGDB_FILE) + 3); | |
849 strcpy(userdb, homedir); strcat(userdb, "/" ADPLUG_CONFDIR "/"); | |
850 strcat(userdb, ADPLUGDB_FILE); | |
851 plr.db->load(userdb); // load user's database | |
852 dbg_printf(" (userdb=\"%s\")", userdb); | |
813
c8cf439179b8
[svn] - Fix a ton and a half of memory leaks, via the wonderful Leonardo Boshell <leonardop -at- gentoo.org>.
nenolod
parents:
683
diff
changeset
|
853 free(userdb); |
359 | 854 } |
855 } | |
856 CAdPlug::set_database(plr.db); | |
857 dbg_printf(".\n"); | |
858 } | |
859 | |
860 static void adplug_quit(void) | |
861 { | |
862 dbg_printf("adplug_quit(): open, "); | |
863 ConfigDb *db = bmp_cfg_db_open(); | |
864 | |
865 // Close database | |
866 dbg_printf("db, "); | |
867 if(plr.db) delete plr.db; | |
868 | |
869 // Write configuration | |
870 dbg_printf("write, "); | |
871 bmp_cfg_db_set_bool(db, CFG_VERSION, "16bit", cfg.bit16); | |
872 bmp_cfg_db_set_bool(db, CFG_VERSION, "Stereo", cfg.stereo); | |
873 bmp_cfg_db_set_int(db, CFG_VERSION, "Frequency", cfg.freq); | |
874 bmp_cfg_db_set_bool(db, CFG_VERSION, "Endless", cfg.endless); | |
875 | |
876 dbg_printf("exclude, "); | |
877 std::string exclude; | |
878 for(CPlayers::const_iterator i = CAdPlug::players.begin(); | |
879 i != CAdPlug::players.end(); i++) | |
880 if(find(cfg.players.begin(), cfg.players.end(), *i) == cfg.players.end()) { | |
881 if(!exclude.empty()) exclude += ":"; | |
882 exclude += (*i)->filetype; | |
883 } | |
884 gchar *cfgval = g_strdup(exclude.c_str()); | |
885 bmp_cfg_db_set_string(db, CFG_VERSION, "Exclude", cfgval); | |
886 free(cfgval); | |
887 | |
888 dbg_printf("close"); | |
889 bmp_cfg_db_close(db); | |
890 dbg_printf(".\n"); | |
891 } | |
892 | |
893 /***** Plugin (exported) *****/ | |
894 | |
895 InputPlugin adplug_ip = | |
896 { | |
897 NULL, // handle (filled by XMMS) | |
898 NULL, // filename (filled by XMMS) | |
644 | 899 ADPLUG_NAME, // plugin description |
359 | 900 adplug_init, // plugin functions... |
901 adplug_about, | |
902 adplug_config, | |
903 adplug_is_our_file, | |
644 | 904 NULL, // scan_dir (look in Input/cdaudio/cdaudio.c) |
359 | 905 adplug_play, |
906 adplug_stop, | |
907 adplug_pause, | |
908 adplug_seek, | |
909 NULL, // set_eq | |
910 adplug_get_time, | |
911 NULL, // get_volume (handled by output plugin) | |
912 NULL, // set_volume (...) | |
913 adplug_quit, | |
914 NULL, // OBSOLETE - DO NOT USE! | |
915 NULL, // add_vis_pcm (filled by XMMS) | |
916 NULL, // set_info (filled by XMMS) | |
917 NULL, // set_info_text (filled by XMMS) | |
918 adplug_song_info, | |
869 | 919 adplug_info_box, // adplug_info_box was here (but it used deprecated GTK+ functions) |
359 | 920 NULL // output plugin (filled by XMMS) |
921 }; | |
922 | |
923 extern "C" InputPlugin *get_iplugin_info(void) | |
924 { | |
925 return &adplug_ip; | |
926 } |