Browse Source

[0.79.1] timebase master fixes

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@464 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
joq 22 years ago
parent
commit
056e6648e0
11 changed files with 146 additions and 48 deletions
  1. +1
    -1
      configure.in
  2. +4
    -1
      example-clients/Makefile.am
  3. +62
    -0
      example-clients/intime.c
  4. +10
    -7
      example-clients/showtime.c
  5. +8
    -2
      example-clients/transport.c
  6. +4
    -0
      jack/internal.h
  7. +8
    -2
      jack/transport.h
  8. +19
    -23
      jackd/engine.c
  9. +23
    -9
      jackd/transengine.c
  10. +0
    -2
      libjack/local.h
  11. +7
    -1
      libjack/transclient.c

+ 1
- 1
configure.in View File

@@ -14,7 +14,7 @@ dnl changes are made
dnl ---
JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=79
JACK_MICRO_VERSION=0
JACK_MICRO_VERSION=1

dnl ---
dnl HOWTO: updating the jack protocal version


+ 4
- 1
example-clients/Makefile.am View File

@@ -108,9 +108,12 @@ jack_unload_LDADD = ../libjack/libjack.la

ip_clientdir = $(ADDON_DIR)

ip_client_LTLIBRARIES = inprocess.la
ip_client_LTLIBRARIES = inprocess.la intime.la

inprocess_la_LDFLAGS = -module -avoid-version
inprocess_la_SOURCES = inprocess.c

intime_la_LDFLAGS = -module -avoid-version
intime_la_SOURCES = intime.c

dist-hook: dist-check-sndfile

+ 62
- 0
example-clients/intime.c View File

@@ -0,0 +1,62 @@
/*
* intime.c -- JACK internal timebase master example client.
*
* This demonstrates how to write an internal timebase master client.
* It fills in extended timecode fields using the trivial assumption
* that we are running at nominal speed, hence there is no drift.
*
* To run, first start `jackd', then `jack_load intime intime'.
*
* Copyright (C) 2003 Jack O'Quin.
*
* 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.
*/

#include <stdio.h>
#include <jack/jack.h>


/* timebase callback
*
* Runs in the process thread. Realtime, must not wait.
*/
void timebase(jack_transport_state_t state, jack_nframes_t nframes,
jack_position_t *pos, int new_pos, void *arg)
{
pos->valid = JackPositionTimecode;
pos->frame_time = pos->frame / (double) pos->frame_rate;
pos->period_duration = nframes / (double) pos->frame_rate;
}

/* after internal client loaded */
int
jack_initialize (jack_client_t *client, const char *data)
{
if (jack_set_timebase_callback(client, 0, timebase, NULL) != 0) {
fprintf (stderr, "Unable to take over timebase.\n");
return 1;
}

fprintf (stderr, "Internal timebase master defined.\n");
jack_activate (client);
return 0;
}

/* before unloading */
void
jack_finish (void)
{
fprintf (stderr, "Internal timebase client exiting.\n");
}

+ 10
- 7
example-clients/showtime.c View File

@@ -22,23 +22,26 @@ showtime ()

switch (transport_state) {
case JackTransportStopped:
printf ("state: Stopped\t");
printf ("state: Stopped");
break;
case JackTransportRolling:
printf ("state: Rolling\t");
printf ("state: Rolling");
break;
case JackTransportStarting:
printf ("state: Starting\t");
printf ("state: Starting");
break;
default:
printf ("state: [unknown]\t");
printf ("state: [unknown]");
}

if (current.valid & JackPositionBBT)
printf ("BBT: %3d|%d|%04d\n",
printf ("\tBBT: %3d|%d|%04d",
current.bar, current.beat, current.tick);
else
printf ("BBT: [-]\n");

if (current.valid & JackPositionTimecode)
printf ("\tTC: %.6f, %.6f",
current.frame_time, current.period_duration);
printf ("\n");
}

void


+ 8
- 2
example-clients/transport.c View File

