summaryrefslogtreecommitdiffstats
path: root/libao2/ao_jack.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /libao2/ao_jack.c
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2
mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in a more logical way. Make the top-level directory less cluttered as well. Renames the following directories: libaf -> audio/filter libao2 -> audio/out libvo -> video/out libmpdemux -> demux Split libmpcodecs: vf* -> video/filter vd*, dec_video.* -> video/decode mp_image*, img_format*, ... -> video/ ad*, dec_audio.* -> audio/decode libaf/format.* is moved to audio/ - this is similar to how mp_image.* is located in video/. Move most top-level .c/.h files to core. (talloc.c/.h is left on top- level, because it's external.) Park some of the more annoying files in compat/. Some of these are relicts from the time mplayer used ffmpeg internals. sub/ is not split, because it's too much of a mess (subtitle code is mixed with OSD display and rendering). Maybe the organization of core is not ideal: it mixes playback core (like mplayer.c) and utility helpers (like bstr.c/h). Should the need arise, the playback core will be moved somewhere else, while core contains all helper and common code.
Diffstat (limited to 'libao2/ao_jack.c')
-rw-r--r--libao2/ao_jack.c361
1 files changed, 0 insertions, 361 deletions
diff --git a/libao2/ao_jack.c b/libao2/ao_jack.c
deleted file mode 100644
index b30f99a14e..0000000000
--- a/libao2/ao_jack.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * JACK audio output driver for MPlayer
- *
- * Copyleft 2001 by Felix Bünemann (atmosfear@users.sf.net)
- * and Reimar Döffinger (Reimar.Doeffinger@stud.uni-karlsruhe.de)
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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
- * along with MPlayer; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "audio_out.h"
-#include "audio_out_internal.h"
-#include "libaf/format.h"
-#include "osdep/timer.h"
-#include "subopt-helper.h"
-
-#include "libavutil/fifo.h"
-
-#include <jack/jack.h>
-
-static const ao_info_t info =
-{
- "JACK audio output",
- "jack",
- "Reimar Döffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de>",
- "based on ao_sdl.c"
-};
-
-LIBAO_EXTERN(jack)
-
-//! maximum number of channels supported, avoids lots of mallocs
-#define MAX_CHANS 8
-static jack_port_t *ports[MAX_CHANS];
-static int num_ports; ///< Number of used ports == number of channels
-static jack_client_t *client;
-static float jack_latency;
-static int estimate;
-static volatile int paused = 0; ///< set if paused
-static volatile int underrun = 0; ///< signals if an underrun occured
-
-static volatile float callback_interval = 0;
-static volatile float callback_time = 0;
-
-//! size of one chunk, if this is too small MPlayer will start to "stutter"
-//! after a short time of playback
-#define CHUNK_SIZE (16 * 1024)
-//! number of "virtual" chunks the buffer consists of
-#define NUM_CHUNKS 8
-#define BUFFSIZE (NUM_CHUNKS * CHUNK_SIZE)
-
-//! buffer for audio data
-static AVFifoBuffer *buffer;
-
-/**
- * \brief insert len bytes into buffer
- * \param data data to insert
- * \param len length of data
- * \return number of bytes inserted into buffer
- *
- * If there is not enough room, the buffer is filled up
- */
-static int write_buffer(unsigned char* data, int len) {
- int free = av_fifo_space(buffer);
- if (len > free) len = free;
- return av_fifo_generic_write(buffer, data, len, NULL);
-}
-
-static void silence(float **bufs, int cnt, int num_bufs);
-
-struct deinterleave {
- float **bufs;
- int num_bufs;
- int cur_buf;
- int pos;
-};
-
-static void deinterleave(void *info, void *src, int len) {
- struct deinterleave *di = info;
- float *s = src;
- int i;
- len /= sizeof(float);
- for (i = 0; i < len; i++) {
- di->bufs[di->cur_buf++][di->pos] = s[i];
- if (di->cur_buf >= di->num_bufs) {
- di->cur_buf = 0;
- di->pos++;
- }
- }
-}
-
-/**
- * \brief read data from buffer and splitting it into channels
- * \param bufs num_bufs float buffers, each will contain the data of one channel
- * \param cnt number of samples to read per channel
- * \param num_bufs number of channels to split the data into
- * \return number of samples read per channel, equals cnt unless there was too
- * little data in the buffer
- *
- * Assumes the data in the buffer is of type float, the number of bytes
- * read is res * num_bufs * sizeof(float), where res is the return value.
- * If there is not enough data in the buffer remaining parts will be filled
- * with silence.
- */
-static int read_buffer(float **bufs, int cnt, int num_bufs) {
- struct deinterleave di = {bufs, num_bufs, 0, 0};
- int buffered = av_fifo_size(buffer);
- if (cnt * sizeof(float) * num_bufs > buffered) {
- silence(bufs, cnt, num_bufs);
- cnt = buffered / sizeof(float) / num_bufs;
- }
- av_fifo_generic_read(buffer, &di, cnt * num_bufs * sizeof(float), deinterleave);
- return cnt;
-}
-
-// end ring buffer stuff
-
-static int control(int cmd, void *arg) {
- return CONTROL_UNKNOWN;
-}
-
-/**
- * \brief fill the buffers with silence
- * \param bufs num_bufs float buffers, each will contain the data of one channel
- * \param cnt number of samples in each buffer
- * \param num_bufs number of buffers
- */
-static void silence(float **bufs, int cnt, int num_bufs) {
- int i;
- for (i = 0; i < num_bufs; i++)
- memset(bufs[i], 0, cnt * sizeof(float));
-}
-
-/**
- * \brief JACK Callback function
- * \param nframes number of frames to fill into buffers
- * \param arg unused
- * \return currently always 0
- *
- * Write silence into buffers if paused or an underrun occured
- */
-static int outputaudio(jack_nframes_t nframes, void *arg) {
- float *bufs[MAX_CHANS];
- int i;
- for (i = 0; i < num_ports; i++)
- bufs[i] = jack_port_get_buffer(ports[i], nframes);
- if (paused || underrun)
- silence(bufs, nframes, num_ports);
- else
- if (read_buffer(bufs, nframes, num_ports) < nframes)
- underrun = 1;
- if (estimate) {
- float now = (float)GetTimer() / 1000000.0;
- float diff = callback_time + callback_interval - now;
- if ((diff > -0.002) && (diff < 0.002))
- callback_time += callback_interval;
- else
- callback_time = now;
- callback_interval = (float)nframes / (float)ao_data.samplerate;
- }
- return 0;
-}
-
-/**
- * \brief print suboption usage help
- */
-static void print_help (void)
-{
- mp_msg (MSGT_AO, MSGL_FATAL,
- "\n-ao jack commandline help:\n"
- "Example: mpv -ao jack:port=myout\n"
- " connects mpv to the jack ports named myout\n"
- "\nOptions:\n"
- " port=<port name>\n"
- " Connects to the given ports instead of the default physical ones\n"
- " name=<client name>\n"
- " Client name to pass to JACK\n"
- " estimate\n"
- " Estimates the amount of data in buffers (experimental)\n"
- " autostart\n"
- " Automatically start JACK server if necessary\n"
- );
-}
-
-static int init(int rate, int channels, int format, int flags) {
- const char **matching_ports = NULL;
- char *port_name = NULL;
- char *client_name = NULL;
- int autostart = 0;
- const opt_t subopts[] = {
- {"port", OPT_ARG_MSTRZ, &port_name, NULL},
- {"name", OPT_ARG_MSTRZ, &client_name, NULL},
- {"estimate", OPT_ARG_BOOL, &estimate, NULL},
- {"autostart", OPT_ARG_BOOL, &autostart, NULL},
- {NULL}
- };
- jack_options_t open_options = JackUseExactName;
- int port_flags = JackPortIsInput;
- int i;
- estimate = 1;
- if (subopt_parse(ao_subdevice, subopts) != 0) {
- print_help();
- return 0;
- }
- if (channels > MAX_CHANS) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] Invalid number of channels: %i\n", channels);
- goto err_out;
- }
- if (!client_name) {
- client_name = malloc(40);
- sprintf(client_name, "mpv [%d]", getpid());
- }
- if (!autostart)
- open_options |= JackNoStartServer;
- client = jack_client_open(client_name, open_options, NULL);
- if (!client) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] cannot open server\n");
- goto err_out;
- }
- buffer = av_fifo_alloc(BUFFSIZE);
- jack_set_process_callback(client, outputaudio, 0);
-
- // list matching ports
- if (!port_name)
- port_flags |= JackPortIsPhysical;
- matching_ports = jack_get_ports(client, port_name, NULL, port_flags);
- if (!matching_ports || !matching_ports[0]) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] no physical ports available\n");
- goto err_out;
- }
- i = 1;
- while (matching_ports[i]) i++;
- if (channels > i) channels = i;
- num_ports = channels;
-
- // create out output ports
- for (i = 0; i < num_ports; i++) {
- char pname[30];
- snprintf(pname, 30, "out_%d", i);
- ports[i] = jack_port_register(client, pname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- if (!ports[i]) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] not enough ports available\n");
- goto err_out;
- }
- }
- if (jack_activate(client)) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] activate failed\n");
- goto err_out;
- }
- for (i = 0; i < num_ports; i++) {
- if (jack_connect(client, jack_port_name(ports[i]), matching_ports[i])) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] connecting failed\n");
- goto err_out;
- }
- }
- rate = jack_get_sample_rate(client);
- jack_latency = (float)(jack_port_get_total_latency(client, ports[0]) +
- jack_get_buffer_size(client)) / (float)rate;
- callback_interval = 0;
-
- ao_data.channels = channels;
- ao_data.samplerate = rate;
- ao_data.format = AF_FORMAT_FLOAT_NE;
- ao_data.bps = channels * rate * sizeof(float);
- ao_data.buffersize = CHUNK_SIZE * NUM_CHUNKS;
- ao_data.outburst = CHUNK_SIZE;
- free(matching_ports);
- free(port_name);
- free(client_name);
- return 1;
-
-err_out:
- free(matching_ports);
- free(port_name);
- free(client_name);
- if (client)
- jack_client_close(client);
- av_fifo_free(buffer);
- buffer = NULL;
- return 0;
-}
-
-// close audio device
-static void uninit(int immed) {
- if (!immed)
- usec_sleep(get_delay() * 1000 * 1000);
- // HACK, make sure jack doesn't loop-output dirty buffers
- reset();
- usec_sleep(100 * 1000);
- jack_client_close(client);
- av_fifo_free(buffer);
- buffer = NULL;
-}
-
-/**
- * \brief stop playing and empty buffers (for seeking/pause)
- */
-static void reset(void) {
- paused = 1;
- av_fifo_reset(buffer);
- paused = 0;
-}
-
-/**
- * \brief stop playing, keep buffers (for pause)
- */
-static void audio_pause(void) {
- paused = 1;
-}
-
-/**
- * \brief resume playing, after audio_pause()
- */
-static void audio_resume(void) {
- paused = 0;
-}
-
-static int get_space(void) {
- return av_fifo_space(buffer);
-}
-
-/**
- * \brief write data into buffer and reset underrun flag
- */
-static int play(void *data, int len, int flags) {
- if (!(flags & AOPLAY_FINAL_CHUNK))
- len -= len % ao_data.outburst;
- underrun = 0;
- return write_buffer(data, len);
-}
-
-static float get_delay(void) {
- int buffered = av_fifo_size(buffer); // could be less
- float in_jack = jack_latency;
- if (estimate && callback_interval > 0) {
- float elapsed = (float)GetTimer() / 1000000.0 - callback_time;
- in_jack += callback_interval - elapsed;
- if (in_jack < 0) in_jack = 0;
- }
- return (float)buffered / (float)ao_data.bps + in_jack;
-}