~ubuntu-branches/debian/sid/audacious-plugins/sid

« back to all changes in this revision

Viewing changes to src/paranormal-ng/plugin.c

  • Committer: Bazaar Package Importer
  • Author(s): Bilal Akhtar
  • Date: 2011-04-10 18:56:21 UTC
  • mfrom: (1.1.14 upstream) (2.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110410185621-7eg1k5a7v3f4aqrn
Tags: 2.4.4-1
* New upstream release.
  - Fix FTBFS with GCC 4.5 (Closes: #621989)
* Upload to unstable.
* debian/control:
  - Update versioned dependencies according to upstream changes.
  - Bump Standards-Version to 3.9.2 (no changes needed).
  - Since the package will be building against the new FFMpeg libs,
    fix the problem of depending on old uninstallable libav*
    packages (Closes: #617603)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * paranormal: iterated pipeline-driven visualization plugin
3
 
 * Copyright (c) 2006, 2007 William Pitcock <nenolod@dereferenced.org>
4
 
 * Portions copyright (c) 2001 Jamie Gennis <jgennis@mindspring.com>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; under version 2 of the License.
9
 
 *
10
 
 * This program 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
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 
 */
19
 
 
20
 
/* FIXME: issues with not uniniting variables between
21
 
   enables?  I wasn't too careful about that, but it
22
 
   seems to work fine.  If there are problems perhaps
23
 
   look for a bug there?
24
 
*/
25
 
 
26
 
#include <config.h>
27
 
 
28
 
#include <stdlib.h>
29
 
#include <stdio.h>
30
 
#include <stdarg.h>
31
 
#include <memory.h>
32
 
#include <math.h>
33
 
#include <setjmp.h>
34
 
#include <unistd.h>
35
 
 
36
 
#include <glib.h>
37
 
#include <audacious/i18n.h>
38
 
 
39
 
#include <gtk/gtk.h>
40
 
#include <audacious/plugin.h>
41
 
#include <SDL/SDL.h>
42
 
#include <SDL/SDL_thread.h>
43
 
 
44
 
#include "paranormal.h"
45
 
#include "actuators.h"
46
 
#include "presets.h"
47
 
#include "containers.h"
48
 
 
49
 
/* Error reporting dlg */
50
 
static GtkWidget *err_dialog;
51
 
 
52
 
/* Draw thread stuff */
53
 
/* FIXME: Do I need mutex for pn_done? */
54
 
static SDL_Thread *draw_thread = NULL;
55
 
static SDL_mutex *sound_data_mutex;
56
 
static SDL_mutex *config_mutex;
57
 
 
58
 
static gboolean pn_done = FALSE;
59
 
jmp_buf quit_jmp;
60
 
gboolean timeout_set = FALSE;
61
 
guint quit_timeout;
62
 
 
63
 
/* Sound stuffs */
64
 
static gboolean new_pcm_data = FALSE;
65
 
static gboolean new_freq_data = FALSE;
66
 
static gint16 tmp_pcm_data[2][512];
67
 
static gint16 tmp_freq_data[2][256];
68
 
 
69
 
/* XMMS interface */
70
 
static void pn_xmms_init (void);
71
 
static void pn_xmms_cleanup (void);
72
 
static void pn_xmms_about (void);
73
 
static void pn_xmms_configure (void);
74
 
static void pn_xmms_render_pcm (gint16 data[2][512]);
75
 
static void pn_xmms_render_freq (gint16 data[2][256]);
76
 
 
77
 
static VisPlugin pn_vp = 
78
 
{
79
 
  .description = "Paranormal Visualization Studio",
80
 
  .num_pcm_chs_wanted = 2,
81
 
  .num_freq_chs_wanted = 2,
82
 
  .init = pn_xmms_init,
83
 
  .cleanup = pn_xmms_cleanup,
84
 
  .about = pn_xmms_about,
85
 
  .configure = pn_xmms_configure,
86
 
  .render_pcm = pn_xmms_render_pcm,
87
 
  .render_freq = pn_xmms_render_freq
88
 
};
89
 
 
90
 
VisPlugin *pn_vplist[] = { &pn_vp, NULL };
91
 
 
92
 
DECLARE_PLUGIN(paranormal, NULL, NULL, NULL, NULL, NULL, NULL, pn_vplist,NULL);
93
 
 
94
 
static void
95
 
load_pn_rc (void)
96
 
{
97
 
  struct pn_actuator *a, *b;
98
 
 
99
 
  if (! pn_rc)
100
 
      pn_rc = g_new0 (struct pn_rc, 1);
101
 
 
102
 
  /* load a default preset */
103
 
  pn_rc->actuator = create_actuator ("container_simple");
104
 
  if (! pn_rc->actuator) goto ugh;
105
 
 
106
 
  a = create_actuator ("general_clear");
107
 
  if (! a) goto ugh;
108
 
  container_add_actuator (pn_rc->actuator, a);
109
 
 
110
 
  a = create_actuator ("wave_horizontal");
111
 
  if (! a) goto ugh;
112
 
  container_add_actuator (pn_rc->actuator, a);
113
 
 
114
 
  return;
115
 
 
116
 
 ugh:
117
 
  if (pn_rc->actuator)
118
 
    destroy_actuator (pn_rc->actuator);
119
 
  pn_error ("Error loading default preset");
120
 
}
121
 
 
122
 
static int
123
 
draw_thread_fn (gpointer data)
124
 
{
125
 
  gfloat fps = 0.0;
126
 
  guint last_time = 0, last_second = 0;
127
 
  guint this_time;
128
 
  pn_init ();
129
 
 
130
 
  /* Used when pn_quit is called from this thread */
131
 
  if (setjmp (quit_jmp) != 0)
132
 
    pn_done = TRUE;
133
 
 
134
 
  while (! pn_done)
135
 
    {
136
 
      SDL_mutexP (sound_data_mutex);
137
 
      if (new_freq_data)
138
 
        {
139
 
          memcpy (pn_sound_data->freq_data, tmp_freq_data,
140
 
                  sizeof (gint16) * 2 * 256);
141
 
          new_freq_data = FALSE;
142
 
        }
143
 
      if (new_pcm_data)
144
 
        {
145
 
          memcpy (pn_sound_data->pcm_data, tmp_pcm_data,
146
 
                  sizeof (gint16) * 2 * 512);
147
 
          new_freq_data = FALSE;
148
 
        }
149
 
      SDL_mutexV (sound_data_mutex);
150
 
      SDL_mutexP (config_mutex);
151
 
      pn_render ();
152
 
      SDL_mutexV (config_mutex);
153
 
 
154
 
      /* Compute the FPS */
155
 
      this_time = SDL_GetTicks ();
156
 
 
157
 
      fps = fps * .95 + (1000. / (gfloat) (this_time - last_time)) * .05;
158
 
      if (this_time > 2000 + last_second)
159
 
        {
160
 
          last_second = this_time;
161
 
          g_print ("FPS: %f\n", fps);
162
 
        }
163
 
      last_time = this_time;
164
 
 
165
 
#ifdef _POSIX_PRIORITY_SCHEDULING
166
 
      sched_yield();
167
 
#endif
168
 
    }
169
 
 
170
 
  /* Just in case a pn_quit () was called in the loop */
171
 
/*    SDL_mutexV (sound_data_mutex); */
172
 
 
173
 
  pn_cleanup ();
174
 
 
175
 
  return 0;
176
 
}
177
 
 
178
 
/* Is there a better way to do this? this = messy
179
 
   It appears that calling disable_plugin () in some
180
 
   thread other than the one that called pn_xmms_init ()
181
 
   causes a seg fault :( */
182
 
static int
183
 
quit_timeout_fn (gpointer data)
184
 
{
185
 
  if (pn_done)
186
 
    {
187
 
      pn_vp.disable_plugin (&pn_vp);
188
 
      return FALSE;
189
 
    }
190
 
 
191
 
  return TRUE;
192
 
}
193
 
 
194
 
static void
195
 
pn_xmms_init (void)
196
 
{
197
 
  /* If it isn't already loaded, load the run control */
198
 
  if (! pn_rc)
199
 
          load_pn_rc ();
200
 
 
201
 
  sound_data_mutex = SDL_CreateMutex ();
202
 
  config_mutex = SDL_CreateMutex ();
203
 
  if (! sound_data_mutex)
204
 
    pn_fatal_error ("Unable to create a new mutex: %s",
205
 
                    SDL_GetError ());
206
 
 
207
 
  pn_done = FALSE;
208
 
  draw_thread = SDL_CreateThread (draw_thread_fn, NULL);
209
 
  if (! draw_thread)
210
 
    pn_fatal_error ("Unable to create a new thread: %s",
211
 
                    SDL_GetError ());
212
 
 
213
 
  /* Add a gtk timeout to test for quits */
214
 
  quit_timeout = gtk_timeout_add (1000, quit_timeout_fn, NULL);
215
 
  timeout_set = TRUE;
216
 
}
217
 
 
218
 
static void
219
 
pn_xmms_cleanup (void)
220
 
{
221
 
  if (timeout_set)
222
 
    {
223
 
      gtk_timeout_remove (quit_timeout);
224
 
      timeout_set = FALSE;
225
 
    }
226
 
 
227
 
  if (draw_thread)
228
 
    {
229
 
      pn_done = TRUE;
230
 
      SDL_WaitThread (draw_thread, NULL);
231
 
      draw_thread = NULL;
232
 
    }
233
 
 
234
 
  if (sound_data_mutex)
235
 
    {
236
 
      SDL_DestroyMutex (sound_data_mutex);
237
 
      sound_data_mutex = NULL;
238
 
    }
239
 
 
240
 
  if (config_mutex)
241
 
    {
242
 
      SDL_DestroyMutex (config_mutex);
243
 
      config_mutex = NULL;
244
 
    }
245
 
}
246
 
 
247
 
static void
248
 
about_close_clicked(GtkWidget *w, GtkWidget **window)
249
 
{
250
 
        gtk_widget_destroy(*window);
251
 
        *window=NULL;
252
 
}
253
 
 
254
 
static void
255
 
about_closed(GtkWidget *w, GdkEvent *e, GtkWidget **window)
256
 
{
257
 
        about_close_clicked(w,window);
258
 
}
259
 
 
260
 
static void
261
 
pn_xmms_about (void)
262
 
{
263
 
  audacious_info_dialog("About Paranormal Visualization Studio", 
264
 
 
265
 
"Paranormal Visualization Studio " VERSION "\n\n\
266
 
Copyright (C) 2006, William Pitcock <nenolod -at- nenolod.net>\n\
267
 
Portions Copyright (C) 2001, Jamie Gennis <jgennis -at- mindspring.com>\n\
268
 
\n\
269
 
This program is free software; you can redistribute it and/or modify\n\
270
 
it under the terms of the GNU General Public License as published by\n\
271
 
the Free Software Foundation; either version 2 of the License, or\n\
272
 
(at your option) any later version.\n\
273
 
\n\
274
 
This program is distributed in the hope that it will be useful,\n\
275
 
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
276
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
277
 
GNU General Public License for more details.\n\
278
 
\n\
279
 
You should have received a copy of the GNU General Public License\n\
280
 
along with this program; if not, write to the Free Software\n\
281
 
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301\n\
282
 
USA", _("Ok"), FALSE, NULL, NULL);
283
 
}
284
 
 
285
 
static void
286
 
pn_xmms_configure (void)
287
 
{
288
 
  /* We should already have a GDK_THREADS_ENTER
289
 
     but we need to give it config_mutex */
290
 
  if (config_mutex)
291
 
    SDL_mutexP (config_mutex);
292
 
 
293
 
  if (! pn_rc)
294
 
          load_pn_rc ();
295
 
 
296
 
  pn_configure ();
297
 
 
298
 
  if (config_mutex)
299
 
    SDL_mutexV (config_mutex);
300
 
}
301
 
 
302
 
static void
303
 
pn_xmms_render_pcm (gint16 data[2][512])
304
 
{
305
 
  SDL_mutexP (sound_data_mutex);
306
 
  memcpy (tmp_pcm_data, data, sizeof (gint16) * 2 * 512);
307
 
  new_pcm_data = TRUE;
308
 
  SDL_mutexV (sound_data_mutex);
309
 
}
310
 
 
311
 
static void
312
 
pn_xmms_render_freq (gint16 data[2][256])
313
 
{
314
 
  SDL_mutexP (sound_data_mutex);
315
 
  memcpy (tmp_freq_data, data, sizeof (gint16) * 2 * 256);
316
 
  new_freq_data = TRUE;
317
 
  SDL_mutexV (sound_data_mutex);
318
 
}
319
 
 
320
 
/* **************** paranormal.h stuff **************** */
321
 
 
322
 
void
323
 
pn_set_rc (struct pn_rc *new_rc)
324
 
{
325
 
  if (config_mutex)
326
 
    SDL_mutexP (config_mutex);
327
 
 
328
 
  if (! pn_rc)
329
 
    load_pn_rc ();
330
 
 
331
 
  if (pn_rc->actuator)
332
 
    destroy_actuator (pn_rc->actuator);
333
 
  pn_rc->actuator = new_rc->actuator;
334
 
 
335
 
  if (config_mutex)
336
 
    SDL_mutexV (config_mutex);
337
 
}
338
 
 
339
 
void
340
 
pn_fatal_error (const char *fmt, ...)
341
 
{
342
 
  char *errstr;
343
 
  va_list ap;
344
 
  GtkWidget *dialog;
345
 
  GtkWidget *close, *label;
346
 
 
347
 
  /* Don't wanna try to lock GDK if we already have it */
348
 
  if (draw_thread && SDL_ThreadID () == SDL_GetThreadID (draw_thread))
349
 
    GDK_THREADS_ENTER ();
350
 
 
351
 
  /* now report the error... */
352
 
  va_start (ap, fmt);
353
 
  errstr = g_strdup_vprintf (fmt, ap);
354
 
  va_end (ap);
355
 
 
356
 
  dialog=gtk_dialog_new();
357
 
  gtk_window_set_title(GTK_WINDOW(dialog), "Error - Paranormal Visualization Studio - " VERSION);
358
 
  gtk_container_border_width (GTK_CONTAINER (dialog), 8);
359
 
 
360
 
  label=gtk_label_new(errstr);
361
 
  fprintf (stderr, "%s\n", errstr);
362
 
  g_free (errstr);
363
 
 
364
 
  close = gtk_button_new_with_label ("Close");
365
 
  gtk_signal_connect_object (GTK_OBJECT (close), "clicked",
366
 
                             GTK_SIGNAL_FUNC (gtk_widget_destroy),
367
 
                             GTK_OBJECT (dialog));
368
 
 
369
 
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label, FALSE,
370
 
                      FALSE, 0);
371
 
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), close,
372
 
                      FALSE, FALSE, 0);
373
 
  gtk_widget_show (label);
374
 
  gtk_widget_show (close);
375
 
 
376
 
  gtk_widget_show (dialog);
377
 
  gtk_widget_grab_focus (dialog);
378
 
 
379
 
  if (draw_thread && SDL_ThreadID () == SDL_GetThreadID (draw_thread))
380
 
    GDK_THREADS_LEAVE ();
381
 
 
382
 
  pn_quit ();
383
 
}
384
 
 
385
 
 
386
 
void
387
 
pn_error (const char *fmt, ...)
388
 
{
389
 
  char *errstr;
390
 
  va_list ap;
391
 
  static GtkWidget *text;
392
 
  static GtkTextBuffer *textbuf;
393
 
 
394
 
  /* now report the error... */
395
 
  va_start (ap, fmt);
396
 
  errstr = g_strdup_vprintf (fmt, ap);
397
 
  va_end (ap);
398
 
  fprintf (stderr, "Paranormal-CRITICAL **: %s\n", errstr);
399
 
 
400
 
  /* This is the easiest way of making sure we don't
401
 
     get stuck trying to lock a mutex that this thread
402
 
     already owns since this fn can be called from either
403
 
     thread */
404
 
  if (draw_thread && SDL_ThreadID () == SDL_GetThreadID (draw_thread))
405
 
    GDK_THREADS_ENTER ();
406
 
 
407
 
  if (! err_dialog)
408
 
    {
409
 
      GtkWidget *close;
410
 
 
411
 
      err_dialog=gtk_dialog_new();
412
 
      gtk_window_set_title (GTK_WINDOW (err_dialog), "Error - Paranormal Visualization Studio - " VERSION);
413
 
      gtk_window_set_policy (GTK_WINDOW (err_dialog), FALSE, FALSE, FALSE);
414
 
      gtk_widget_set_usize (err_dialog, 400, 200);
415
 
      gtk_container_border_width (GTK_CONTAINER (err_dialog), 8);
416
 
 
417
 
      textbuf = gtk_text_buffer_new(NULL);
418
 
      text = gtk_text_view_new_with_buffer (textbuf);
419
 
 
420
 
      close = gtk_button_new_with_label ("Close");
421
 
      gtk_signal_connect_object (GTK_OBJECT (close), "clicked",
422
 
                                 GTK_SIGNAL_FUNC (gtk_widget_hide),
423
 
                                 GTK_OBJECT (err_dialog));
424
 
      gtk_signal_connect_object (GTK_OBJECT (err_dialog), "delete-event",
425
 
                                 GTK_SIGNAL_FUNC (gtk_widget_hide),
426
 
                                 GTK_OBJECT (err_dialog));
427
 
 
428
 
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (err_dialog)->vbox), text, FALSE,
429
 
                          FALSE, 0);
430
 
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (err_dialog)->action_area), close,
431
 
                          FALSE, FALSE, 0);
