git-svn-id: svn+ssh://jackaudio.org/trunk/jack@454 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
@@ -13,7 +13,7 @@ dnl micro version = incremented when implementation-only | |||
dnl changes are made | |||
dnl --- | |||
JACK_MAJOR_VERSION=0 | |||
JACK_MINOR_VERSION=77 | |||
JACK_MINOR_VERSION=78 | |||
JACK_MICRO_VERSION=0 | |||
@@ -296,6 +296,7 @@ libjack/Makefile | |||
drivers/Makefile | |||
drivers/alsa/Makefile | |||
drivers/solaris/Makefile | |||
drivers/dummy/Makefile | |||
example-clients/Makefile | |||
doc/Makefile | |||
doc/reference.doxygen | |||
@@ -1,5 +1,6 @@ | |||
Makefile | |||
Makefile.in | |||
doxygen-build.stamp | |||
reference | |||
reference.doxygen | |||
html | |||
latex |
@@ -6,7 +6,7 @@ DOX=reference.doxygen | |||
EXTRA_DIST= | |||
INSTIMAGES=reference/html/doxygen.png reference/html/fsm.png | |||
INSTIMAGES=html/doxygen.png /html/fsm.png | |||
DOC_STAMPS=html-build.stamp | |||
@@ -25,36 +25,36 @@ clean-local: | |||
distclean-local: clean | |||
rm -f *.stamp || true | |||
if test -d reference; then rm -rf reference; fi | |||
if test -d html; then rm -rf html; fi | |||
if test -d latex; then rm -rf latex; fi | |||
install-data-local: | |||
$(mkinstalldirs) $(DESTDIR)$(DOC_DIR)/reference/html | |||
(installfiles=`echo reference/html/*.html`; \ | |||
if test "$$installfiles" = 'reference/html/*.html'; \ | |||
$(mkinstalldirs) $(DESTDIR)$(DOC_DIR)/html | |||
(installfiles=`echo html/*.html`; \ | |||
if test "$$installfiles" = 'html/*.html'; \ | |||
then echo '-- Nothing to install' ; \ | |||
else \ | |||
for i in $$installfiles $(INSTIMAGES) reference/html/doxygen.css; do \ | |||
for i in $$installfiles $(INSTIMAGES) html/doxygen.css; do \ | |||
echo '-- Installing '$$i ; \ | |||
$(INSTALL_DATA) $$i $(DESTDIR)$(DOC_DIR)/reference/html; \ | |||
$(INSTALL_DATA) $$i $(DESTDIR)$(DOC_DIR)/html; \ | |||
done; \ | |||
fi) | |||
# we need doxygen stuff built so we can know what to uninstall | |||
uninstall-local: doxygen-build.stamp | |||
(installfiles=`echo reference/html/*.html`; \ | |||
if test "$$installfiles" = 'reference/html/*.html'; \ | |||
(installfiles=`echo html/*.html`; \ | |||
if test "$$installfiles" = 'html/*.html'; \ | |||
then echo '-- Nothing to uninstall' ; \ | |||
else \ | |||
for i in $$installfiles $(INSTIMAGES) reference/html/doxygen.css; do \ | |||
for i in $$installfiles $(INSTIMAGES) html/doxygen.css; do \ | |||
echo '-- Unstalling '$$i ; \ | |||
rm $(DESTDIR)$(DOC_DIR)/$$i; \ | |||
done; \ | |||
fi) | |||
dist-hook: dist-hook-local | |||
mkdir $(distdir)/reference | |||
mkdir $(distdir)/reference/html | |||
-cp reference/html/*.html reference/html/*.css \ | |||
reference/html/*.png $(distdir)/reference/html | |||
mkdir $(distdir)/html | |||
-cp html/*.html html/*.css \ | |||
html/*.png $(distdir)/html | |||
.PHONY : dist-hook-local |
@@ -30,7 +30,7 @@ PROJECT_NUMBER = @JACK_VERSION@ | |||
# If a relative path is entered, it will be relative to the location | |||
# where doxygen was started. If left blank the current directory will be used. | |||
OUTPUT_DIRECTORY = reference | |||
OUTPUT_DIRECTORY = | |||
# The OUTPUT_LANGUAGE tag is used to specify the language in which all | |||
# documentation generated by doxygen is written. Doxygen will use this | |||
@@ -12,6 +12,7 @@ else | |||
SOLARIS_DIR = | |||
endif | |||
SUBDIRS = $(ALSA_DIR) $(SOLARIS_DIR) | |||
SUBDIRS = dummy $(ALSA_DIR) $(SOLARIS_DIR) | |||
DIST_SUBDIRS = dummy alsa solaris | |||
DIST_SUBDIRS = alsa solaris |
@@ -191,9 +191,9 @@ static void | |||
alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) | |||
{ | |||
switch (driver->sample_bytes) { | |||
switch (driver->playback_sample_bytes) { | |||
case 2: | |||
if (driver->interleaved) { | |||
if (driver->playback_interleaved) { | |||
driver->channel_copy = memcpy_interleave_d16_s16; | |||
} else { | |||
driver->channel_copy = memcpy_fake; | |||
@@ -219,12 +219,10 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) | |||
driver->write_via_copy = sample_move_d16_sS; | |||
break; | |||
} | |||
driver->read_via_copy = sample_move_dS_s16; | |||
break; | |||
case 4: | |||
if (driver->interleaved) { | |||
if (driver->playback_interleaved) { | |||
driver->channel_copy = memcpy_interleave_d32_s32; | |||
} else { | |||
driver->channel_copy = memcpy_fake; | |||
@@ -250,9 +248,15 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) | |||
driver->write_via_copy = sample_move_d32u24_sS; | |||
break; | |||
} | |||
break; | |||
} | |||
switch (driver->capture_sample_bytes) { | |||
case 2: | |||
driver->read_via_copy = sample_move_dS_s16; | |||
break; | |||
case 4: | |||
driver->read_via_copy = sample_move_dS_s32u24; | |||
break; | |||
} | |||
} | |||
@@ -389,10 +393,6 @@ static int | |||
alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cycle, jack_nframes_t user_nperiods, jack_nframes_t rate) | |||
{ | |||
int p_noninterleaved = 0; | |||
int c_noninterleaved = 0; | |||
snd_pcm_format_t c_format = 0; | |||
snd_pcm_format_t p_format = 0; | |||
int dir; | |||
unsigned int p_period_size = 0; | |||
unsigned int c_period_size = 0; | |||
@@ -431,8 +431,8 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc | |||
if (driver->playback_handle) { | |||
p_period_size = snd_pcm_hw_params_get_period_size (driver->playback_hw_params, &dir); | |||
p_nfragments = snd_pcm_hw_params_get_periods (driver->playback_hw_params, &dir); | |||
p_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->playback_hw_params); | |||
p_noninterleaved = (snd_pcm_hw_params_get_access (driver->playback_hw_params) == SND_PCM_ACCESS_MMAP_NONINTERLEAVED); | |||
driver->playback_sample_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->playback_hw_params); | |||
driver->playback_interleaved = (snd_pcm_hw_params_get_access (driver->playback_hw_params) == SND_PCM_ACCESS_MMAP_INTERLEAVED); | |||
if (p_period_size != driver->frames_per_cycle) { | |||
jack_error ("alsa_pcm: requested an interrupt every %u frames but got %uc frames for playback", | |||
@@ -444,8 +444,8 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc | |||
if (driver->capture_handle) { | |||
c_period_size = snd_pcm_hw_params_get_period_size (driver->capture_hw_params, &dir); | |||
c_nfragments = snd_pcm_hw_params_get_periods (driver->capture_hw_params, &dir); | |||
c_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->capture_hw_params); | |||
c_noninterleaved = (snd_pcm_hw_params_get_access (driver->capture_hw_params) == SND_PCM_ACCESS_MMAP_NONINTERLEAVED); | |||
driver->capture_sample_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->capture_hw_params); | |||
driver->capture_interleaved = (snd_pcm_hw_params_get_access (driver->capture_hw_params) == SND_PCM_ACCESS_MMAP_INTERLEAVED); | |||
if (c_period_size != driver->frames_per_cycle) { | |||
jack_error ("alsa_pcm: requested an interrupt every %u frames but got %uc frames for capture", | |||
@@ -460,44 +460,35 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc | |||
return -1; | |||
} | |||
/* Check that we are using the same sample format on both streams */ | |||
if (p_format != c_format) { | |||
jack_error ("Sorry. The PCM device \"%s\" and \"%s\"" | |||
"don't support the same sample format for capture and playback." | |||
"We cannot use this PCM device.", driver->alsa_name_playback, driver->alsa_name_capture ); | |||
return -1; | |||
} | |||
/* check interleave setup */ | |||
if (c_noninterleaved != p_noninterleaved) { | |||
jack_error ("ALSA: the playback and capture components for this PCM device differ " | |||
"in their use of channel interleaving. We cannot use this PCM device."); | |||
return -1; | |||
} | |||
driver->nfragments = c_nfragments; | |||
driver->interleaved = !c_noninterleaved; | |||
driver->sample_format = c_format; | |||
} else if (driver->capture_handle) { | |||
driver->nfragments = c_nfragments; | |||
driver->interleaved = !c_noninterleaved; | |||
driver->sample_format = c_format; | |||
} else { | |||
driver->nfragments = p_nfragments; | |||
driver->interleaved = !p_noninterleaved; | |||
driver->sample_format = p_format; | |||
} | |||
driver->buffer_frames = driver->frames_per_cycle * driver->nfragments; | |||
driver->sample_bytes = snd_pcm_format_physical_width (driver->sample_format) / 8; | |||
driver->playback_sample_bytes = snd_pcm_format_physical_width (driver->playback_sample_format) / 8; | |||
driver->capture_sample_bytes = snd_pcm_format_physical_width (driver->capture_sample_format) / 8; | |||
switch (driver->playback_sample_format) { | |||
case SND_PCM_FORMAT_S32_LE: | |||
case SND_PCM_FORMAT_S16_LE: | |||
case SND_PCM_FORMAT_S32_BE: | |||
case SND_PCM_FORMAT_S16_BE: | |||
break; | |||
default: | |||
jack_error ("programming error: unhandled format type for playback"); | |||
exit (1); | |||
} | |||
switch (driver->sample_format) { | |||
switch (driver->capture_sample_format) { | |||
case SND_PCM_FORMAT_S32_LE: | |||
case SND_PCM_FORMAT_S16_LE: | |||
case SND_PCM_FORMAT_S32_BE: | |||
@@ -505,11 +496,11 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc | |||
break; | |||
default: | |||
jack_error ("programming error: unhandled format type"); | |||
jack_error ("programming error: unhandled format type for capture"); | |||
exit (1); | |||
} | |||
if (driver->interleaved) { | |||
if (driver->playback_interleaved) { | |||
const snd_pcm_channel_area_t *my_areas; | |||
snd_pcm_uframes_t offset, frames; | |||
if (snd_pcm_mmap_begin(driver->playback_handle, &my_areas, &offset, &frames) < 0) { | |||
@@ -517,16 +508,22 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc | |||
return -1; | |||
} | |||
driver->playback_interleave_skip = my_areas[0].step / 8; | |||
driver->interleave_unit = snd_pcm_format_physical_width (driver->playback_sample_format) / 8; | |||
} else { | |||
driver->interleave_unit = 0; /* NOT USED */ | |||
driver->playback_interleave_skip = snd_pcm_format_physical_width (driver->playback_sample_format) / 8; | |||
} | |||
if (driver->capture_interleaved) { | |||
const snd_pcm_channel_area_t *my_areas; | |||
snd_pcm_uframes_t offset, frames; | |||
if (snd_pcm_mmap_begin(driver->capture_handle, &my_areas, &offset, &frames) < 0) { | |||
jack_error ("ALSA: %s: mmap areas info error", driver->alsa_name_playback); | |||
jack_error ("ALSA: %s: mmap areas info error", driver->alsa_name_capture); | |||
return -1; | |||
} | |||
driver->capture_interleave_skip = my_areas[0].step / 8; | |||
driver->interleave_unit = snd_pcm_format_physical_width (driver->sample_format) / 8; | |||
} else { | |||
driver->interleave_unit = 0; /* NOT USED */ | |||
driver->playback_interleave_skip = snd_pcm_format_physical_width (driver->sample_format) / 8; | |||
driver->capture_interleave_skip = driver->playback_interleave_skip; | |||
driver->capture_interleave_skip = snd_pcm_format_physical_width (driver->capture_sample_format) / 8; | |||
} | |||
if (driver->playback_nchannels > driver->capture_nchannels) { | |||
@@ -576,8 +573,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc | |||
} | |||
driver->clock_sync_data = (ClockSyncStatus *) malloc (sizeof (ClockSyncStatus) * | |||
(driver->capture_nchannels > driver->playback_nchannels ? | |||
driver->capture_nchannels : driver->playback_nchannels)); | |||
driver->max_nchannels); | |||
driver->period_usecs = (jack_time_t) floor ((((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f); | |||
driver->poll_timeout = (int) floor (1.5f * driver->period_usecs); | |||
@@ -1170,6 +1166,7 @@ alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes) | |||
snd_pcm_sframes_t contiguous; | |||
snd_pcm_sframes_t offset; | |||
jack_port_t *port; | |||
int err; | |||
driver->process_count++; | |||
@@ -1224,9 +1221,10 @@ alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes) | |||
alsa_driver_silence_untouched_channels (driver, contiguous); | |||
} | |||
if (snd_pcm_mmap_commit (driver->playback_handle, offset, contiguous) < 0) { | |||
jack_error ("could not complete playback of %lu frames", contiguous); | |||
return -1; | |||
if ((err = snd_pcm_mmap_commit (driver->playback_handle, offset, contiguous)) < 0) { | |||
jack_error ("could not complete playback of %lu frames: error = %d", contiguous, err); | |||
if (err != -EPIPE && err != -ESTRPIPE) | |||
return -1; | |||
} | |||
nframes -= contiguous; | |||
@@ -0,0 +1,6 @@ | |||
Makefile | |||
Makefile.in | |||
.deps | |||
.libs | |||
*.lo | |||
*.la |
@@ -0,0 +1,12 @@ | |||
MAINTAINERCLEANFILES=Makefile.in | |||
AM_CFLAGS = $(JACK_CFLAGS) | |||
plugindir = $(ADDON_DIR) | |||
plugin_LTLIBRARIES = jack_dummy.la | |||
jack_dummy_la_LDFLAGS = -module -avoid-version | |||
jack_dummy_la_SOURCES = dummy_driver.c dummy_driver.h | |||
# jack_alsa_la_LIBADD = |
@@ -0,0 +1,323 @@ | |||
/* | |||
Copyright (C) 2003 Robert Ham <rah@bash.sh> | |||
Copyright (C) 2001 Paul Davis | |||
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., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
$Id$ | |||
*/ | |||
#include <stdio.h> | |||
#include <memory.h> | |||
#include <unistd.h> | |||
#include <stdlib.h> | |||
#include <errno.h> | |||
#include <stdarg.h> | |||
#include <getopt.h> | |||
#include <jack/types.h> | |||
#include <jack/internal.h> | |||
#include <jack/engine.h> | |||
#include <jack/time.h> | |||
#include "dummy_driver.h" | |||
#undef DEBUG_WAKEUP | |||
static int | |||
dummy_driver_audio_start (dummy_driver_t *driver) | |||
{ | |||
return 0; | |||
} | |||
static int | |||
dummy_driver_audio_stop (dummy_driver_t *driver) | |||
{ | |||
return 0; | |||
} | |||
static jack_nframes_t | |||
dummy_driver_wait (dummy_driver_t *driver, int extra_fd, int *status, float *delayed_usecs) | |||
{ | |||
usleep (driver->wait_time); | |||
driver->last_wait_ust = jack_get_microseconds (); | |||
*status = 0; | |||
*delayed_usecs = 0.0; | |||
return driver->period_size; | |||
} | |||
static int | |||
dummy_driver_null_cycle (dummy_driver_t* driver, jack_nframes_t nframes) | |||
{ | |||
return 0; | |||
} | |||
static int | |||
dummy_driver_read (dummy_driver_t *driver, jack_nframes_t nframes) | |||
{ | |||
return 0; | |||
} | |||
static int | |||
dummy_driver_write (dummy_driver_t* driver, jack_nframes_t nframes) | |||
{ | |||
return 0; | |||
} | |||
static int | |||
dummy_driver_attach (dummy_driver_t *driver, jack_engine_t *engine) | |||
{ | |||
jack_port_t * port; | |||
char buf[32]; | |||
unsigned int chn; | |||
int port_flags; | |||
driver->engine = engine; | |||
driver->engine->set_buffer_size (engine, driver->period_size); | |||
driver->engine->set_sample_rate (engine, driver->sample_rate); | |||
port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal; | |||
for (chn = 0; chn < driver->capture_channels; chn++) | |||
{ | |||
snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1); | |||
port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | |||
if (!port) | |||
{ | |||
jack_error ("DUMMY: cannot register port for %s", buf); | |||
break; | |||
} | |||
driver->capture_ports = jack_slist_append (driver->capture_ports, port); | |||
} | |||
port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal; | |||
for (chn = 0; chn < driver->playback_channels; chn++) | |||
{ | |||
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1); | |||
port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | |||
if (!port) | |||
{ | |||
jack_error ("DUMMY: cannot register port for %s", buf); | |||
break; | |||
} | |||
driver->playback_ports = jack_slist_append (driver->playback_ports, port); | |||
} | |||
jack_activate (driver->client); | |||
return 0; | |||
} | |||
static void | |||
dummy_driver_detach (dummy_driver_t *driver, jack_engine_t *engine) | |||
{ | |||
JSList * node; | |||
if (driver->engine == 0) | |||
return; | |||
for (node = driver->capture_ports; node; node = jack_slist_next (node)) | |||
jack_port_unregister (driver->client, ((jack_port_t *) node->data)); | |||
jack_slist_free (driver->capture_ports); | |||
driver->capture_ports = NULL; | |||
for (node = driver->playback_ports; node; node = jack_slist_next (node)) | |||
jack_port_unregister (driver->client, ((jack_port_t *) node->data)); | |||
jack_slist_free (driver->playback_ports); | |||
driver->playback_ports = NULL; | |||
driver->engine = NULL; | |||
} | |||
static void | |||
dummy_driver_delete (dummy_driver_t *driver) | |||
{ | |||
free (driver); | |||
} | |||
static jack_driver_t * | |||
dummy_driver_new (jack_client_t * client, | |||
char *name, | |||
unsigned int capture_ports, | |||
unsigned int playback_ports, | |||
jack_nframes_t sample_rate, | |||
jack_nframes_t period_size, | |||
unsigned long wait_time) | |||
{ | |||
dummy_driver_t * driver; | |||
printf ("creating dummy driver ... %s|%lu|%lu|%lu|%u|%u\n", | |||
name, sample_rate, period_size, wait_time, | |||
capture_ports, playback_ports); | |||
driver = (dummy_driver_t *) calloc (1, sizeof (dummy_driver_t)); | |||
jack_driver_init ((jack_driver_t *) driver); | |||
driver->attach = (JackDriverAttachFunction) dummy_driver_attach; | |||
driver->detach = (JackDriverDetachFunction) dummy_driver_detach; | |||
driver->wait = (JackDriverWaitFunction) dummy_driver_wait; | |||
driver->read = (JackDriverReadFunction) dummy_driver_read; | |||
driver->write = (JackDriverReadFunction) dummy_driver_write; | |||
driver->null_cycle = (JackDriverNullCycleFunction) dummy_driver_null_cycle; | |||
driver->start = (JackDriverStartFunction) dummy_driver_audio_start; | |||
driver->stop = (JackDriverStopFunction) dummy_driver_audio_stop; | |||
driver->period_usecs = (((float)period_size) / ((float)sample_rate)) / 1000000.0; | |||
driver->sample_rate = sample_rate; | |||
driver->period_size = period_size; | |||
driver->wait_time = wait_time; | |||
driver->capture_channels = capture_ports; | |||
driver->capture_ports = NULL; | |||
driver->playback_channels = playback_ports; | |||
driver->playback_ports = NULL; | |||
driver->client = client; | |||
driver->engine = NULL; | |||
return (jack_driver_t *) driver; | |||
} | |||
static void | |||
dummy_usage () | |||
{ | |||
fprintf (stderr, "\n" | |||
"dummy driver arguments:\n" | |||
" -h,--help \tprint this message\n" | |||
" -r,--rate <n> \tsample rate (default: 48000)\n" | |||
" -p,--period <n> \tframes per period (default: 1024)\n" | |||
" -C,--capture <n> \tnumber of capture ports (default: 2)\n" | |||
" -P,--playback <n> \tnumber of playback ports (default: 2)\n" | |||
" -w,--wait <usecs> \tnumber of usecs to wait between engine processes (default: 21333)\n" | |||
"\n"); | |||
} | |||
static void | |||
dummy_error (char *type, char *value) | |||
{ | |||
fprintf (stderr, "dummy driver: unknown %s: `%s'\n", type, value); | |||
dummy_usage(); | |||
} | |||
/* DRIVER "PLUGIN" INTERFACE */ | |||
const char driver_client_name[] = "dummy_pcm"; | |||
jack_driver_t * | |||
driver_initialize (jack_client_t *client, int argc, char **argv) | |||
{ | |||
jack_nframes_t sample_rate = 48000; | |||
jack_nframes_t period_size = 1024; | |||
unsigned int capture_ports = 2; | |||
unsigned int playback_ports = 2; | |||
int wait_time_set = 0; | |||
unsigned long wait_time; | |||
int opt; | |||
char optstring[2]; /* string made from opt char */ | |||
struct option long_options[] = | |||
{ | |||
{ "help", no_argument, NULL, 'h' }, | |||
{ "rate", required_argument, NULL, 'r' }, | |||
{ "period", required_argument, NULL, 'p' }, | |||
{ "capture", required_argument, NULL, 'C' }, | |||
{ "playback", required_argument, NULL, 'P' }, | |||
{ "wait", required_argument, NULL, 'w' }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
/* | |||
* Setting optind back to zero is a hack to reinitialize a new | |||
* getopts() loop. See declaration in <getopt.h>. | |||
*/ | |||
optind = 0; | |||
opterr = 0; | |||
while ((opt = getopt_long(argc, argv, "C::P::p:r:w:h", | |||
long_options, NULL)) | |||
!= EOF) { | |||
switch (opt) { | |||
case 'C': | |||
capture_ports = atoi (optarg); | |||
break; | |||
case 'P': | |||
playback_ports = atoi (optarg); | |||
break; | |||
case 'p': | |||
period_size = atoi(optarg); | |||
break; | |||
case 'r': | |||
sample_rate = atoi(optarg); | |||
break; | |||
case 'w': | |||
wait_time = strtoul(optarg, NULL, 10); | |||
wait_time_set = 1; | |||
break; | |||
case 'h': | |||
dummy_usage(); | |||
return NULL; | |||
/* the rest is error handling: */ | |||
case 1: /* not an option */ | |||
dummy_error("parameter", optarg); | |||
return NULL; | |||
default: /* unrecognized option */ | |||
optstring[0] = (char) optopt; | |||
optstring[1] = '\0'; | |||
dummy_error("option", optstring); | |||
return NULL; | |||
} | |||
} | |||
if (!wait_time_set) | |||
wait_time = (((float)period_size) / ((float)sample_rate)) * 1000000.0; | |||
return dummy_driver_new (client, "dummy_pcm", capture_ports, playback_ports, | |||
sample_rate, period_size, wait_time); | |||
} | |||
void | |||
driver_finish (jack_driver_t *driver) | |||
{ | |||
dummy_driver_delete ((dummy_driver_t *) driver); | |||
} |
@@ -0,0 +1,52 @@ | |||
/* | |||
Copyright (C) 2003 Robert Ham <rah@bash.sh> | |||
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., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#ifndef __JACK_DUMMY_DRIVER_H__ | |||
#define __JACK_DUMMY_DRIVER_H__ | |||
#include <unistd.h> | |||
#include <jack/types.h> | |||
#include <jack/jslist.h> | |||
#include <jack/driver.h> | |||
#include <jack/jack.h> | |||
typedef struct _dummy_driver dummy_driver_t; | |||
struct _dummy_driver | |||
{ | |||
JACK_DRIVER_DECL | |||
jack_nframes_t sample_rate; | |||
jack_nframes_t period_size; | |||
unsigned long wait_time; | |||
unsigned int capture_channels; | |||
unsigned int playback_channels; | |||
JSList * capture_ports; | |||
JSList * playback_ports; | |||
struct _jack_engine * engine; | |||
jack_client_t * client; | |||
}; | |||
#endif /* __JACK_DUMMY_DRIVER_H__ */ |
@@ -62,7 +62,8 @@ typedef struct { | |||
channel_t user_nchannels; | |||
channel_t playback_nchannels; | |||
channel_t capture_nchannels; | |||
unsigned long sample_bytes; | |||
unsigned long playback_sample_bytes; | |||
unsigned long capture_sample_bytes; | |||
jack_nframes_t frame_rate; | |||
jack_nframes_t frames_per_cycle; | |||
@@ -76,7 +77,8 @@ typedef struct { | |||
snd_pcm_uframes_t buffer_frames; | |||
unsigned long channels_not_done; | |||
unsigned long channel_done_bits; | |||
snd_pcm_format_t sample_format; | |||
snd_pcm_format_t playback_sample_format; | |||
snd_pcm_format_t capture_sample_format; | |||
float max_sample_val; | |||
unsigned long user_nperiods; | |||
unsigned long nfragments; | |||
@@ -102,7 +104,8 @@ typedef struct { | |||
char hw_metering : 1; | |||
char all_monitor_in : 1; | |||
char capture_and_playback_not_synced : 1; | |||
char interleaved : 1; | |||
char playback_interleaved : 1; | |||
char capture_interleaved : 1; | |||
char with_monitor_ports : 1; | |||
ReadCopyFunction read_via_copy; | |||
@@ -130,27 +133,27 @@ static __inline__ void alsa_driver_mark_channel_done (alsa_driver_t *driver, cha | |||
} | |||
static __inline__ void alsa_driver_silence_on_channel (alsa_driver_t *driver, channel_t chn, jack_nframes_t nframes) { | |||
if (driver->interleaved) { | |||
if (driver->playback_interleaved) { | |||
memset_interleave | |||
(driver->playback_addr[chn], | |||
0, nframes * driver->sample_bytes, | |||
0, nframes * driver->playback_sample_bytes, | |||
driver->interleave_unit, | |||
driver->playback_interleave_skip); | |||
} else { | |||
memset (driver->playback_addr[chn], 0, nframes * driver->sample_bytes); | |||
memset (driver->playback_addr[chn], 0, nframes * driver->playback_sample_bytes); | |||
} | |||
alsa_driver_mark_channel_done (driver,chn); | |||
} | |||
static __inline__ void alsa_driver_silence_on_channel_no_mark (alsa_driver_t *driver, channel_t chn, jack_nframes_t nframes) { | |||
if (driver->interleaved) { | |||
if (driver->playback_interleaved) { | |||
memset_interleave | |||
(driver->playback_addr[chn], | |||
0, nframes * driver->sample_bytes, | |||
0, nframes * driver->playback_sample_bytes, | |||
driver->interleave_unit, | |||
driver->playback_interleave_skip); | |||
} else { | |||
memset (driver->playback_addr[chn], 0, nframes * driver->sample_bytes); | |||
memset (driver->playback_addr[chn], 0, nframes * driver->playback_sample_bytes); | |||
} | |||
} | |||
@@ -184,7 +187,7 @@ static __inline__ void alsa_driver_copy_channel (alsa_driver_t *driver, | |||
driver->channel_copy (driver->playback_addr[output_channel], | |||
driver->capture_addr[input_channel], | |||
nsamples * driver->sample_bytes, | |||
nsamples * driver->playback_sample_bytes, | |||
driver->playback_interleave_skip, | |||
driver->capture_interleave_skip); | |||
alsa_driver_mark_channel_done (driver, output_channel); | |||
@@ -336,7 +336,7 @@ typedef struct _jack_client_internal { | |||
struct _jack_client_internal *next_client; /* not a linked list! */ | |||
dlhandle handle; | |||
int (*initialize)(jack_client_t*, const char*); /* for internal clients only */ | |||
void (*finish)(void); /* for internal clients only */ | |||
void (*finish)(void *); /* for internal clients only */ | |||
int error; | |||
#if defined(__APPLE__) && defined(__POWERPC__) | |||
@@ -779,7 +779,7 @@ jack_client_unload (jack_client_internal_t *client) | |||
{ | |||
if (client->handle) { | |||
if (client->finish) { | |||
client->finish (); | |||
client->finish (client->control->process_arg); | |||
} | |||
dlclose (client->handle); | |||
} | |||
@@ -22,6 +22,7 @@ | |||
#include <config.h> | |||
#include <errno.h> | |||
#include <assert.h> | |||
#include <string.h> | |||
#include <stdio.h> | |||
#include <jack/internal.h> | |||
#include <jack/engine.h> | |||