Commit ad347033 authored by sletz's avatar sletz
Browse files

rebase from trunk 4306:4323

git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@4324 0c269be4-1314-0410-8aa9-9f06e86f4224
parent ecb84b5f
......@@ -34,6 +34,10 @@ Valerio Pilo
Jackdmp changes log
---------------------------
2011-04-18 Stephane Letz <letz@grame.fr>
* JackWeakAPI.cpp renamed in JackWeakAPI.c.
2011-04-04 Stephane Letz <letz@grame.fr>
* Correct driver lifetime management.
......
......@@ -28,12 +28,12 @@ namespace Jack
int JackFreewheelDriver::Process()
{
int res = 0;
int res = 0;
jack_log("JackFreewheelDriver::Process master %lld", fEngineControl->fTimeOutUsecs);
JackDriver::CycleTakeBeginTime();
jack_log("JackFreewheelDriver::Process master %lld", fEngineControl->fTimeOutUsecs);
JackDriver::CycleTakeBeginTime();
if (fEngine->Process(fBeginDateUst, fEndDateUst)) {
if (fEngine->Process(fBeginDateUst, fEndDateUst)) {
if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable)) { // Signal all clients
jack_error("JackFreewheelDriver::Process: ResumeRefNum error");
......@@ -46,10 +46,10 @@ int JackFreewheelDriver::Process()
return 0;
}
} else { // Graph not finished: do not activate it
} else { // Graph not finished: do not activate it
jack_error("JackFreewheelDriver::Process: Process error");
res = -1;
}
}
return res;
}
......
......@@ -54,23 +54,16 @@ JackMidiAsyncQueue::DequeueEvent()
{
jack_midi_event_t *event = 0;
if (jack_ringbuffer_read_space(info_ring) >= INFO_SIZE) {
size_t size;
event = &dequeue_event;
jack_ringbuffer_read(info_ring, (char *) &(event->time),
sizeof(jack_nframes_t));
size_t size;
jack_ringbuffer_read(info_ring, (char *) &size, sizeof(size_t));
jack_ringbuffer_read(info_ring, (char *) &size,
sizeof(size_t));
jack_ringbuffer_read(byte_ring, (char *) data_buffer,
size * sizeof(jack_midi_data_t));
event->buffer = data_buffer;
event->size = size;
jack_ringbuffer_data_t vector[2];
jack_ringbuffer_get_read_vector(byte_ring, vector);
size_t size1 = vector[0].len;
memcpy(data_buffer, vector[0].buf, size1 * sizeof(jack_midi_data_t));
if (size1 < size) {
memcpy(data_buffer + size1, vector[1].buf,
(size - size1) * sizeof(jack_midi_data_t));
}
jack_ringbuffer_read_advance(byte_ring,
size * sizeof(jack_midi_data_t));
}
return event;
}
......
......@@ -28,14 +28,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
namespace Jack {
/**
* This is a MIDI message queue designed to allow two threads to pass MIDI
* messages between two threads (though it can also be used to buffer
* events internally). This is especially useful if the MIDI API
* you're attempting to interface with doesn't provide the ability to
* schedule MIDI events ahead of time and/or has blocking send/receive
* calls, as it allows a separate thread to handle input/output while the
* JACK process thread copies events from a `JackMidiBufferReadQueue` to
* this queue, or from this queue to a `JackMidiBufferWriteQueue`.
* This is a MIDI message queue designed to allow one thread to pass MIDI
* messages to another thread (though it can also be used to buffer events
* internally). This is especially useful if the MIDI API you're
* attempting to interface with doesn't provide the ability to schedule
* MIDI events ahead of time and/or has blocking send/receive calls, as it
* allows a separate thread to handle input/output while the JACK process
* thread copies events from a MIDI buffer to this queue, or vice versa.
*/
class SERVER_EXPORT JackMidiAsyncQueue:
......@@ -64,7 +63,8 @@ namespace Jack {
JackMidiAsyncQueue(size_t max_bytes=4096, size_t max_messages=1024);
virtual ~JackMidiAsyncQueue();
virtual
~JackMidiAsyncQueue();
/**
* Dequeues and returns a MIDI event. Returns '0' if there are no MIDI
......
......@@ -66,6 +66,12 @@ JackMidiRawInputWriteQueue::EnqueueEvent(jack_nframes_t time, size_t size,
return packet_queue->EnqueueEvent(time, size, buffer);
}
size_t
JackMidiRawInputWriteQueue::GetAvailableSpace()
{
return packet_queue->GetAvailableSpace();
}
void
JackMidiRawInputWriteQueue::HandleBufferFailure(size_t unbuffered_bytes,
size_t total_bytes)
......
......@@ -142,6 +142,13 @@ namespace Jack {
EnqueueEvent(jack_nframes_t time, size_t size,
jack_midi_data_t *buffer);
/**
* Returns the maximum size event that can be enqueued right *now*.
*/
size_t
GetAvailableSpace();
/**
* The `Process()` method should be called each time the
* `EnqueueEvent()` method returns `OK`. The `Process()` method will
......
......@@ -50,27 +50,23 @@ JackMidiRawOutputWriteQueue::~JackMidiRawOutputWriteQueue()
delete rt_queue;
}
bool
void
JackMidiRawOutputWriteQueue::DequeueNonRealtimeEvent()
{
non_rt_event = non_rt_queue->DequeueEvent();
bool result = non_rt_event != 0;
if (result) {
if (non_rt_event) {
non_rt_event_time = non_rt_event->time;
running_status = ApplyRunningStatus(non_rt_event, running_status);
}
return result;
}
bool
void
JackMidiRawOutputWriteQueue::DequeueRealtimeEvent()
{
rt_event = rt_queue->DequeueEvent();
bool result = rt_event != 0;
if (result) {
if (rt_event) {
rt_event_time = rt_event->time;
}
return result;
}
Jack::JackMidiWriteQueue::EnqueueResult
......@@ -79,11 +75,7 @@ JackMidiRawOutputWriteQueue::EnqueueEvent(jack_nframes_t time, size_t size,
{
JackMidiAsyncQueue *queue = (size == 1) && (*buffer >= 0xf8) ? rt_queue :
non_rt_queue;
EnqueueResult result = queue->EnqueueEvent(time, size, buffer);
if (result == OK) {
last_enqueued_message_time = time;
}
return result;
return queue->EnqueueEvent(time, size, buffer);
}
void
......@@ -99,38 +91,34 @@ JackMidiRawOutputWriteQueue::HandleWriteQueueBug(jack_nframes_t time,
jack_nframes_t
JackMidiRawOutputWriteQueue::Process(jack_nframes_t boundary_frame)
{
jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
while (STILL_TIME(current_frame, boundary_frame)) {
if (! non_rt_event) {
DequeueNonRealtimeEvent();
}
if (! rt_event) {
DequeueRealtimeEvent();
}
if (! (non_rt_event || rt_event)) {
return 0;
if (! non_rt_event) {
DequeueNonRealtimeEvent();
}
if (! rt_event) {
DequeueRealtimeEvent();
}
while (rt_event) {
jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
if ((rt_event_time > current_frame) && non_rt_event &&
(non_rt_event_time < rt_event_time)) {
if (! SendNonRTBytes(rt_event_time < boundary_frame ?
rt_event_time : boundary_frame)) {
return non_rt_event_time;
}
current_frame = send_queue->GetNextScheduleFrame();
}
if (! WriteRealtimeEvents(boundary_frame)) {
break;
if (! STILL_TIME(current_frame, boundary_frame)) {
return (! non_rt_event) ? rt_event_time :
non_rt_event_time < rt_event_time ? non_rt_event_time :
rt_event_time;
}
jack_nframes_t non_rt_boundary =
rt_event && STILL_TIME(rt_event_time, boundary_frame) ?
rt_event_time : boundary_frame;
if (! WriteNonRealtimeEvents(non_rt_boundary)) {
break;
if (! SendByte(rt_event_time, *(rt_event->buffer))) {
return rt_event_time;
}
current_frame = send_queue->GetNextScheduleFrame();
DequeueRealtimeEvent();
}
// If we get here, that means there is some sort of message available, and
// that either we can't currently write to the write queue or we have
// reached the boundary frame. Return the earliest time that a message is
// scheduled to be sent.
return ! non_rt_event ? rt_event_time :
non_rt_event->size > 1 ? current_frame :
! rt_event ? non_rt_event_time :
non_rt_event_time < rt_event_time ? non_rt_event_time : rt_event_time;
SendNonRTBytes(boundary_frame);
return non_rt_event ? non_rt_event_time : 0;
}
bool
......@@ -151,78 +139,20 @@ JackMidiRawOutputWriteQueue::SendByte(jack_nframes_t time,
}
bool
JackMidiRawOutputWriteQueue::
WriteNonRealtimeEvents(jack_nframes_t boundary_frame)
JackMidiRawOutputWriteQueue::SendNonRTBytes(jack_nframes_t boundary_frame)
{
if (! non_rt_event) {
if (! DequeueNonRealtimeEvent()) {
return true;
}
}
jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
do {
// Send out as much of the non-realtime buffer as we can, save for one
// byte which we will send out when the message is supposed to arrive.
for (; non_rt_event->size > 1;
while (non_rt_event) {
for (; non_rt_event->size;
(non_rt_event->size)--, (non_rt_event->buffer)++) {
jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
if (! STILL_TIME(current_frame, boundary_frame)) {
return true;
}
if (! SendByte(current_frame, *(non_rt_event->buffer))) {
if (! SendByte(non_rt_event_time, *(non_rt_event->buffer))) {
return false;
}
current_frame = send_queue->GetNextScheduleFrame();
}
if (! (STILL_TIME(current_frame, boundary_frame) &&
STILL_TIME(non_rt_event_time, boundary_frame))) {
return true;
}
// There's still time. Try to send the byte.
if (! SendByte(non_rt_event_time, *(non_rt_event->buffer))) {
return false;
}
current_frame = send_queue->GetNextScheduleFrame();
if (! DequeueNonRealtimeEvent()) {
break;
}
} while (STILL_TIME(current_frame, boundary_frame));
return true;
}
bool
JackMidiRawOutputWriteQueue::WriteRealtimeEvents(jack_nframes_t boundary_frame)
{
jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
if (! rt_event) {
if (! DequeueRealtimeEvent()) {
return true;
}
}
for (;;) {
if (! STILL_TIME(current_frame, boundary_frame)) {
return false;
}
// If:
// -there's still time before we need to send the realtime event
// -there's a non-realtime event available for sending
// -non-realtime data can be scheduled before this event
if ((rt_event_time > current_frame) && non_rt_event &&
((non_rt_event->size > 1) ||
(non_rt_event_time < rt_event_time))) {
return true;
}
if (! SendByte(rt_event_time, *(rt_event->buffer))) {
return false;
}
current_frame = send_queue->GetNextScheduleFrame();
if (! DequeueRealtimeEvent()) {
return true;
}
DequeueNonRealtimeEvent();
}
return true;
}
......@@ -27,7 +27,7 @@ namespace Jack {
/**
* This queue enqueues valid MIDI events and modifies them for raw output
* to a write queue. It has a number of advantages over straight MIDI
* to a write queue. It has a couple of advantages over straight MIDI
* event copying:
*
* -Running status: Status bytes can be omitted when the status byte of the
......@@ -39,10 +39,6 @@ namespace Jack {
* non-realtime bytes so that realtime messages can be sent as close as
* possible to the time they're scheduled for sending.
*
* -Time optimization: Bytes in non-realtime messages are sent out early
* when possible, with the last byte of the message being sent out as close
* to the specified event time as possible.
*
* Use this queue if the MIDI API you're interfacing with allows you to
* send raw MIDI bytes.
*/
......@@ -52,7 +48,6 @@ namespace Jack {
private:
jack_nframes_t last_enqueued_message_time;
jack_midi_event_t *non_rt_event;
jack_nframes_t non_rt_event_time;
JackMidiAsyncQueue *non_rt_queue;
......@@ -62,20 +57,17 @@ namespace Jack {
jack_midi_data_t running_status;
JackMidiSendQueue *send_queue;
bool
void
DequeueNonRealtimeEvent();
bool
void
DequeueRealtimeEvent();
bool
SendByte(jack_nframes_t time, jack_midi_data_t byte);
bool
WriteNonRealtimeEvents(jack_nframes_t boundary_frame);
bool
WriteRealtimeEvents(jack_nframes_t boundary_frame);
SendNonRTBytes(jack_nframes_t boundary_frame);
protected:
......
......@@ -55,10 +55,11 @@ Jack::ApplyRunningStatus(jack_midi_event_t *event,
jack_nframes_t
Jack::GetCurrentFrame()
{
jack_time_t time = GetMicroSeconds();
JackEngineControl *control = GetEngineControl();
JackTimer timer;
control->ReadFrameTime(&timer);
return timer.Time2Frames(GetMicroSeconds(), control->fBufferSize);
return timer.Time2Frames(time, control->fBufferSize);
}
jack_nframes_t
......
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id:
//
// jackWeakAPI based on code from Stéphane Letz (Grame)
// partly based on Julien Pommier (PianoTeq : http://www.pianoteq.com/) code.
// jackWeakAPI partly based on Julien Pommier (PianoTeq : http://www.pianoteq.com/) code.
//
// Copyright (C) 2002-2007 Werner Schweer and others
// Copyright (C) 2009 Grame
......@@ -24,6 +20,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <jack/jack.h>
#include <jack/session.h>
#include <jack/thread.h>
#include <jack/midiport.h>
#include <math.h>
......@@ -31,7 +28,7 @@
#include <dlfcn.h>
#endif
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
/* dynamically load libjack and forward all registered calls to libjack
(similar to what relaytool is trying to do, but more portably..)
......@@ -40,24 +37,25 @@
typedef void (*print_function)(const char *);
typedef void *(*thread_routine)(void*);
using std::cerr;
int libjack_is_present = 0; // public symbol, similar to what relaytool does.
static int libjack_is_present = 0; // public symbol, similar to what relaytool does.
#ifdef WIN32
HMODULE libjack_handle = 0;
static HMODULE libjack_handle = 0;
#else
static void *libjack_handle = 0;
#endif
static void __attribute__((constructor)) tryload_libjack()
{
if (getenv("SKIP_LIBJACK") == 0) { // just in case libjack is causing troubles..
#ifdef __APPLE__
libjack_handle = dlopen("libjack.0.dylib", RTLD_LAZY);
#elif defined(WIN32)
libjack_handle = LoadLibrary("libjack.dll");
#ifdef _WIN64
libjack_handle = LoadLibrary("libjack64.dll");
#else
libjack_handle = LoadLibrary("libjack.dll");
#endif
#else
libjack_handle = dlopen("libjack.so.0", RTLD_LAZY);
#endif
......@@ -289,8 +287,8 @@ DECL_VOID_FUNCTION(jack_free, (void* ptr), (ptr));
// session
DECL_FUNCTION(int, jack_set_session_callback, (jack_client_t* ext_client, JackSessionCallback session_callback, void* arg), (ext_client, session_callback, arg));
DECL_FUNCTION(jack_session_command_t*, jack_session_notify, (jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path), (ext_client, target, ev_type, path)à);
DECL_FUNCTION(int jack_session_reply, (jack_client_t* ext_client, jack_session_event_t *event), (ext_client, event));
DECL_FUNCTION(jack_session_command_t*, jack_session_notify, (jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path), (ext_client, target, ev_type, path));
DECL_FUNCTION(int, jack_session_reply, (jack_client_t* ext_client, jack_session_event_t *event), (ext_client, event));
DECL_VOID_FUNCTION(jack_session_event_free, (jack_session_event_t* ev), (ev));
DECL_FUNCTION(char*, jack_get_uuid_for_client_name, (jack_client_t* ext_client, const char* client_name),(ext_client, client_name));
DECL_FUNCTION(char*, jack_get_client_name_by_uuid, (jack_client_t* ext_client, const char* client_uuid),(ext_client, client_uuid));
......
......@@ -540,12 +540,15 @@ int main(int argc, char* argv[])
// Slave drivers
for (it = slaves_list.begin(); it != slaves_list.end(); it++) {
jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it);
jackctl_server_remove_slave(server_ctl, slave_driver_ctl);
if (slave_driver_ctl)
jackctl_server_remove_slave(server_ctl, slave_driver_ctl);
}
// Internal clients
for (it = internals_list.begin(); it != internals_list.end(); it++) {
jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it);
jackctl_server_unload_internal(server_ctl, internal_driver_ctl);
if (internal_driver_ctl)
jackctl_server_unload_internal(server_ctl, internal_driver_ctl);
}
jackctl_server_close(server_ctl);
destroy_server:
......
......@@ -55,8 +55,6 @@ $Id: net_driver.c,v 1.17 2006/04/16 20:16:10 torbenh Exp $
#include <samplerate.h>
#endif
#include "JackError.h"
#include "netjack.h"
#include "netjack_packet.h"
......
......@@ -68,8 +68,6 @@
#include <samplerate.h>
#endif
#include "JackError.h"
#if HAVE_CELT
#include <celt/celt.h>
#endif
......
/* -*- Mode: C ; c-basic-offset: 4 -*- */
/*
Copyright (C) 2007,2008,2010 Nedko Arnaudov
Copyright (C) 2007,2008,2010,2011 Nedko Arnaudov
Copyright (C) 2007-2008 Juuso Alasuutari
This program is free software; you can redistribute it and/or modify
......@@ -42,6 +42,7 @@ struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
NULL
};
static
jackctl_driver_t *
jack_controller_find_driver(
jackctl_server_t *server,
......@@ -64,9 +65,7 @@ jack_controller_find_driver(
return NULL;
}
bool
jack_controller_add_slave_drivers(
struct jack_controller * controller_ptr)
static bool jack_controller_check_slave_driver(struct jack_controller * controller_ptr, const char * name)
{
struct list_head * node_ptr;
struct jack_controller_slave_driver * driver_ptr;
......@@ -74,31 +73,40 @@ jack_controller_add_slave_drivers(
list_for_each(node_ptr, &controller_ptr->slave_drivers)
{
driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
driver_ptr->handle = jack_controller_find_driver(controller_ptr->server, driver_ptr->name);
if (driver_ptr->handle == NULL)
if (strcmp(name, driver_ptr->name) == 0)
{
jack_error("Unknown driver \"%s\"", driver_ptr->name);
goto fail;
return true;
}
}
return false;
}
static bool jack_controller_load_slave_drivers(struct jack_controller * controller_ptr)
{
struct list_head * node_ptr;
struct jack_controller_slave_driver * driver_ptr;
list_for_each(node_ptr, &controller_ptr->slave_drivers)
{
driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
assert(driver_ptr->handle != NULL);
assert(!driver_ptr->loaded);
if (!jackctl_server_add_slave(controller_ptr->server, driver_ptr->handle))
{
jack_error("Driver \"%s\" cannot be loaded", driver_ptr->name);
goto fail;
return false;
}
driver_ptr->loaded = true;
}
return true;
fail:
driver_ptr->handle = NULL;
return false;
}
void
jack_controller_remove_slave_drivers(
struct jack_controller * controller_ptr)
static void jack_controller_unload_slave_drivers(struct jack_controller * controller_ptr)
{
struct list_head * node_ptr;
struct jack_controller_slave_driver * driver_ptr;
......@@ -106,14 +114,31 @@ jack_controller_remove_slave_drivers(
list_for_each(node_ptr, &controller_ptr->slave_drivers)
{
driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
if (driver_ptr->handle != NULL)
if (driver_ptr->loaded)
{
jackctl_server_remove_slave(controller_ptr->server, driver_ptr->handle);
driver_ptr->handle = NULL;
driver_ptr->loaded = false;
}
}
}
static void jack_controller_remove_slave_drivers(struct jack_controller * controller_ptr)
{
struct jack_controller_slave_driver * driver_ptr;
while (!list_empty(&controller_ptr->slave_drivers))
{
driver_ptr = list_entry(controller_ptr->slave_drivers.next, struct jack_controller_slave_driver, siblings);
assert(!driver_ptr->loaded);
list_del(&driver_ptr->siblings);
free(driver_ptr->name);
free(driver_ptr);
}
controller_ptr->slave_drivers_vparam_value.str[0] = 0;
}
static
jackctl_internal_t *
jack_controller_find_internal(
jackctl_server_t *server,
......@@ -136,42 +161,18 @@ jack_controller_find_internal(
return NULL;
}
jackctl_parameter_t *
jack_controller_find_parameter(
const JSList * parameters_list,