432
 
      gtk_widget_show (text);
433
 
      gtk_widget_show (close);
434
 
    }
435
 
 
436
 
  gtk_text_buffer_set_text(GTK_TEXT_BUFFER(textbuf), errstr, -1);
437
 
  g_free (errstr);
438
 
 
439
 
  gtk_widget_show (err_dialog);
440
 
  gtk_widget_grab_focus (err_dialog);
441
 
 
442
 
  if (draw_thread && SDL_ThreadID () == SDL_GetThreadID (draw_thread))
443
 
    GDK_THREADS_LEAVE ();
444
 
}
445
 
 
446
 
 
447
 
/* This is confusing...
448
 
   Don't call this from anywhere but the draw thread or
449
 
   the initialization xmms thread (ie NOT the xmms sound
450
 
   data functions) */
451
 
void
452
 
pn_quit (void)
453
 
{
454
 
  if (draw_thread && SDL_ThreadID () == SDL_GetThreadID (draw_thread))
455
 
    {
456
 
      /* We're in the draw thread so be careful */
457
 
      longjmp (quit_jmp, 1);
458
 
    }
459
 
  else
460
 
    {
461
 
      /* We're not in the draw thread, so don't sweat it...
462
 
         addendum: looks like we have to bend over backwards (forwards?)
463
 
         for xmms here too */
464
 
      pn_vp.disable_plugin (&pn_vp);
465
 
      while (1)
466
 
        gtk_main_iteration ();
467
 
    }
468
 
}