Audacious
$Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
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 }