@@ -56,7 +56,7 @@ void timebase(jack_transport_state_t state, jack_nframes_t nframes,

if (new_pos || time_reset) {

pos->valid |= JackPositionBBT;
pos->valid = JackPositionBBT;
pos->beats_per_bar = time_beats_per_bar;
pos->beat_type = time_beat_type;
pos->ticks_per_beat = time_ticks_per_beat;
@@ -69,7 +69,7 @@ void timebase(jack_transport_state_t state, jack_nframes_t nframes,
* or time signature changes at specific locations in the
* transport timeline. */

min = (double) pos->frame / ((double) pos->frame_rate * 60.0);
min = pos->frame / ((double) pos->frame_rate * 60.0);
abs_tick = min * pos->beats_per_minute * pos->ticks_per_beat;
abs_beat = abs_tick / pos->ticks_per_beat;

@@ -80,6 +80,12 @@ void timebase(jack_transport_state_t state, jack_nframes_t nframes,
pos->ticks_per_beat;
pos->bar++; /* adjust start to bar 1 */

#if 0
/* some debug code... */
fprintf(stderr, "\nnew position: %lu\tBBT: %3d|%d|%04d\n",
pos->frame, pos->bar, pos->beat, pos->tick);
#endif

} else {

/* Compute BBT info based on previous period. */


+ 4
- 0
jack/internal.h View File

@@ -374,5 +374,9 @@ extern void jack_client_invalidate_port_buffers (jack_client_t *client);
extern void jack_transport_copy_position (jack_position_t *from,
jack_position_t *to);

extern void jack_call_sync_client (jack_client_t *client);

extern void jack_call_timebase_master (jack_client_t *client);

#endif /* __jack_internal_h__ */


+ 8
- 2
jack/transport.h View File

@@ -49,10 +49,12 @@ typedef unsigned long long jack_unique_t; /**< Unique ID (opaque) */
typedef enum {

JackPositionBBT = 0x10, /**< Bar, Beat, Tick */
JackPositionTimecode = 0x20, /**< External timecode */

} jack_position_bits_t;

#define JACK_POSITION_MASK (JackPositionBBT) /**< all valid position bits */
/** all valid position bits */
#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode)
#define EXTENDED_TIME_INFO

/**
@@ -79,10 +81,14 @@ typedef struct {
double ticks_per_beat;
double beats_per_minute;

/* JackPositionTimecode fields: */
double frame_time; /**< current time in seconds */
double period_duration; /**< period duration (sec) */

/* For binary compatibility, new fields should be allocated from
* this padding area with new valid bits controlling access, so
* the existing structure size and offsets are preserved. */
int padding[14];
int padding[10];

/* When (unique_1 == unique_2) the contents are consistent. */
jack_unique_t unique_2; /**< unique ID */


+ 19
- 23
jackd/engine.c View File

@@ -390,34 +390,30 @@ jack_process_internal(jack_engine_t *engine, JSList *node, jack_nframes_t nframe
/* internal client ("plugin") */

if (ctl->process) {

DEBUG ("calling process() on an internal client");

ctl->state = Running;

/* XXX how to time out an internal client? */

engine->current_client = client;
DEBUG ("invoking an internal client's callbacks");
ctl->state = Running;
engine->current_client = client;

if (ctl->process (nframes, ctl->process_arg) == 0) {
ctl->state = Finished;
} else {
jack_error ("internal client %s failed", client->control->name);
engine->process_errors++;
return NULL; /* will stop the loop */
}
/* XXX how to time out an internal client? */

//JOQ: can an internal client be slow sync?
//JOQ: can an internal client have a timebase master?
if (ctl->sync_cb)
jack_call_sync_client (ctl->private_client);

} else {
DEBUG ("internal client has no process() function");
if (ctl->process)
if (ctl->process (nframes, ctl->process_arg)) {
jack_error ("internal client %s failed", ctl->name);
engine->process_errors++;
}

ctl->state = Finished;
}
if (ctl->timebase_cb)
jack_call_timebase_master (ctl->private_client);
ctl->state = Finished;

return jack_slist_next (node);
if (engine->process_errors)
return NULL; /* will stop the loop */
else
return jack_slist_next (node);
}

#if defined(__APPLE__) && defined(__POWERPC__)


+ 23
- 9
jackd/transengine.c View File

@@ -176,6 +176,8 @@ jack_timebase_reset (jack_engine_t *engine, jack_client_id_t client_id)
client->control->is_timebase = 0;
engine->timebase_client = NULL;
ectl->pending_time.valid = 0;
VERBOSE (engine, "%s resigned as timebase master\n",
client->control->name);
ret = 0;
} else
ret = EINVAL;
@@ -197,22 +199,34 @@ jack_timebase_set (jack_engine_t *engine,

client = jack_client_internal_by_id (engine, client_id);

if (client == NULL) {
// JOQ: use PRIuLEAST32 here...
VERBOSE (engine, " %lu no longer exists!\n", client_id);
jack_unlock_graph (engine);
return EINVAL;
}

if (conditional && engine->timebase_client) {

/* see if timebase master is someone else */
if (client && (client != engine->timebase_client))
if (client != engine->timebase_client) {
VERBOSE (engine, "conditional timebase for %s failed\n"
" %s is already the master\n",
client->control->name,
engine->timebase_client->control->name);
ret = EBUSY;
} else
VERBOSE (engine, " %s was already timebase master:\n",
client->control->name);

} else {

if (client) {
if (engine->timebase_client)
engine->timebase_client->
control->is_timebase = 0;
engine->timebase_client = client;
client->control->is_timebase = 1;
} else
ret = EINVAL;
if (engine->timebase_client)
engine->timebase_client->control->is_timebase = 0;
engine->timebase_client = client;
client->control->is_timebase = 1;
VERBOSE (engine, "new timebase master: %s\n",
client->control->name);
}

jack_unlock_graph (engine);


+ 0
- 2
libjack/local.h View File

@@ -32,8 +32,6 @@ struct _jack_client {

extern int jack_client_deliver_request (const jack_client_t *client, jack_request_t *req);
extern jack_port_t *jack_port_new (const jack_client_t *client, jack_port_id_t port_id, jack_control_t *control);
extern void jack_call_sync_client (jack_client_t *client);
extern void jack_call_timebase_master (jack_client_t *client);


extern void *jack_zero_filled_buffer;


+ 7
- 1
libjack/transclient.c View File

@@ -122,8 +122,14 @@ jack_transport_request_new_pos (jack_client_t *client, jack_position_t *pos)
{
jack_control_t *ectl = client->engine;

/* carefully copy requested postion into shared memory */
/* distinguish this request from all others */
pos->unique_1 = pos->unique_2 = jack_generate_unique_id(ectl);

/* clients may not set these fields */
pos->usecs = ectl->current_time.usecs;
pos->frame_rate = ectl->current_time.frame_rate;

/* carefully copy requested postion into shared memory */
jack_transport_copy_position (pos, &ectl->request_time);
return 0;


Loading…
Cancel
Save