Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
output.c
Go to the documentation of this file.
1 /*
2  * output.c
3  * Copyright 2009-2010 John Lindgren
4  *
5  * This file is part of Audacious.
6  *
7  * Audacious is free software: you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free Software
9  * Foundation, version 2 or version 3 of the License.
10  *
11  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * Audacious. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * The Audacious team does not consider modular code linking to Audacious or
19  * using our public API to be a derived work.
20  */
21 
22 #include <glib.h>
23 #include <math.h>
24 #include <pthread.h>
25 #include <string.h>
26 
27 #include "debug.h"
28 #include "effect.h"
29 #include "equalizer.h"
30 #include "misc.h"
31 #include "output.h"
32 #include "playback.h"
33 #include "plugins.h"
34 #include "vis_runner.h"
35 
36 #define SW_VOLUME_RANGE 40 /* decibels */
37 
38 static OutputPlugin * cop = NULL;
39 
40 void output_get_volume (int * l, int * r)
41 {
42  if (get_bool (NULL, "software_volume_control"))
43  {
44  * l = get_int (NULL, "sw_volume_left");
45  * r = get_int (NULL, "sw_volume_right");
46  }
47  else if (cop != NULL && cop->get_volume != NULL)
48  cop->get_volume (l, r);
49  else
50  {
51  * l = 0;
52  * r = 0;
53  }
54 }
55 
56 void output_set_volume (int l, int r)
57 {
58  if (get_bool (NULL, "software_volume_control"))
59  {
60  set_int (NULL, "sw_volume_left", l);
61  set_int (NULL, "sw_volume_right", r);
62  }
63  else if (cop != NULL && cop->set_volume != NULL)
64  cop->set_volume (l, r);
65 }
66 
67 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
68 static bool_t locked = FALSE;
69 
70 #define LOCK do {pthread_mutex_lock (& mutex); locked = TRUE;} while (0)
71 #define UNLOCK do {locked = FALSE; pthread_mutex_unlock (& mutex);} while (0)
72 #define LOCKED g_return_if_fail (locked)
73 #define LOCKED_RET(a) g_return_val_if_fail (locked, a)
74 #define LOCK_VIS do {vis_runner_lock (); LOCK;} while (0)
75 #define UNLOCK_VIS do {UNLOCK; vis_runner_unlock ();} while (0)
76 #define LOCKED_VIS g_return_if_fail (locked && vis_runner_locked ())
77 #define LOCKED_VIS_RET(a) g_return_val_if_fail (locked && vis_runner_locked (), a)
78 
79 static bool_t opened = FALSE;
81 
85 static int64_t frames_written;
88 
89 static void reset_time (void)
90 {
91  LOCKED_VIS;
92  g_return_if_fail (cop->set_written_time != NULL);
93  vis_runner_time_offset (- cop->written_time ());
94  cop->set_written_time (0);
95 }
96 
97 static void drain (void)
98 {
99  LOCKED;
100  g_return_if_fail (cop->drain != NULL);
101  cop->drain ();
102 }
103 
104 static void real_close (void)
105 {
106  LOCKED_VIS;
108  cop->close_audio ();
109  opened = FALSE;
110  leave_open = FALSE;
111 }
112 
113 static bool_t open_audio (int format, int rate, int channels)
114 {
116  g_return_val_if_fail (! opened, FALSE);
117 
120  decoder_rate = rate;
122  effect_rate = rate;
125 
127  output_rate)
128  {
129  reset_time ();
130  opened = TRUE;
131  }
132  else
133  {
134  if (leave_open)
135  {
136  drain ();
137  real_close ();
138  }
139 
140  int depth = get_int (NULL, "output_bit_depth");
141  output_format = (depth == 32) ? FMT_S32_NE : (depth == 24) ? FMT_S24_NE
142  : (depth == 16) ? FMT_S16_NE : FMT_FLOAT;
145 
146  if (cop->open_audio (output_format, output_rate, output_channels))
147  {
149  opened = TRUE;
150  }
151  }
152 
153  leave_open = FALSE;
154  waiting = FALSE;
155  aborted = FALSE;
156  paused = FALSE;
157  frames_written = 0;
159 
160  return opened;
161 }
162 
164 {
165  g_return_val_if_fail (cop != NULL, FALSE);
166  LOCK_VIS;
167  bool_t success = open_audio (format, rate, channels);
168  UNLOCK_VIS;
169  return success;
170 }
171 
172 static void set_gain (ReplayGainInfo * info)
173 {
174  LOCKED;
175  g_return_if_fail (opened && ! waiting);
176 
177  AUDDBG ("Replay Gain info:\n");
178  AUDDBG (" album gain: %f dB\n", info->album_gain);
179  AUDDBG (" album peak: %f\n", info->album_peak);
180  AUDDBG (" track gain: %f dB\n", info->track_gain);
181  AUDDBG (" track peak: %f\n", info->track_peak);
182 
184  memcpy (& replay_gain_info, info, sizeof (ReplayGainInfo));
185 }
186 
188 {
189  g_return_if_fail (cop != NULL);
190  LOCK;
191  set_gain (info);
192  UNLOCK;
193 }
194 
195 static void apply_replay_gain (float * data, int samples)
196 {
197  if (! get_bool (NULL, "enable_replay_gain"))
198  return;
199 
200  float factor = powf (10, get_double (NULL, "replay_gain_preamp") / 20);
201 
202  if (have_replay_gain)
203  {
204  if (get_bool (NULL, "replay_gain_album"))
205  {
206  factor *= powf (10, replay_gain_info.album_gain / 20);
207 
208  if (get_bool (NULL, "enable_clipping_prevention") &&
209  replay_gain_info.album_peak * factor > 1)
210  factor = 1 / replay_gain_info.album_peak;
211  }
212  else
213  {
214  factor *= powf (10, replay_gain_info.track_gain / 20);
215 
216  if (get_bool (NULL, "enable_clipping_prevention") &&
217  replay_gain_info.track_peak * factor > 1)
218  factor = 1 / replay_gain_info.track_peak;
219  }
220  }
221  else
222  factor *= powf (10, get_double (NULL, "default_gain") / 20);
223 
224  if (factor < 0.99 || factor > 1.01)
225  audio_amplify (data, 1, samples, & factor);
226 }
227 
228 static void apply_software_volume (float * data, int channels, int frames)
229 {
230  float left_factor, right_factor;
231  float factors[channels];
232  int channel;
233 
234  if (! get_bool (NULL, "software_volume_control"))
235  return;
236 
237  int l = get_int (NULL, "sw_volume_left");
238  int r = get_int (NULL, "sw_volume_right");
239  if (l == 100 && r == 100)
240  return;
241 
242  left_factor = (l == 0) ? 0 : powf (10, (float) SW_VOLUME_RANGE * (l - 100) / 100 / 20);
243  right_factor = (r == 0) ? 0 : powf (10, (float) SW_VOLUME_RANGE * (r - 100) / 100 / 20);
244 
245  if (channels == 2)
246  {
247  factors[0] = left_factor;
248  factors[1] = right_factor;
249  }
250  else
251  {
252  for (channel = 0; channel < channels; channel ++)
253  factors[channel] = MAX (left_factor, right_factor);
254  }
255 
256  audio_amplify (data, channels, frames, factors);
257 }
258 
259 static void write_processed (void * data, int samples)
260 {
261  LOCKED_VIS;
262 
263  if (! samples)
264  return;
265 
266  vis_runner_pass_audio (cop->written_time (), data, samples, output_channels,
267  output_rate);
268  eq_filter (data, samples);
269  apply_software_volume (data, output_channels, samples / output_channels);
270 
271  void * allocated = NULL;
272 
273  if (output_format != FMT_FLOAT)
274  {
275  void * new = g_malloc (FMT_SIZEOF (output_format) * samples);
276  audio_to_int (data, new, output_format, samples);
277  data = new;
278  g_free (allocated);
279  allocated = new;
280  }
281 
282  while (! aborted)
283  {
284  int ready = (cop->buffer_free != NULL) ? cop->buffer_free () /
285  FMT_SIZEOF (output_format) : output_channels * (output_rate / 50);
286  ready = MIN (ready, samples);
287  cop->write_audio (data, FMT_SIZEOF (output_format) * ready);
288  data = (char *) data + FMT_SIZEOF (output_format) * ready;
289  samples -= ready;
290 
291  if (! samples)
292  break;
293 
294  waiting = TRUE;
295  UNLOCK_VIS;
296 
297  if (cop->period_wait != NULL)
298  cop->period_wait ();
299  else if (cop->buffer_free != NULL)
300  g_usleep (20000);
301 
302  LOCK_VIS;
303  waiting = FALSE;
304  }
305 
306  g_free (allocated);
307 }
308 
309 static void write_audio (void * data, int size)
310 {
311  LOCKED;
312  g_return_if_fail (opened && ! waiting);
313 
314  int samples = size / FMT_SIZEOF (decoder_format);
315  frames_written += samples / decoder_channels;
316 
317  void * allocated = NULL;
318 
319  if (decoder_format != FMT_FLOAT)
320  {
321  float * new = g_malloc (sizeof (float) * samples);
322  audio_from_int (data, decoder_format, new, samples);
323  data = new;
324  g_free (allocated);
325  allocated = new;
326  }
327 
328  apply_replay_gain (data, samples);
329  float * fdata = data;
330  effect_process (& fdata, & samples);
331  data = fdata;
332 
333  if (data != allocated)
334  {
335  g_free (allocated);
336  allocated = NULL;
337  }
338 
339  write_processed (data, samples);
340  g_free (allocated);
341 }
342 
343 static void output_write_audio (void * data, int size)
344 {
345  g_return_if_fail (cop != NULL);
346  LOCK_VIS;
347  write_audio (data, size);
348  UNLOCK_VIS;
349 }
350 
351 static void close_audio (void)
352 {
353  LOCKED;
354  g_return_if_fail (opened && ! waiting);
355  opened = FALSE;
356 
357  if (! leave_open)
358  {
359  effect_flush ();
360  real_close ();
361  }
362 }
363 
364 static void output_close_audio (void)
365 {
366  g_return_if_fail (cop != NULL);
367  LOCK_VIS;
368  close_audio ();
369  UNLOCK_VIS;
370 }
371 
372 static void do_pause (bool_t p)
373 {
374  LOCKED_VIS;
375  g_return_if_fail (opened);
376  cop->pause (p);
378  paused = p;
379 }
380 
381 static void output_pause (bool_t p)
382 {
383  g_return_if_fail (cop != NULL);
384  LOCK_VIS;
385  do_pause (p);
386  UNLOCK_VIS;
387 }
388 
389 static void flush (int time)
390 {
391  LOCKED_VIS;
392  g_return_if_fail (opened);
393 
394  aborted = FALSE;
395 
396  /* When playback is started from the middle of a song, flush() is called
397  * before any audio is actually written in order to set the time counter.
398  * In this case, we do not want to cut off the end of the previous song, so
399  * we do not actually flush. */
400  if (! frames_written)
401  {
402  g_return_if_fail (cop->set_written_time != NULL);
403  vis_runner_time_offset (time - cop->written_time ());
404  cop->set_written_time (time);
405  }
406  else
407  {
408  vis_runner_flush ();
409  effect_flush ();
410  cop->flush (effect_decoder_to_output_time (time));
411  }
412 
413  frames_written = time * (int64_t) decoder_rate / 1000;
414 }
415 
416 static void output_flush (int time)
417 {
418  g_return_if_fail (cop != NULL);
419  LOCK_VIS;
420  flush (time);
421  UNLOCK_VIS;
422 }
423 
424 static int written_time (void)
425 {
426  LOCKED_RET (0);
427  g_return_val_if_fail (opened && ! waiting, 0);
428  return frames_written * (int64_t) 1000 / decoder_rate;
429 }
430 
431 static int output_written_time (void)
432 {
433  g_return_val_if_fail (cop != NULL, 0);
434  LOCK;
435  int time = written_time ();
436  UNLOCK;
437  return time;
438 }
439 
440 static void write_buffers (void)
441 {
442  LOCKED;
443  float * data = NULL;
444  int samples = 0;
445  effect_finish (& data, & samples);
446  write_processed (data, samples);
447 }
448 
449 static void set_leave_open (void)
450 {
451  LOCKED;
452  g_return_if_fail (opened && ! waiting);
453 
454  if (! paused)
455  {
456  write_buffers ();
457  leave_open = TRUE;
458  }
459 }
460 
462 {
463  g_return_val_if_fail (cop != NULL, FALSE);
464  LOCK_VIS;
465  set_leave_open ();
466  UNLOCK_VIS;
467  return FALSE;
468 }
469 
470 static void abort_write (void)
471 {
472  LOCKED;
473  g_return_if_fail (opened);
474  aborted = TRUE;
475  cop->flush (cop->output_time ());
476 }
477 
478 static void output_abort_write (void)
479 {
480  g_return_if_fail (cop != NULL);
481  LOCK;
482  abort_write ();
483  UNLOCK;
484 }
485 
486 const struct OutputAPI output_api =
487 {
489  .set_replaygain_info = output_set_replaygain_info,
490  .write_audio = output_write_audio,
491  .close_audio = output_close_audio,
492 
493  .pause = output_pause,
494  .flush = output_flush,
495  .written_time = output_written_time,
496  .buffer_playing = output_buffer_playing,
497  .abort_write = output_abort_write,
498 };
499 
500 static int output_time (void)
501 {
502  LOCKED_RET (0);
503  g_return_val_if_fail (opened || leave_open, 0);
504  return cop->output_time ();
505 }
506 
507 int get_output_time (void)
508 {
509  g_return_val_if_fail (cop != NULL, 0);
510  LOCK;
511 
512  int time = 0;
513  if (opened)
514  {
516  time = MAX (0, time);
517  }
518 
519  UNLOCK;
520  return time;
521 }
522 
524 {
525  g_return_val_if_fail (cop != NULL, 0);
526  LOCK;
527  int time = output_time ();
528  UNLOCK;
529  return time;
530 }
531 
532 void output_drain (void)
533 {
534  g_return_if_fail (cop != NULL);
535  LOCK_VIS;
536 
537  if (leave_open)
538  {
539  write_buffers ();
540  drain ();
541  real_close ();
542  }
543 
544  UNLOCK_VIS;
545 }
546 
548 {
549  OutputPlugin * op = plugin_get_header (p);
550  g_return_val_if_fail (op != NULL && op->init != NULL, TRUE);
551 
552  if (! op->init ())
553  return TRUE;
554 
555  if (op->cleanup != NULL)
556  op->cleanup ();
557 
558  * pp = p;
559  return FALSE;
560 }
561 
563 {
564  PluginHandle * p = NULL;
566  return p;
567 }
568 
570 {
571  return (cop != NULL) ? plugin_by_header (cop) : NULL;
572 }
573 
575 {
576  if (cop != NULL)
577  {
578  if (playback_get_playing ())
579  playback_stop ();
580 
581  if (cop->cleanup != NULL)
582  cop->cleanup ();
583 
584  cop = NULL;
585  }
586 
587  if (plugin != NULL)
588  {
589  OutputPlugin * op = plugin_get_header (plugin);
590  g_return_val_if_fail (op != NULL && op->init != NULL, FALSE);
591 
592  if (! op->init ())
593  return FALSE;
594 
595  cop = op;
596  }
597 
598  return TRUE;
599 }