Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
output.c
Go to the documentation of this file.
00001 /*
00002  * output.c
00003  * Copyright 2009-2010 John Lindgren
00004  *
00005  * This file is part of Audacious.
00006  *
00007  * Audacious is free software: you can redistribute it and/or modify it under
00008  * the terms of the GNU General Public License as published by the Free Software
00009  * Foundation, version 2 or version 3 of the License.
00010  *
00011  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
00012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00013  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along with
00016  * Audacious. If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * The Audacious team does not consider modular code linking to Audacious or
00019  * using our public API to be a derived work.
00020  */
00021 
00022 #include <math.h>
00023 #include <libaudcore/audio.h>
00024 
00025 #include "audconfig.h"
00026 #include "debug.h"
00027 #include "effect.h"
00028 #include "equalizer.h"
00029 #include "output.h"
00030 #include "playback.h"
00031 #include "plugins.h"
00032 #include "vis_runner.h"
00033 
00034 #define SW_VOLUME_RANGE 40 /* decibels */
00035 
00036 static OutputPlugin * cop = NULL;
00037 
00038 void output_get_volume (gint * l, gint * r)
00039 {
00040     if (cfg.software_volume_control)
00041     {
00042         * l = cfg.sw_volume_left;
00043         * r = cfg.sw_volume_right;
00044     }
00045     else if (cop != NULL && cop->get_volume != NULL)
00046         cop->get_volume (l, r);
00047     else
00048     {
00049         * l = 0;
00050         * r = 0;
00051     }
00052 }
00053 
00054 void output_set_volume (gint l, gint r)
00055 {
00056     if (cfg.software_volume_control)
00057     {
00058         cfg.sw_volume_left = l;
00059         cfg.sw_volume_right = r;
00060     }
00061     else if (cop != NULL && cop->set_volume != NULL)
00062         cop->set_volume (l, r);
00063 }
00064 
00065 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
00066 static gboolean locked = FALSE;
00067 
00068 #define LOCK do {g_static_mutex_lock (& mutex); locked = TRUE;} while (0)
00069 #define UNLOCK do {locked = FALSE; g_static_mutex_unlock (& mutex);} while (0)
00070 #define LOCKED g_return_if_fail (locked)
00071 #define LOCKED_RET(a) g_return_val_if_fail (locked, a)
00072 #define LOCK_VIS do {vis_runner_lock (); LOCK;} while (0)
00073 #define UNLOCK_VIS do {UNLOCK; vis_runner_unlock ();} while (0)
00074 #define LOCKED_VIS g_return_if_fail (locked && vis_runner_locked ())
00075 #define LOCKED_VIS_RET(a) g_return_val_if_fail (locked && vis_runner_locked (), a)
00076 
00077 static gboolean opened = FALSE;
00078 static gboolean leave_open = FALSE;
00079 
00080 static gboolean waiting, aborted, paused;
00081 static gint decoder_format, decoder_channels, decoder_rate, effect_channels,
00082  effect_rate, output_format, output_channels, output_rate;
00083 static gint64 frames_written;
00084 static gboolean have_replay_gain;
00085 static ReplayGainInfo replay_gain_info;
00086 
00087 static void reset_time (void)
00088 {
00089     LOCKED_VIS;
00090     g_return_if_fail (cop->set_written_time != NULL);
00091     vis_runner_time_offset (- cop->written_time ());
00092     cop->set_written_time (0);
00093 }
00094 
00095 static void drain (void)
00096 {
00097     LOCKED;
00098     g_return_if_fail (cop->drain != NULL);
00099     cop->drain ();
00100 }
00101 
00102 static void real_close (void)
00103 {
00104     LOCKED_VIS;
00105     vis_runner_start_stop (FALSE, FALSE);
00106     cop->close_audio ();
00107     opened = FALSE;
00108     leave_open = FALSE;
00109 }
00110 
00111 static gboolean open_audio (gint format, gint rate, gint channels)
00112 {
00113     LOCKED_VIS_RET (FALSE);
00114     g_return_val_if_fail (! opened, FALSE);
00115 
00116     decoder_format = format;
00117     decoder_channels = channels;
00118     decoder_rate = rate;
00119     effect_channels = channels;
00120     effect_rate = rate;
00121     effect_start (& effect_channels, & effect_rate);
00122     eq_set_format (effect_channels, effect_rate);
00123 
00124     if (leave_open && effect_channels == output_channels && effect_rate ==
00125      output_rate)
00126     {
00127         reset_time ();
00128         opened = TRUE;
00129     }
00130     else
00131     {
00132         if (leave_open)
00133         {
00134             drain ();
00135             real_close ();
00136         }
00137 
00138         output_format = cfg.output_bit_depth == 32 ? FMT_S32_NE :
00139          cfg.output_bit_depth == 24 ? FMT_S24_NE : cfg.output_bit_depth == 16 ?
00140          FMT_S16_NE : FMT_FLOAT;
00141         output_channels = effect_channels;
00142         output_rate = effect_rate;
00143 
00144         if (cop->open_audio (output_format, output_rate, output_channels))
00145         {
00146             vis_runner_start_stop (TRUE, FALSE);
00147             opened = TRUE;
00148         }
00149     }
00150 
00151     leave_open = FALSE;
00152     waiting = FALSE;
00153     aborted = FALSE;
00154     paused = FALSE;
00155     frames_written = 0;
00156     have_replay_gain = FALSE;
00157 
00158     return opened;
00159 }
00160 
00161 static gboolean output_open_audio (gint format, gint rate, gint channels)
00162 {
00163     g_return_val_if_fail (cop != NULL, FALSE);
00164     LOCK_VIS;
00165     gboolean success = open_audio (format, rate, channels);
00166     UNLOCK_VIS;
00167     return success;
00168 }
00169 
00170 static void set_gain (ReplayGainInfo * info)
00171 {
00172     LOCKED;
00173     g_return_if_fail (opened && ! waiting);
00174 
00175     AUDDBG ("Replay Gain info:\n");
00176     AUDDBG (" album gain: %f dB\n", info->album_gain);
00177     AUDDBG (" album peak: %f\n", info->album_peak);
00178     AUDDBG (" track gain: %f dB\n", info->track_gain);
00179     AUDDBG (" track peak: %f\n", info->track_peak);
00180 
00181     have_replay_gain = TRUE;
00182     memcpy (& replay_gain_info, info, sizeof (ReplayGainInfo));
00183 }
00184 
00185 static void output_set_replaygain_info (ReplayGainInfo * info)
00186 {
00187     g_return_if_fail (cop != NULL);
00188     LOCK;
00189     set_gain (info);
00190     UNLOCK;
00191 }
00192 
00193 static void apply_replay_gain (gfloat * data, gint samples)
00194 {
00195     gfloat factor = powf (10, (gfloat) cfg.replay_gain_preamp / 20);
00196 
00197     if (! cfg.enable_replay_gain)
00198         return;
00199 
00200     if (have_replay_gain)
00201     {
00202         if (cfg.replay_gain_album)
00203         {
00204             factor *= powf (10, replay_gain_info.album_gain / 20);
00205 
00206             if (cfg.enable_clipping_prevention &&
00207              replay_gain_info.album_peak * factor > 1)
00208                 factor = 1 / replay_gain_info.album_peak;
00209         }
00210         else
00211         {
00212             factor *= powf (10, replay_gain_info.track_gain / 20);
00213 
00214             if (cfg.enable_clipping_prevention &&
00215              replay_gain_info.track_peak * factor > 1)
00216                 factor = 1 / replay_gain_info.track_peak;
00217         }
00218     }
00219     else
00220         factor *= powf (10, (gfloat) cfg.default_gain / 20);
00221 
00222     if (factor < 0.99 || factor > 1.01)
00223         audio_amplify (data, 1, samples, & factor);
00224 }
00225 
00226 static void apply_software_volume (gfloat * data, gint channels, gint frames)
00227 {
00228     gfloat left_factor, right_factor;
00229     gfloat factors[channels];
00230     gint channel;
00231 
00232     if (! cfg.software_volume_control || (cfg.sw_volume_left == 100 &&
00233      cfg.sw_volume_right == 100))
00234         return;
00235 
00236     left_factor = (cfg.sw_volume_left == 0) ? 0 : powf (10, (gfloat)
00237      SW_VOLUME_RANGE * (cfg.sw_volume_left - 100) / 100 / 20);
00238     right_factor = (cfg.sw_volume_right == 0) ? 0 : powf (10, (gfloat)
00239      SW_VOLUME_RANGE * (cfg.sw_volume_right - 100) / 100 / 20);
00240 
00241     if (channels == 2)
00242     {
00243         factors[0] = left_factor;
00244         factors[1] = right_factor;
00245     }
00246     else
00247     {
00248         for (channel = 0; channel < channels; channel ++)
00249             factors[channel] = MAX (left_factor, right_factor);
00250     }
00251 
00252     audio_amplify (data, channels, frames, factors);
00253 }
00254 
00255 static void write_processed (void * data, gint samples)
00256 {
00257     LOCKED_VIS;
00258 
00259     if (! samples)
00260         return;
00261 
00262     vis_runner_pass_audio (cop->written_time (), data, samples, output_channels,
00263      output_rate);
00264     eq_filter (data, samples);
00265     apply_software_volume (data, output_channels, samples / output_channels);
00266 
00267     void * allocated = NULL;
00268 
00269     if (output_format != FMT_FLOAT)
00270     {
00271         void * new = g_malloc (FMT_SIZEOF (output_format) * samples);
00272         audio_to_int (data, new, output_format, samples);
00273         data = new;
00274         g_free (allocated);
00275         allocated = new;
00276     }
00277 
00278     while (! aborted)
00279     {
00280         gint ready = (cop->buffer_free != NULL) ? cop->buffer_free () /
00281          FMT_SIZEOF (output_format) : output_channels * (output_rate / 50);
00282         ready = MIN (ready, samples);
00283         cop->write_audio (data, FMT_SIZEOF (output_format) * ready);
00284         data = (char *) data + FMT_SIZEOF (output_format) * ready;
00285         samples -= ready;
00286 
00287         if (! samples)
00288             break;
00289 
00290         waiting = TRUE;
00291         UNLOCK_VIS;
00292 
00293         if (cop->period_wait != NULL)
00294             cop->period_wait ();
00295         else if (cop->buffer_free != NULL)
00296             g_usleep (20000);
00297 
00298         LOCK_VIS;
00299         waiting = FALSE;
00300     }
00301 
00302     g_free (allocated);
00303 }
00304 
00305 static void write_audio (void * data, gint size)
00306 {
00307     LOCKED;
00308     g_return_if_fail (opened && ! waiting);
00309 
00310     gint samples = size / FMT_SIZEOF (decoder_format);
00311     frames_written += samples / decoder_channels;
00312 
00313     void * allocated = NULL;
00314 
00315     if (decoder_format != FMT_FLOAT)
00316     {
00317         gfloat * new = g_malloc (sizeof (gfloat) * samples);
00318         audio_from_int (data, decoder_format, new, samples);
00319         data = new;
00320         g_free (allocated);
00321         allocated = new;
00322     }
00323 
00324     apply_replay_gain (data, samples);
00325     gfloat * fdata = data;
00326     effect_process (& fdata, & samples);
00327     data = fdata;
00328 
00329     if (data != allocated)
00330     {
00331         g_free (allocated);
00332         allocated = NULL;
00333     }
00334 
00335     write_processed (data, samples);
00336     g_free (allocated);
00337 }
00338 
00339 static void output_write_audio (void * data, gint size)
00340 {
00341     g_return_if_fail (cop != NULL);
00342     LOCK_VIS;
00343     write_audio (data, size);
00344     UNLOCK_VIS;
00345 }
00346 
00347 static void close_audio (void)
00348 {
00349     LOCKED;
00350     g_return_if_fail (opened && ! waiting);
00351     opened = FALSE;
00352 
00353     if (! leave_open)
00354     {
00355         effect_flush ();
00356         real_close ();
00357     }
00358 }
00359 
00360 static void output_close_audio (void)
00361 {
00362     g_return_if_fail (cop != NULL);
00363     LOCK_VIS;
00364     close_audio ();
00365     UNLOCK_VIS;
00366 }
00367 
00368 static void do_pause (gboolean p)
00369 {
00370     LOCKED_VIS;
00371     g_return_if_fail (opened);
00372     cop->pause (p);
00373     vis_runner_start_stop (TRUE, p);
00374     paused = p;
00375 }
00376 
00377 static void output_pause (gboolean p)
00378 {
00379     g_return_if_fail (cop != NULL);
00380     LOCK_VIS;
00381     do_pause (p);
00382     UNLOCK_VIS;
00383 }
00384 
00385 static void flush (gint time)
00386 {
00387     LOCKED_VIS;
00388     g_return_if_fail (opened);
00389 
00390     aborted = FALSE;
00391 
00392     /* When playback is started from the middle of a song, flush() is called
00393      * before any audio is actually written in order to set the time counter.
00394      * In this case, we do not want to cut off the end of the previous song, so
00395      * we do not actually flush. */
00396     if (! frames_written)
00397     {
00398         g_return_if_fail (cop->set_written_time != NULL);
00399         cop->set_written_time (time);
00400     }
00401     else
00402     {
00403         vis_runner_flush ();
00404         effect_flush ();
00405         cop->flush (effect_decoder_to_output_time (time));
00406     }
00407 
00408     frames_written = time * (gint64) decoder_rate / 1000;
00409 }
00410 
00411 static void output_flush (gint time)
00412 {
00413     g_return_if_fail (cop != NULL);
00414     LOCK_VIS;
00415     flush (time);
00416     UNLOCK_VIS;
00417 }
00418 
00419 static gint written_time (void)
00420 {
00421     LOCKED_RET (0);
00422     g_return_val_if_fail (opened && ! waiting, 0);
00423     return frames_written * (gint64) 1000 / decoder_rate;
00424 }
00425 
00426 static gint output_written_time (void)
00427 {
00428     g_return_val_if_fail (cop != NULL, 0);
00429     LOCK;
00430     gint time = written_time ();
00431     UNLOCK;
00432     return time;
00433 }
00434 
00435 static void write_buffers (void)
00436 {
00437     LOCKED;
00438     gfloat * data = NULL;
00439     gint samples = 0;
00440     effect_finish (& data, & samples);
00441     write_processed (data, samples);
00442 }
00443 
00444 static void set_leave_open (void)
00445 {
00446     LOCKED;
00447     g_return_if_fail (opened && ! waiting);
00448 
00449     if (! paused)
00450     {
00451         write_buffers ();
00452         leave_open = TRUE;
00453     }
00454 }
00455 
00456 static gboolean output_buffer_playing (void)
00457 {
00458     g_return_val_if_fail (cop != NULL, FALSE);
00459     LOCK_VIS;
00460     set_leave_open ();
00461     UNLOCK_VIS;
00462     return FALSE;
00463 }
00464 
00465 static void abort_write (void)
00466 {
00467     LOCKED;
00468     g_return_if_fail (opened);
00469     aborted = TRUE;
00470     cop->flush (cop->output_time ());
00471 }
00472 
00473 static void output_abort_write (void)
00474 {
00475     g_return_if_fail (cop != NULL);
00476     LOCK;
00477     abort_write ();
00478     UNLOCK;
00479 }
00480 
00481 const struct OutputAPI output_api =
00482 {
00483     .open_audio = output_open_audio,
00484     .set_replaygain_info = output_set_replaygain_info,
00485     .write_audio = output_write_audio,
00486     .close_audio = output_close_audio,
00487 
00488     .pause = output_pause,
00489     .flush = output_flush,
00490     .written_time = output_written_time,
00491     .buffer_playing = output_buffer_playing,
00492     .abort_write = output_abort_write,
00493 };
00494 
00495 static gint output_time (void)
00496 {
00497     LOCKED_RET (0);
00498     g_return_val_if_fail (opened || leave_open, 0);
00499     return cop->output_time ();
00500 }
00501 
00502 gint get_output_time (void)
00503 {
00504     g_return_val_if_fail (cop != NULL, 0);
00505     LOCK;
00506 
00507     gint time = 0;
00508     if (opened)
00509     {
00510         time = effect_output_to_decoder_time (output_time ());
00511         time = MAX (0, time);
00512     }
00513 
00514     UNLOCK;
00515     return time;
00516 }
00517 
00518 gint get_raw_output_time (void)
00519 {
00520     g_return_val_if_fail (cop != NULL, 0);
00521     LOCK;
00522     gint time = output_time ();
00523     UNLOCK;
00524     return time;
00525 }
00526 
00527 void output_drain (void)
00528 {
00529     g_return_if_fail (cop != NULL);
00530     LOCK_VIS;
00531 
00532     if (leave_open)
00533     {
00534         write_buffers ();
00535         drain ();
00536         real_close ();
00537     }
00538 
00539     UNLOCK_VIS;
00540 }
00541 
00542 static gboolean probe_cb (PluginHandle * p, PluginHandle * * pp)
00543 {
00544     OutputPlugin * op = plugin_get_header (p);
00545     g_return_val_if_fail (op != NULL && op->init != NULL, TRUE);
00546 
00547     if (! op->init ())
00548         return TRUE;
00549 
00550     if (op->cleanup != NULL)
00551         op->cleanup ();
00552 
00553     * pp = p;
00554     return FALSE;
00555 }
00556 
00557 PluginHandle * output_plugin_probe (void)
00558 {
00559     PluginHandle * p = NULL;
00560     plugin_for_each (PLUGIN_TYPE_OUTPUT, (PluginForEachFunc) probe_cb, & p);
00561     return p;
00562 }
00563 
00564 PluginHandle * output_plugin_get_current (void)
00565 {
00566     return (cop != NULL) ? plugin_by_header (cop) : NULL;
00567 }
00568 
00569 gboolean output_plugin_set_current (PluginHandle * plugin)
00570 {
00571     if (cop != NULL)
00572     {
00573         if (playback_get_playing ())
00574             playback_stop ();
00575 
00576         if (cop->cleanup != NULL)
00577             cop->cleanup ();
00578 
00579         cop = NULL;
00580     }
00581 
00582     if (plugin != NULL)
00583     {
00584         OutputPlugin * op = plugin_get_header (plugin);
00585         g_return_val_if_fail (op != NULL && op->init != NULL, FALSE);
00586 
00587         if (! op->init ())
00588             return FALSE;
00589 
00590         cop = op;
00591     }
00592 
00593     return TRUE;
00594 }