Mercurial > audlegacy
view audacious/output.c @ 1938:1d9c1026d9f8 trunk
[svn] - DoubleSize support.
This has bugs, the most notable one being that DoubleSize only works
right if you restart the player.
The second bug is rather obvious too. No osmosis skinengine. No
TinyPlayer. Classic-esque skinengine only. This is because the
doublesize algorithm hates you and wants you to go die in a fire.
author | nenolod |
---|---|
date | Sun, 05 Nov 2006 04:43:16 -0800 |
parents | def887eae029 |
children | a99862e5bd65 |
line wrap: on
line source
/* BMP - Cross-platform multimedia player * Copyright (C) 2003-2004 BMP development team. * * Based on XMMS: * Copyright (C) 1998-2003 XMMS development team. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "output.h" #include "iir.h" #include "main.h" #include "input.h" #include "playlist.h" #include "libaudacious/util.h" OutputPluginData op_data = { NULL, NULL }; OutputPluginState op_state = { 0, 0, 0 }; OutputPlugin psuedo_output_plugin = { NULL, NULL, "XMMS reverse compatibility output plugin", NULL, NULL, NULL, NULL, output_get_volume, output_set_volume, output_open_audio, output_write_audio, output_close_audio, output_flush, output_pause, output_buffer_free, output_buffer_playing, get_output_time, get_written_time, NULL }; OutputPlugin * get_current_output_plugin(void) { return op_data.current_output_plugin; } void set_current_output_plugin(gint i) { #if 0 gint time; gint pos; gboolean playing; #endif GList *node = g_list_nth(op_data.output_list, i); if (!node) { op_data.current_output_plugin = NULL; return; } op_data.current_output_plugin = node->data; #if 0 playing = bmp_playback_get_playing(); if (playing) { /* FIXME: we do all on our own here */ guint min = 0, sec = 0, params, time, pos; gchar timestr[10]; bmp_playback_pause(); pos = get_playlist_position(); time = bmp_playback_get_time() / 1000; g_snprintf(timestr, sizeof(timestr), "%u:%2.2u", time / 60, time % 60); params = sscanf(timestr, "%u:%u", &min, &sec); if (params == 2) time = (min * 60) + sec; else if (params == 1) time = min; else return; bmp_playback_stop(); playlist_set_position(pos); bmp_playback_play_file(playlist_get_filename(pos)); while (!bmp_playback_get_playing()) g_message("waiting..."); if (playlist_get_current_length() > -1 && time <= (playlist_get_current_length() / 1000)) { /* Some time for things to cool down and heat up */ g_usleep(1000000); bmp_playback_seek(time); } } #endif } GList * get_output_list(void) { return op_data.output_list; } void output_about(gint i) { OutputPlugin *out = g_list_nth(op_data.output_list, i)->data; if (out && out->about) out->about(); } void output_configure(gint i) { OutputPlugin *out = g_list_nth(op_data.output_list, i)->data; if (out && out->configure) out->configure(); } void output_get_volume(gint * l, gint * r) { *l = *r = -1; if (!op_data.current_output_plugin) return; if (!op_data.current_output_plugin->get_volume) return; op_data.current_output_plugin->get_volume(l, r); } void output_set_volume(gint l, gint r) { if (!op_data.current_output_plugin) return; if (!op_data.current_output_plugin->set_volume) return; op_data.current_output_plugin->set_volume(l, r); } void output_set_eq(gboolean active, gfloat pre, gfloat * bands) { int i; preamp[0] = 1.0 + 0.0932471 * pre + 0.00279033 * pre * pre; preamp[1] = 1.0 + 0.0932471 * pre + 0.00279033 * pre * pre; for (i = 0; i < 10; ++i) { set_gain(i, 0, 0.03 * bands[i] + 0.000999999 * bands[i] * bands[i]); set_gain(i, 1, 0.03 * bands[i] + 0.000999999 * bands[i] * bands[i]); } } /* this should be in BYTES, NOT gint16s */ static void byteswap(size_t size, gint16 * buf) { gint16 *it; size &= ~1; /* must be multiple of 2 */ for (it = buf; it < buf + size / 2; ++it) *(guint16 *) it = GUINT16_SWAP_LE_BE(*(guint16 *) it); } /* called by input plugin to peek at the output plugin's write progress */ gint get_written_time(void) { OutputPlugin *op = get_current_output_plugin(); return op->written_time(); } /* called by input plugin to peek at the output plugin's output progress */ gint get_output_time(void) { OutputPlugin *op = get_current_output_plugin(); return op->output_time(); } gint output_open_audio(AFormat fmt, gint rate, gint nch) { gint ret; OutputPlugin *op; op = get_current_output_plugin(); if (op == NULL) return -1; /* Is our output port already open? */ if ((op_state.rate != 0 && op_state.nch != 0) && (op_state.rate == rate && op_state.nch == nch && op_state.fmt == fmt)) { /* Yes, and it's the correct sampling rate. Reset the counter and go. */ op->flush(0); return 1; } else if (op_state.rate != 0 && op_state.nch != 0) op->close_audio(); ret = op->open_audio(fmt, rate, nch); if (ret == 1) /* Success? */ { op_state.fmt = fmt; op_state.rate = rate; op_state.nch = nch; } return ret; } void output_write_audio(gpointer ptr, gint length) { OutputPlugin *op = get_current_output_plugin(); /* Sanity check. */ if (op == NULL) return; op->write_audio(ptr, length); } void output_close_audio(void) { OutputPlugin *op = get_current_output_plugin(); /* Do not close if there are still songs to play and the user has * not requested a stop. --nenolod */ if (ip_data.stop == FALSE && (playlist_get_position_nolock() < playlist_get_length_nolock() - 1)) return; /* Sanity check. */ if (op == NULL) return; op->close_audio(); /* Reset the op_state. */ op_state.fmt = op_state.rate = op_state.nch = 0; } void output_flush(gint time) { OutputPlugin *op = get_current_output_plugin(); if (op == NULL) return; op->flush(time); } void output_pause(gshort paused) { OutputPlugin *op = get_current_output_plugin(); if (op == NULL) return; op->pause(paused); } gint output_buffer_free(void) { OutputPlugin *op = get_current_output_plugin(); if (op == NULL) return 0; return op->buffer_free(); } gint output_buffer_playing(void) { OutputPlugin *op = get_current_output_plugin(); if (op == NULL) return 0; return op->buffer_playing(); } /* called by input plugin when data is ready */ void produce_audio(gint time, /* position */ AFormat fmt, /* output format */ gint nch, /* channels */ gint length, /* length of sample */ gpointer ptr, /* data */ int *going /* 0 when time to stop */ ) { static int init = 0; int swapped = 0; guint myorder = G_BYTE_ORDER == G_LITTLE_ENDIAN ? FMT_S16_LE : FMT_S16_BE; int caneq = (fmt == FMT_S16_NE || fmt == myorder); OutputPlugin *op = get_current_output_plugin(); int writeoffs; if (!caneq && cfg.equalizer_active) { /* wrong byte order */ byteswap(length, ptr); /* so convert */ ++swapped; ++caneq; } /* can eq now, mark swapd */ else if (caneq && !cfg.equalizer_active) /* right order but no eq */ caneq = 0; /* so don't eq */ if (caneq) { /* if eq enab */ if (!init) { /* if first run */ init_iir(); /* then init eq */ ++init; } iir(&ptr, length, nch); if (swapped) /* if was swapped */ byteswap(length, ptr); /* swap back for output */ } /* do vis plugin(s) */ input_add_vis_pcm(time, fmt, nch, length, ptr); writeoffs = 0; while (writeoffs < length) { int writable = length - writeoffs; if (writable > 2048) writable = 2048; if (writable == 0) return; while (op->buffer_free() < writable) { /* wait output buf */ if (going && !*going) /* thread stopped? */ return; /* so finish */ if (ip_data.stop) /* has a stop been requested? */ return; /* yes, so finish */ g_usleep(10000); /* else sleep for retry */ } if (ip_data.stop) return; /* do output */ op->write_audio(((guint8 *) ptr) + writeoffs, writable); writeoffs += writable; } }