Commit d1004b0e authored by Mark Hills's avatar Mark Hills
Browse files

Merge branch 'deck'

* deck:
  A dummy deck for testing
  Refactor deck creation
  Make deck responsible for importer
  Make deck responsible for the protect flag
  Make deck responsible for timecode init
  Rename local variables
parents f94af1ab 4b7509f1
......@@ -50,6 +50,7 @@ OBJS = controller.o \
cues.o \
deck.o \
device.o \
dummy.o \
excrate.o \
external.o \
index.o \
......
......@@ -41,82 +41,87 @@ static const struct record no_record = {
* A deck is a logical grouping of the various components which
* reflects the user's view on a deck in the system.
*
* Pre: deck->device, deck->timecoder, deck->importer are valid
* Pre: deck->device is valid
*/
int deck_init(struct deck *deck, struct rt *rt)
int deck_init(struct deck *d, struct rt *rt,
struct timecode_def *timecode, const char *importer,
double speed, bool phono, bool protect)
{
unsigned int rate;
assert(deck->importer != NULL);
if (rt_add_device(rt, &deck->device) == -1)
if (rt_add_device(rt, &d->device) == -1)
return -1;
deck->ncontrol = 0;
deck->record = &no_record;
deck->punch = NO_PUNCH;
rate = device_sample_rate(&deck->device);
player_init(&deck->player, rate, track_acquire_empty(), &deck->timecoder);
cues_reset(&deck->cues);
d->ncontrol = 0;
d->record = &no_record;
d->punch = NO_PUNCH;
d->protect = protect;
assert(importer != NULL);
d->importer = importer;
rate = device_sample_rate(&d->device);
assert(timecode != NULL);
timecoder_init(&d->timecoder, timecode, speed, rate, phono);
player_init(&d->player, rate, track_acquire_empty(), &d->timecoder);
cues_reset(&d->cues);
/* The timecoder and player are driven by requests from
* the audio device */
device_connect_timecoder(&deck->device, &deck->timecoder);
device_connect_player(&deck->device, &deck->player);
device_connect_timecoder(&d->device, &d->timecoder);
device_connect_player(&d->device, &d->player);
return 0;
}
void deck_clear(struct deck *deck)
void deck_clear(struct deck *d)
{
/* FIXME: remove from rig and rt */
player_clear(&deck->player);
timecoder_clear(&deck->timecoder);
device_clear(&deck->device);
player_clear(&d->player);
timecoder_clear(&d->timecoder);
device_clear(&d->device);
}
bool deck_is_locked(const struct deck *deck)
bool deck_is_locked(const struct deck *d)
{
return (deck->protect && player_is_active(&deck->player));
return (d->protect && player_is_active(&d->player));
}
/*
* Load a record from the library to a deck
*/
void deck_load(struct deck *deck, struct record *record)
void deck_load(struct deck *d, struct record *record)
{
struct track *t;
if (deck_is_locked(deck)) {
if (deck_is_locked(d)) {
status_printf(STATUS_WARN, "Stop deck to load a different track");
return;
}
t = track_acquire_by_import(deck->importer, record->pathname);
t = track_acquire_by_import(d->importer, record->pathname);
if (t == NULL)
return;
deck->record = record;
player_set_track(&deck->player, t); /* passes reference */
d->record = record;
player_set_track(&d->player, t); /* passes reference */
}
void deck_recue(struct deck *deck)
void deck_recue(struct deck *d)
{
if (deck_is_locked(deck)) {
if (deck_is_locked(d)) {
status_printf(STATUS_WARN, "Stop deck to recue");
return;
}
player_recue(&deck->player);
player_recue(&d->player);
}
void deck_clone(struct deck *deck, const struct deck *from)
void deck_clone(struct deck *d, const struct deck *from)
{
deck->record = from->record;
player_clone(&deck->player, &from->player);
d->record = from->record;
player_clone(&d->player, &from->player);
}
/*
......
......@@ -51,7 +51,9 @@ struct deck {
struct controller *control[4];
};
int deck_init(struct deck *deck, struct rt *rt);
int deck_init(struct deck *deck, struct rt *rt,
struct timecode_def *timecode, const char *importer,
double speed, bool phono, bool protect);
void deck_clear(struct deck *deck);
bool deck_is_locked(const struct deck *deck);
......
/*
* Copyright (C) 2014 Mark Hills <mark@xwax.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* 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 version 2 for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include "dummy.h"
static unsigned int sample_rate(struct device *d)
{
return 48000;
}
static struct device_ops dummy_ops = {
.sample_rate = sample_rate,
};
void dummy_init(struct device *d)
{
device_init(d, &dummy_ops);
}
/*
* Copyright (C) 2014 Mark Hills <mark@xwax.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* 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 version 2 for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#ifndef DUMMY_H
#define DUMMY_H
#include "device.h"
void dummy_init(struct device *d);
#endif
......@@ -79,6 +79,11 @@ Use the given importer executable for subsequent decks.
.B \-s \fIpath\fR
Use the given scanner executable to scan subsequent music libraries.
.TP
.B \-\-dummy
Create a deck which is not connected to any audio device, used
for testing.
.TP
.B \-k
Lock into RAM any memory required for real-time use.
......
......@@ -30,6 +30,7 @@
#include "controller.h"
#include "device.h"
#include "dicer.h"
#include "dummy.h"
#include "interface.h"
#include "jack.h"
#include "library.h"
......@@ -61,6 +62,16 @@ char *banner = "xwax " VERSION \
size_t ndeck;
struct deck deck[3];
static size_t nctl;
static struct controller ctl[2];
static struct rt rt;
static double speed;
static bool protect, phono;
static const char *importer;
static struct timecode_def *timecode;
static void usage(FILE *fd)
{
fprintf(fd, "Usage: xwax [<options>]\n\n");
......@@ -85,7 +96,8 @@ static void usage(FILE *fd)
" -u Allow all operations when playing\n"
" --line Line level signal (default)\n"
" --phono Tolerate cartridge level signal ('software pre-amp')\n"
" -i <program> Importer (default '%s')\n\n",
" -i <program> Importer (default '%s')\n"
" --dummy Build a dummy deck with no audio device\n\n",
DEFAULT_IMPORTER);
#ifdef WITH_OSS
......@@ -125,18 +137,55 @@ static void usage(FILE *fd)
"See the xwax(1) man page for full information and examples.\n");
}
static struct device* start_deck(const char *desc)
{
fprintf(stderr, "Initialising deck %zd (%s)...\n", ndeck, desc);
if (ndeck == ARRAY_SIZE(deck)) {
fprintf(stderr, "Too many decks.\n");
return NULL;
}
return &deck[ndeck].device;
}
static int commit_deck(void)
{
int r;
struct deck *d;
size_t n;
/* Fallback to a default timecode. Don't initialise this at the
* front of the program to avoid buildling unnecessary LUTs */
if (timecode == NULL) {
timecode = timecoder_find_definition(DEFAULT_TIMECODE);
assert(timecode != NULL);
}
d = &deck[ndeck];
r = deck_init(d, &rt, timecode, importer, speed, phono, protect);
if (r == -1)
return -1;
/* Connect this deck to available controllers */
for (n = 0; n < nctl; n++)
controller_add_deck(&ctl[n], d);
ndeck++;
return 0;
}
int main(int argc, char *argv[])
{
int rc = -1, n, priority;
const char *importer, *scanner, *geo;
const char *scanner, *geo;
char *endptr;
size_t nctl;
double speed;
struct timecode_def *timecode;
bool protect, use_mlock, phono;
bool use_mlock;
struct controller ctl[2];
struct rt rt;
struct library library;
#if defined WITH_OSS || WITH_ALSA
......@@ -288,10 +337,7 @@ int main(int argc, char *argv[])
!strcmp(argv[0], "-j"))
{
int r;
unsigned int sample_rate;
struct deck *ld;
struct device *device;
struct timecoder *timecoder;
/* Create a deck */
......@@ -301,18 +347,9 @@ int main(int argc, char *argv[])
return -1;
}
if (ndeck == ARRAY_SIZE(deck)) {
fprintf(stderr, "Too many decks; aborting.\n");
device = start_deck(argv[1]);
if (device == NULL)
return -1;
}
fprintf(stderr, "Initialising deck %zd (%s)...\n", ndeck, argv[1]);
ld = &deck[ndeck];
device = &ld->device;
timecoder = &ld->timecoder;
ld->importer = importer;
ld->protect = protect;
/* Work out which device type we are using, and initialise
* an appropriate device. */
......@@ -343,32 +380,24 @@ int main(int argc, char *argv[])
if (r == -1)
return -1;
sample_rate = device_sample_rate(device);
/* Default timecode decoder where none is specified */
commit_deck();
if (timecode == NULL) {
timecode = timecoder_find_definition(DEFAULT_TIMECODE);
assert(timecode != NULL);
}
argv += 2;
argc -= 2;
timecoder_init(timecoder, timecode, speed, sample_rate, phono);
} else if (!strcmp(argv[0], "--dummy")) {
/* Connect up the elements to make an operational deck */
struct device *v;
r = deck_init(ld, &rt);
if (r == -1)
v = start_deck("dummy");
if (v == NULL)
return -1;
/* Connect this deck to available controllers */
for (n = 0; n < nctl; n++)
controller_add_deck(&ctl[n], &deck[ndeck]);
ndeck++;
dummy_init(v);
commit_deck();
argv += 2;
argc -= 2;
argv++;
argc--;
} else if (!strcmp(argv[0], "-t")) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment