git-svn-id: svn+ssh://jackaudio.org/trunk/jack@355 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
@@ -13,7 +13,7 @@ dnl micro version = incremented when implementation-only | |||||
dnl changes are made | dnl changes are made | ||||
dnl --- | dnl --- | ||||
JACK_MAJOR_VERSION=0 | JACK_MAJOR_VERSION=0 | ||||
JACK_MINOR_VERSION=64 | |||||
JACK_MINOR_VERSION=65 | |||||
JACK_MICRO_VERSION=0 | JACK_MICRO_VERSION=0 | ||||
dnl --- | dnl --- | ||||
@@ -41,7 +41,7 @@ dnl slacker than this, and closer to those for the JACK version | |||||
dnl number. | dnl number. | ||||
dnl --- | dnl --- | ||||
JACK_API_CURRENT=0 | JACK_API_CURRENT=0 | ||||
JACK_API_REVISION=12 | |||||
JACK_API_REVISION=13 | |||||
JACK_API_AGE=0 | JACK_API_AGE=0 | ||||
AC_SUBST(JACK_MAJOR_VERSION) | AC_SUBST(JACK_MAJOR_VERSION) | ||||
@@ -74,7 +74,7 @@ set_control_id (snd_ctl_elem_id_t *ctl, const char *name) | |||||
{ | { | ||||
snd_ctl_elem_id_set_name (ctl, name); | snd_ctl_elem_id_set_name (ctl, name); | ||||
snd_ctl_elem_id_set_numid (ctl, 0); | snd_ctl_elem_id_set_numid (ctl, 0); | ||||
snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_PCM); | |||||
snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_HWDEP); | |||||
snd_ctl_elem_id_set_device (ctl, 0); | snd_ctl_elem_id_set_device (ctl, 0); | ||||
snd_ctl_elem_id_set_subdevice (ctl, 0); | snd_ctl_elem_id_set_subdevice (ctl, 0); | ||||
snd_ctl_elem_id_set_index (ctl, 0); | snd_ctl_elem_id_set_index (ctl, 0); | ||||
@@ -86,7 +86,8 @@ set_control_id (snd_ctl_elem_id_t *ctl, const char *name) | |||||
/* input_channel to output_channel (see hdsp_physical_input_index */ | /* input_channel to output_channel (see hdsp_physical_input_index */ | ||||
/* etc. above. */ | /* etc. above. */ | ||||
/* gain is an int from 0 to 65535, with 0 being -inf gain, and */ | /* gain is an int from 0 to 65535, with 0 being -inf gain, and */ | ||||
/* 65535 being about 2dB. */ | |||||
/* 65535 being about +2dB. */ | |||||
static int hdsp_set_mixer_gain(jack_hardware_t *hw, int input_channel, | static int hdsp_set_mixer_gain(jack_hardware_t *hw, int input_channel, | ||||
int output_channel, int gain) | int output_channel, int gain) | ||||
{ | { | ||||
@@ -133,11 +134,14 @@ static int hdsp_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) | |||||
/* Monitoring requested for this channel? */ | /* Monitoring requested for this channel? */ | ||||
if(mask & (1<<i)) { | if(mask & (1<<i)) { | ||||
/* Yes. Connect physical input to output */ | /* Yes. Connect physical input to output */ | ||||
if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i], | if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i], | ||||
hdsp_physical_output_index[i], | hdsp_physical_output_index[i], | ||||
HDSP_UNITY_GAIN) != 0) { | HDSP_UNITY_GAIN) != 0) { | ||||
return -1; | return -1; | ||||
} | } | ||||
#ifdef CANNOT_HEAR_SOFTWARE_STREAM_WHEN_MONITORING | |||||
/* ...and disconnect the corresponding software */ | /* ...and disconnect the corresponding software */ | ||||
/* channel */ | /* channel */ | ||||
if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i], | if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i], | ||||
@@ -145,6 +149,8 @@ static int hdsp_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) | |||||
HDSP_MINUS_INFINITY_GAIN) != 0) { | HDSP_MINUS_INFINITY_GAIN) != 0) { | ||||
return -1; | return -1; | ||||
} | } | ||||
#endif | |||||
} else { | } else { | ||||
/* No. Disconnect physical input from output */ | /* No. Disconnect physical input from output */ | ||||
if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i], | if(hdsp_set_mixer_gain (hw, hdsp_physical_input_index[i], | ||||
@@ -152,6 +158,8 @@ static int hdsp_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) | |||||
HDSP_MINUS_INFINITY_GAIN) != 0) { | HDSP_MINUS_INFINITY_GAIN) != 0) { | ||||
return -1; | return -1; | ||||
} | } | ||||
#ifdef CANNOT_HEAR_SOFTWARE_STREAM_WHEN_MONITORING | |||||
/* ...and connect the corresponding software */ | /* ...and connect the corresponding software */ | ||||
/* channel */ | /* channel */ | ||||
if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i], | if(hdsp_set_mixer_gain (hw, hdsp_audio_stream_index[i], | ||||
@@ -159,6 +167,7 @@ static int hdsp_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) | |||||
HDSP_UNITY_GAIN) != 0) { | HDSP_UNITY_GAIN) != 0) { | ||||
return -1; | return -1; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
} | } | ||||
/* Cache the monitor mask */ | /* Cache the monitor mask */ | ||||
@@ -89,15 +89,15 @@ process (jack_nframes_t nframes, void *arg) | |||||
jack_transport_info_t ti; | jack_transport_info_t ti; | ||||
if (transport_aware) { | if (transport_aware) { | ||||
ti.valid = JackTransportPosition | JackTransportState; | |||||
int mask = JackTransportPosition | JackTransportState; | |||||
jack_get_transport_info (client, &ti); | jack_get_transport_info (client, &ti); | ||||
// not rolling, bail out | |||||
if (ti.state == JackTransportStopped) { | |||||
if (((ti.valid & mask) != mask) || ti.transport_state == JackTransportStopped) { | |||||
// no valid information, or not rolling, bail out | |||||
process_silence (nframes); | process_silence (nframes); | ||||
return 0; | return 0; | ||||
} | } | ||||
offset = ti.position % wave_length; | |||||
offset = ti.frame % wave_length; | |||||
} | } | ||||
process_audio (nframes); | process_audio (nframes); | ||||
@@ -14,7 +14,12 @@ void | |||||
showtime () | showtime () | ||||
{ | { | ||||
jack_transport_info_t current = now; | jack_transport_info_t current = now; | ||||
printf ("frame: %lu state: %d loop: %lu-%lu\n", current.position, current.state, current.loop_start, current.loop_end); | |||||
printf ("frame: %lu state: %d loop: %lu-%lu " | |||||
"BBT: %d|%d|%d\n", | |||||
current.frame, current.transport_state, current.loop_start, current.loop_end, | |||||
current.bar, | |||||
current.beat, | |||||
current.tick); | |||||
} | } | ||||
int | int | ||||
@@ -66,32 +66,6 @@ typedef struct { | |||||
size_t size; | size_t size; | ||||
} jack_port_segment_info_t; | } jack_port_segment_info_t; | ||||
typedef struct _time_info | |||||
{ | |||||
jack_nframes_t frame; | |||||
jack_nframes_t frame_rate; | |||||
jack_time_t usecs; | |||||
jack_transport_state_t transport_state; | |||||
jack_nframes_t loop_start; | |||||
jack_nframes_t loop_end; | |||||
#if 0 | |||||
double ppqPos; // 1 ppq | |||||
double tempo; // in bpm | |||||
double barStartPos; // last bar start, in 1 ppq | |||||
double cycleStartPos; // 1 ppq | |||||
double cycleEndPos; // 1 ppq | |||||
float timeSigNumerator; // time signature | |||||
float timeSigDenominator; | |||||
long smpteOffset; | |||||
long smpteFrameRate; // 0:24, 1:25, 2:29.97, 3:30, 4:29.97 df, 5:30 df | |||||
long samplesToNextClock; // midi clock resolution (24 ppq), can be negative | |||||
long flags; // see below | |||||
#endif | |||||
} jack_time_info_t; | |||||
typedef struct { | typedef struct { | ||||
volatile unsigned long long guard1; | volatile unsigned long long guard1; | ||||
volatile jack_nframes_t frames; | volatile jack_nframes_t frames; | ||||
@@ -101,8 +75,8 @@ typedef struct { | |||||
typedef struct { | typedef struct { | ||||
jack_time_info_t current_time; | |||||
jack_time_info_t pending_time; | |||||
jack_transport_info_t current_time; | |||||
jack_transport_info_t pending_time; | |||||
jack_frame_timer_t frame_timer; | jack_frame_timer_t frame_timer; | ||||
int internal; | int internal; | ||||
jack_nframes_t frames_at_cycle_start; | jack_nframes_t frames_at_cycle_start; | ||||
@@ -48,21 +48,43 @@ typedef enum { | |||||
JackTransportState = 0x1, | JackTransportState = 0x1, | ||||
JackTransportPosition = 0x2, | JackTransportPosition = 0x2, | ||||
JackTransportLoop = 0x4 | |||||
JackTransportLoop = 0x4, | |||||
JackTransportSMPTE = 0x8, | |||||
JackTransportBBT = 0x10, | |||||
} jack_transport_bits_t; | } jack_transport_bits_t; | ||||
#define EXTENDED_TIME_INFO \ | |||||
/** | /** | ||||
* Struct for transport status information. | * Struct for transport status information. | ||||
*/ | */ | ||||
typedef struct { | typedef struct { | ||||
/* these two cannot be set from clients: the server sets them */ | |||||
jack_transport_bits_t valid; | |||||
jack_transport_state_t state; | |||||
jack_nframes_t position; | |||||
jack_nframes_t frame_rate; // current frame rate (per second) | |||||
jack_time_t usecs; // monotonic, free-rolling | |||||
jack_transport_bits_t valid; // which fields are legal to read | |||||
jack_transport_state_t transport_state; | |||||
jack_nframes_t frame; | |||||
jack_nframes_t loop_start; | jack_nframes_t loop_start; | ||||
jack_nframes_t loop_end; | jack_nframes_t loop_end; | ||||
long smpte_offset; // SMPTE offset (SMPTE frame when frame = 0) | |||||
float smpte_frame_rate; // 29.97, 30, 24 etc. | |||||
int bar; // current bar | |||||
int beat; // current beat-within-bar | |||||
int tick; // current tick-within-beat | |||||
double bar_start_tick; // | |||||
float beats_per_bar; | |||||
float beat_type; | |||||
double ticks_per_beat; | |||||
double beats_per_minute; | |||||
} jack_transport_info_t; | } jack_transport_info_t; | ||||
/** | /** | ||||
@@ -70,27 +92,25 @@ typedef struct { | |||||
* cycle. | * cycle. | ||||
* | * | ||||
* The 'valid' field of the tinfo struct should contain | * The 'valid' field of the tinfo struct should contain | ||||
* a bitmask of all transport info fields that should | |||||
* be set with this call. | |||||
* a bitmask of all transport info fields that are set | |||||
* in tinfo. | |||||
* | * | ||||
* @pre Caller must be the current timebase master. | * @pre Caller must be the current timebase master. | ||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | |||||
*/ | */ | ||||
int jack_set_transport_info (jack_client_t *client, | |||||
jack_transport_info_t *tinfo); | |||||
void jack_set_transport_info (jack_client_t *client, | |||||
jack_transport_info_t *tinfo); | |||||
/** | /** | ||||
* Gets the current transport state. | * Gets the current transport state. | ||||
* | * | ||||
* The 'valid' field of the tinfo struct should contain | |||||
* a bitmask of all transport info fields that the | |||||
* client is interested in. | |||||
* On return, the 'valid' field of the tinfo struct will contain | |||||
* a bitmask of all transport info fields that are legal to | |||||
* use. | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | |||||
*/ | */ | ||||
int jack_get_transport_info (jack_client_t *client, | |||||
jack_transport_info_t *tinfo); | |||||
void jack_get_transport_info (jack_client_t *client, | |||||
jack_transport_info_t *tinfo); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
@@ -288,7 +288,7 @@ static void | |||||
jack_register_shm (char *shm_name) | jack_register_shm (char *shm_name) | ||||
{ | { | ||||
if (jack_shm_id_cnt < MAX_SHM_ID) { | if (jack_shm_id_cnt < MAX_SHM_ID) { | ||||
snprintf (jack_shm_registry[jack_shm_id_cnt++], sizeof (shm_name_t), shm_name); | |||||
snprintf (jack_shm_registry[jack_shm_id_cnt++], sizeof (shm_name_t), "%s", shm_name); | |||||
} | } | ||||
} | } | ||||
@@ -615,9 +615,14 @@ jack_engine_post_process (jack_engine_t *engine) | |||||
JSList *node; | JSList *node; | ||||
int need_remove = FALSE; | int need_remove = FALSE; | ||||
/* maintain the current_time.usecs and frame_rate values, since clients | |||||
are not permitted to set these. | |||||
*/ | |||||
engine->control->pending_time.usecs = engine->control->current_time.usecs; | engine->control->pending_time.usecs = engine->control->current_time.usecs; | ||||
engine->control->pending_time.frame_rate = engine->control->current_time.frame_rate; | |||||
engine->control->current_time = engine->control->pending_time; | engine->control->current_time = engine->control->pending_time; | ||||
/* find any clients that need removal due to timeouts, etc. */ | /* find any clients that need removal due to timeouts, etc. */ | ||||
for (node = engine->clients; node; node = jack_slist_next (node) ) { | for (node = engine->clients; node; node = jack_slist_next (node) ) { | ||||
@@ -1276,6 +1281,8 @@ jack_client_deactivate (jack_engine_t *engine, jack_client_id_t id) | |||||
engine->control->pending_time.frame = 0; | engine->control->pending_time.frame = 0; | ||||
engine->control->current_time.transport_state = JackTransportStopped; | engine->control->current_time.transport_state = JackTransportStopped; | ||||
engine->control->pending_time.transport_state = JackTransportStopped; | engine->control->pending_time.transport_state = JackTransportStopped; | ||||
engine->control->current_time.valid = JackTransportState|JackTransportPosition; | |||||
engine->control->pending_time.valid = JackTransportState|JackTransportPosition; | |||||
} | } | ||||
for (portnode = client->ports; portnode; portnode = jack_slist_next (portnode)) { | for (portnode = client->ports; portnode; portnode = jack_slist_next (portnode)) { | ||||
@@ -2150,6 +2157,8 @@ jack_zombify_client (jack_engine_t *engine, jack_client_internal_t *client) | |||||
engine->control->pending_time.frame = 0; | engine->control->pending_time.frame = 0; | ||||
engine->control->current_time.transport_state = JackTransportStopped; | engine->control->current_time.transport_state = JackTransportStopped; | ||||
engine->control->pending_time.transport_state = JackTransportStopped; | engine->control->pending_time.transport_state = JackTransportStopped; | ||||
engine->control->current_time.valid = JackTransportState|JackTransportPosition; | |||||
engine->control->pending_time.valid = JackTransportState|JackTransportPosition; | |||||
} | } | ||||
jack_client_disconnect (engine, client); | jack_client_disconnect (engine, client); | ||||
@@ -2819,6 +2828,7 @@ jack_port_do_connect (jack_engine_t *engine, | |||||
jack_connection_internal_t *connection; | jack_connection_internal_t *connection; | ||||
jack_port_internal_t *srcport, *dstport; | jack_port_internal_t *srcport, *dstport; | ||||
jack_port_id_t src_id, dst_id; | jack_port_id_t src_id, dst_id; | ||||
jack_client_internal_t *client; | |||||
if ((srcport = jack_get_port_by_name (engine, source_port)) == NULL) { | if ((srcport = jack_get_port_by_name (engine, source_port)) == NULL) { | ||||
jack_error ("unknown source port in attempted connection [%s]", source_port); | jack_error ("unknown source port in attempted connection [%s]", source_port); | ||||
@@ -2852,12 +2862,31 @@ jack_port_do_connect (jack_engine_t *engine, | |||||
return -1; | return -1; | ||||
} | } | ||||
if (strcmp (srcport->shared->type_info.type_name, | |||||
dstport->shared->type_info.type_name) != 0) { | |||||
if (strcmp (srcport->shared->type_info.type_name, dstport->shared->type_info.type_name) != 0) { | |||||
jack_error ("ports used in attemped connection are not of the same data type"); | jack_error ("ports used in attemped connection are not of the same data type"); | ||||
return -1; | return -1; | ||||
} | } | ||||
if ((client = jack_client_internal_by_id (engine, srcport->shared->client_id)) == 0) { | |||||
jack_error ("unknown client set as owner of port - cannot connect"); | |||||
return -1; | |||||
} | |||||
if (!client->control->active) { | |||||
jack_error ("cannot connect ports owned by inactive clients; \"%s\" is not active", client->control->name); | |||||
return -1; | |||||
} | |||||
if ((client = jack_client_internal_by_id (engine, dstport->shared->client_id)) == 0) { | |||||
jack_error ("unknown client set as owner of port - cannot connect"); | |||||
return -1; | |||||
} | |||||
if (!client->control->active) { | |||||
jack_error ("cannot connect ports owned by inactive clients; \"%s\" is not active", client->control->name); | |||||
return -1; | |||||
} | |||||
connection = (jack_connection_internal_t *) malloc (sizeof (jack_connection_internal_t)); | connection = (jack_connection_internal_t *) malloc (sizeof (jack_connection_internal_t)); | ||||
connection->source = srcport; | connection->source = srcport; | ||||
@@ -529,7 +529,7 @@ jack_client_new (const char *client_name) | |||||
fail: | fail: | ||||
if (client->engine) { | if (client->engine) { | ||||
munmap ((char *) client->engine, sizeof (jack_control_t)); | |||||
munmap ((char *) client->engine, res.control_size); | |||||
} | } | ||||
if (client->control) { | if (client->control) { | ||||
munmap ((char *) client->control, sizeof (jack_client_control_t)); | munmap ((char *) client->control, sizeof (jack_client_control_t)); | ||||
@@ -1411,48 +1411,18 @@ jack_frame_time (const jack_client_t *client) | |||||
/* TRANSPORT CONTROL */ | /* TRANSPORT CONTROL */ | ||||
int | |||||
void | |||||
jack_get_transport_info (jack_client_t *client, | jack_get_transport_info (jack_client_t *client, | ||||
jack_transport_info_t *info) | jack_transport_info_t *info) | ||||
{ | { | ||||
jack_time_info_t *time_info = &client->engine->current_time; | |||||
if (info->valid & JackTransportState) { | |||||
info->state = time_info->transport_state; | |||||
} | |||||
if (info->valid & JackTransportPosition) { | |||||
info->position = time_info->frame; | |||||
} | |||||
if (info->valid & JackTransportLoop) { | |||||
info->loop_start = time_info->loop_start; | |||||
info->loop_end = time_info->loop_end; | |||||
} | |||||
return 0; | |||||
*info = client->engine->current_time; | |||||
} | } | ||||
int | |||||
void | |||||
jack_set_transport_info (jack_client_t *client, | jack_set_transport_info (jack_client_t *client, | ||||
jack_transport_info_t *info) | jack_transport_info_t *info) | ||||
{ | { | ||||
jack_time_info_t *time_info = &client->engine->pending_time; | |||||
if (info->valid & JackTransportState) { | |||||
time_info->transport_state = info->state; | |||||
} | |||||
if (info->valid & JackTransportPosition) { | |||||
time_info->frame = info->position; | |||||
} | |||||
if (info->valid & JackTransportLoop) { | |||||
time_info->loop_start = info->loop_start; | |||||
time_info->loop_end = info->loop_end; | |||||
} | |||||
return 0; | |||||
client->engine->pending_time = *info; | |||||
} | } | ||||
float | float | ||||