Commit 82316a54 authored by sletz's avatar sletz
Browse files

Merge of Dmitry Baikov MIDI branch.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1647 0c269be4-1314-0410-8aa9-9f06e86f4224
parent 17a9ec8e
......@@ -13,6 +13,10 @@ Tom Szilagyi
Jackdmp changes log
---------------------------
2007-10-25 Stephane Letz <letz@grame.fr>
* Merge of Dmitry Baikov MIDI branch.
2007-10-24 Stephane Letz <letz@grame.fr>
* Implementation of server_name setting (-n).
......@@ -130,6 +134,10 @@ Tom Szilagyi
2007-05-29 Stephane Letz <letz@grame.fr>
* Add "callback exiting" and "jack_frame_time" tests in jack_test.
2007-05-09 Stephane Letz <letz@grame.fr>
* Add a mutex in JackGraphManager AllocatePort/ReleasePort methods.
2007-05-05 Stephane Letz <letz@grame.fr>
......@@ -154,14 +162,39 @@ Tom Szilagyi
2007-04-23 Stephane Letz <letz@grame.fr>
* Dmitry Baikov jackmp-time patch: add jack_get_time, jack_time_to_frames, jack_frames_to_time.
2007-04-03 Stephane Letz <letz@grame.fr>
* Dmitry Baikov remove-nframes patch.
2007-04-02 Stephane Letz <letz@grame.fr>
* Dmitry Baikov lost-event patch.
2007-04-01 Stephane Letz <letz@grame.fr>
* Merge JackGraphManager Remove and Release method in a unique Release method.
2007-03-12 Stephane Letz <letz@grame.fr>
* Bug fix in JackMidiBuffer::MaxEventSize().
2007-03-09 Stephane Letz <letz@grame.fr>
* Dmitry Baikov MIDI patch phase 2.
2007-03-08 Stephane Letz <letz@grame.fr>
* Dmitry Baikov jackmp-port-clear patch.
2007-03-06 Stephane Letz <letz@grame.fr>
* Dmitry Baikov MIDI patch phase 1.
2007-03-04 Stephane Letz <letz@grame.fr>
* Dmitry Baikov patch for JackGraphManager.cpp.
* Dmitry Baikov patch for JackGraphManager.cpp.
* Dmitry Baikov MIDI patch phase 0.
2007-02-19 Stephane Letz <letz@grame.fr>
......
......@@ -220,7 +220,7 @@ class JackAtomicState
UInt16 cur_index;
UInt16 next_index = GetCurrentIndex();
do {
cur_index = next_index;
cur_index = next_index;
state = ReadCurrentState();
......
......
......@@ -53,6 +53,7 @@ int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
{
fEngineControl->fBufferSize = buffer_size;
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec
fGraphManager->SetBufferSize(buffer_size);
return 0;
}
......@@ -86,7 +87,7 @@ int JackAudioDriver::Attach()
for (i = 0; i < fCaptureChannels; i++) {
snprintf(buf, sizeof(buf) - 1, "%s:%s:out%d", fClientControl->fName, fCaptureDriverName, i + 1);
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags)) == NO_PORT) {
jack_error("driver: cannot register port for %s", buf);
return -1;
}
......@@ -101,7 +102,7 @@ int JackAudioDriver::Attach()
for (i = 0; i < fPlaybackChannels; i++) {
snprintf(buf, sizeof(buf) - 1, "%s:%s:in%d", fClientControl->fName, fPlaybackDriverName, i + 1);
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags)) == NO_PORT) {
jack_error("driver: cannot register port for %s", buf);
return -1;
}
......@@ -115,7 +116,7 @@ int JackAudioDriver::Attach()
if (fWithMonitorPorts) {
JackLog("Create monitor port \n");
snprintf(buf, sizeof(buf) - 1, "%s:%s:monitor_%u", fClientControl->fName, fPlaybackDriverName, i + 1);
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, JackPortIsOutput)) == NO_PORT) {
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput)) == NO_PORT) {
jack_error("Cannot register monitor port for %s", buf);
return -1;
} else {
......
/*
Copyright (C) 2001-2003 Paul Davis
Copyright (C) 2004-2006 Grame
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 "JackPortType.h"
#include <string.h>
namespace Jack
{
static void AudioBufferInit(void* buffer, size_t buffer_size, jack_nframes_t)
{
memset(buffer, 0, buffer_size);
}
static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_t frames)
{
jack_nframes_t frames_group = frames / 4;
frames = frames % 4;
while (frames_group > 0) {
register float mixFloat1 = *mixbuffer;
register float sourceFloat1 = *buffer;
register float mixFloat2 = *(mixbuffer + 1);
register float sourceFloat2 = *(buffer + 1);
register float mixFloat3 = *(mixbuffer + 2);
register float sourceFloat3 = *(buffer + 2);
register float mixFloat4 = *(mixbuffer + 3);
register float sourceFloat4 = *(buffer + 3);
buffer += 4;
frames_group--;
mixFloat1 += sourceFloat1;
mixFloat2 += sourceFloat2;
mixFloat3 += sourceFloat3;
mixFloat4 += sourceFloat4;
*mixbuffer = mixFloat1;
*(mixbuffer + 1) = mixFloat2;
*(mixbuffer + 2) = mixFloat3;
*(mixbuffer + 3) = mixFloat4;
mixbuffer += 4;
}
while (frames > 0) {
register float mixFloat1 = *mixbuffer;
register float sourceFloat1 = *buffer;
buffer++;
frames--;
mixFloat1 += sourceFloat1;
*mixbuffer = mixFloat1;
mixbuffer++;
}
}
static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_count, jack_nframes_t nframes)
{
void* buffer;
// Copy first buffer
memcpy(mixbuffer, src_buffers[0], nframes * sizeof(float));
// Mix remaining buffers
for (int i = 1; i < src_count; ++i) {
buffer = src_buffers[i];
MixAudioBuffer((float*)mixbuffer, (float*)buffer, nframes);
}
}
const JackPortType gAudioPortType = {
JACK_DEFAULT_AUDIO_TYPE,
AudioBufferInit,
AudioBufferMixdown
};
} // namespace Jack
......@@ -86,7 +86,7 @@ class JackClientChannelInterface
virtual void ClientDeactivate(int refnum, int* result)
{}
virtual void PortRegister(int refnum, const char* name, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result)
virtual void PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result)
{}
virtual void PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
{}
......
......@@ -414,11 +414,11 @@ int JackClient::PortRegister(const char* port_name, const char* port_type, unsig
return 0; // Means failure here...
}
JackLog("JackClient::PortRegister ref = %ld name = %s \n", GetClientControl()->fRefNum, name.c_str());
JackLog("JackClient::PortRegister ref = %ld name = %s type = %s\n", GetClientControl()->fRefNum, name.c_str(), port_type);
int result = -1;
jack_port_id_t port_index = NO_PORT;
fChannel->PortRegister(GetClientControl()->fRefNum, name.c_str(), flags, buffer_size, &port_index, &result);
fChannel->PortRegister(GetClientControl()->fRefNum, name.c_str(), port_type, flags, buffer_size, &port_index, &result);
JackLog("JackClient::PortRegister port_index = %ld \n", port_index);
if (result == 0) {
......
......@@ -129,6 +129,7 @@ int JackDriver::Open(jack_nframes_t nframes,
if (fEngineControl->fTimeOutUsecs == 0) /* usecs; if zero, use 2 period size. */
fEngineControl->fTimeOutUsecs = (jack_time_t)(2.f * fEngineControl->fPeriodUsecs);
fGraphManager->SetBufferSize(nframes);
fGraphManager->DirectConnect(fClientControl->fRefNum, fClientControl->fRefNum); // Connect driver to itself for sync
/*
......
......@@ -59,6 +59,7 @@ class JackDummyDriver : public JackAudioDriver
jack_nframes_t playback_latency);
int Process();
};
} // end of namespace
......
......@@ -680,12 +680,12 @@ int JackEngine::ClientDeactivate(int refnum)
// Port management
//-----------------
int JackEngine::PortRegister(int refnum, const char* name, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index)
int JackEngine::PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index)
{
JackLog("JackEngine::PortRegister ref = %ld name = %s flags = %d buffer_size = %d\n", refnum, name, flags, buffer_size);
JackLog("JackEngine::PortRegister ref = %ld name = %s type = %s flags = %d buffer_size = %d\n", refnum, name, type, flags, buffer_size);
assert(fClientTable[refnum]);
*port_index = fGraphManager->AllocatePort(refnum, name, (JackPortFlags)flags);
*port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags);
if (*port_index != NO_PORT) {
NotifyPortRegistation(*port_index, true);
return 0;
......
......@@ -96,7 +96,7 @@ class JackEngine
int InternalClientUnload(int refnum, int* status);
// Port management
int PortRegister(int refnum, const char* name, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index);
int PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index);
int PortUnRegister(int refnum, jack_port_id_t port);
int PortConnect(int refnum, const char* src, const char* dst);
......
......@@ -165,31 +165,26 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff
jack_int_t len = manager->Connections(port_index);
if (len == 0) { // No connections: return a zero-filled buffer
float* buffer = GetBuffer(port_index);
memset(buffer, 0, buffer_size * sizeof(float)); // Clear buffer
return buffer;
port->ClearBuffer(buffer_size);
return port->GetBuffer();
} else if (len == 1) { // One connection: use zero-copy mode - just pass the buffer of the connected (output) port.
assert(manager->GetPort(port_index, 0) != port_index); // Check recursion
return GetBuffer(manager->GetPort(port_index, 0), buffer_size);
} else { // Multiple connections
const jack_int_t* connections = manager->GetConnections(port_index);
float* mixbuffer = GetBuffer(port_index);
jack_port_id_t src_index;
float* buffer;
// Copy first buffer
src_index = connections[0];
AssertPort(src_index);
buffer = (float*)GetBuffer(src_index, buffer_size);
memcpy(mixbuffer, buffer, buffer_size * sizeof(float));
// Mix remaining buffers
for (int i = 1; (i < CONNECTION_NUM) && ((src_index = connections[i]) != EMPTY); i++) {
void* buffers[CONNECTION_NUM];
jack_port_id_t src_index;
int i;
for (i = 0; (i < CONNECTION_NUM) && ((src_index = connections[i]) != EMPTY); i++) {
AssertPort(src_index);
buffer = (float*)GetBuffer(src_index, buffer_size);
JackPort::MixBuffer(mixbuffer, buffer, buffer_size);
buffers[i] = GetBuffer(src_index, buffer_size);
}
return mixbuffer;
JackPort* port = GetPort(port_index);
port->MixBuffers(buffers, i, buffer_size);
return port->GetBuffer();
}
}
......@@ -202,7 +197,7 @@ int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // C
/**
jackd.h
* If @ref JackPortCanMonitor is set for this @a port, turn input
* monitoring on or off. Otherwise, do nothing.
* monitoring on or off. Otherwise, do nothing.
if (!(fFlags & JackPortCanMonitor))
return -1;
......@@ -266,7 +261,7 @@ jack_nframes_t JackGraphManager::GetTotalLatency(jack_port_id_t port_index)
}
// Server
jack_port_id_t JackGraphManager::AllocatePortAux(int refnum, const char* port_name, JackPortFlags flags)
jack_port_id_t JackGraphManager::AllocatePortAux(int refnum, const char* port_name, const char* port_type, JackPortFlags flags)
{
jack_port_id_t port_index;
......@@ -274,8 +269,9 @@ jack_port_id_t JackGraphManager::AllocatePortAux(int refnum, const char* port_na
for (port_index = FIRST_AVAILABLE_PORT; port_index < PORT_NUM; port_index++) {
JackPort* port = GetPort(port_index);
if (!port->IsUsed()) {
JackLog("JackGraphManager::AllocatePortAux port_index = %ld name = %s\n", port_index, port_name);
port->Allocate(refnum, port_name, flags);
JackLog("JackGraphManager::AllocatePortAux port_index = %ld name = %s type = %s\n", port_index, port_name, port_type);
if (!port->Allocate(refnum, port_name, port_type, flags))
return NO_PORT;
break;
}
}
......@@ -284,12 +280,19 @@ jack_port_id_t JackGraphManager::AllocatePortAux(int refnum, const char* port_na
}
// Server
jack_port_id_t JackGraphManager::AllocatePort(int refnum, const char* port_name, JackPortFlags flags)
jack_port_id_t JackGraphManager::AllocatePort(int refnum, const char* port_name, const char* port_type, JackPortFlags flags)
{
JackLock lock(this);
JackConnectionManager* manager = WriteNextStateStart();
jack_port_id_t port_index = AllocatePortAux(refnum, port_name, flags);
jack_port_id_t port_index = AllocatePortAux(refnum, port_name, port_type, flags);
assert(fBufferSize != 0);
if (port_index != NO_PORT) {
JackPort* port = GetPort(port_index);
assert(port);
port->ClearBuffer(fBufferSize);
int res;
if (flags & JackPortIsOutput) {
res = manager->AddOutputPort(refnum, port_index);
......@@ -298,8 +301,6 @@ jack_port_id_t JackGraphManager::AllocatePort(int refnum, const char* port_name,
}
// Insertion failure
if (res < 0) {
JackPort* port = GetPort(port_index);
assert(port);
port->Release();
port_index = NO_PORT;
}
......@@ -309,9 +310,26 @@ jack_port_id_t JackGraphManager::AllocatePort(int refnum, const char* port_name,
return port_index;
}
// Server
void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size)
{
JackLock lock(this);
JackLog("JackGraphManager::SetBufferSize size = %ld\n", (long int)buffer_size);
jack_port_id_t port_index;
fBufferSize = buffer_size;
for (port_index = FIRST_AVAILABLE_PORT; port_index < PORT_NUM; port_index++) {
JackPort* port = GetPort(port_index);
if (port->IsUsed())
port->ClearBuffer(fBufferSize);
}
}
// Server
int JackGraphManager::ReleasePort(int refnum, jack_port_id_t port_index)
{
JackLock lock(this);
JackConnectionManager* manager = WriteNextStateStart();
JackPort* port = GetPort(port_index);
int res;
......@@ -469,18 +487,23 @@ int JackGraphManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
{
JackConnectionManager* manager = WriteNextStateStart();
JackLog("JackGraphManager::Connect port_src = %ld port_dst = %ld\n", port_src, port_dst);
bool in_use_src = GetPort(port_src)->fInUse;
bool in_use_dst = GetPort(port_dst)->fInUse;
JackPort* src = GetPort(port_src);
JackPort* dst = GetPort(port_dst);
int res = 0;
if (!in_use_src || !in_use_dst) {
if (!in_use_src)
if (!src->fInUse || !dst->fInUse) {
if (!src->fInUse)
jack_error("JackGraphManager::Connect: port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName);
if (!in_use_dst)
if (!dst->fInUse)
jack_error("JackGraphManager::Connect: port_dst = %ld not used name = %s", port_dst, GetPort(port_dst)->fName);
res = -1;
goto end;
}
if (src->fTypeId != dst->fTypeId) {
jack_error("JackGraphManager::Connect: different port types: port_src = %ld port_dst = %ld", port_src, port_dst);
res = -1;
goto end;
}
if (manager->IsConnected(port_src, port_dst)) {
jack_error("JackGraphManager::Connect already connected port_src = %ld port_dst = %ld", port_src, port_dst);
res = EEXIST;
......
......@@ -26,6 +26,7 @@ This program is free software; you can redistribute it and/or modify
#include "JackConstants.h"
#include "JackConnectionManager.h"
#include "JackAtomicState.h"
#include "JackMutex.h"
namespace Jack
{
......@@ -34,15 +35,16 @@ namespace Jack
\brief Graph manager: contains the connection manager and the port array.
*/
class JackGraphManager : public JackShmMem, public JackAtomicState<JackConnectionManager>
class JackGraphManager : public JackShmMem, public JackAtomicState<JackConnectionManager>, public JackLockAble
{
private:
JackPort fPortArray[PORT_NUM];
JackClientTiming fClientTiming[CLIENT_NUM];
jack_nframes_t fBufferSize;
jack_port_id_t AllocatePortAux(int refnum, const char* port_name, JackPortFlags flags);
jack_port_id_t AllocatePortAux(int refnum, const char* port_name, const char* port_type, JackPortFlags flags);
void GetConnectionsAux(JackConnectionManager* manager, const char** res, jack_port_id_t port_index);
const char** GetPortsAux(const char* port_name_pattern, const char* type_name_pattern, unsigned long flags);
float* GetBuffer(jack_port_id_t port_index);
......@@ -51,13 +53,15 @@ class JackGraphManager : public JackShmMem, public JackAtomicState<JackConnectio
public:
JackGraphManager()
JackGraphManager() : fBufferSize(0)
{}
virtual ~JackGraphManager()
{}
void SetBufferSize(jack_nframes_t buffer_size);
// Ports management
jack_port_id_t AllocatePort(int refnum, const char* port_name, JackPortFlags flags);
jack_port_id_t AllocatePort(int refnum, const char* port_name, const char* port_type, JackPortFlags flags);
int ReleasePort(int refnum, jack_port_id_t port_index);
void RemoveAllPorts(int refnum);
void DisconnectAllPorts(int refnum);
......
......@@ -72,9 +72,9 @@ class JackInternalClientChannel : public JackClientChannelInterface
*result = fEngine->ClientDeactivate(refnum);
}
void PortRegister(int refnum, const char* name, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result)
void PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result)
{
*result = fEngine->PortRegister(refnum, name, flags, buffer_size, port_index);
*result = fEngine->PortRegister(refnum, name, type, flags, buffer_size, port_index);
}
void PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
{
......
/*
Copyright (C) 2007 Dmitry Baikov
Original JACK MIDI implementation Copyright (C) 2004 Ian Esten
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 "JackError.h"
#include "JackMidiPort.h"
#include "JackExports.h"
#include <errno.h>
#include <string.h>
#ifdef WIN32
#define ENOBUFS 55
#endif
#ifdef __cplusplus
extern "C" {
#endif
EXPORT jack_nframes_t jack_midi_get_event_count(void* port_buffer);
EXPORT int jack_midi_event_get(jack_midi_event_t* event,
void* port_buffer, jack_nframes_t event_index);
EXPORT void jack_midi_clear_buffer(void* port_buffer);
EXPORT size_t jack_midi_max_event_size(void* port_buffer);
EXPORT jack_midi_data_t* jack_midi_event_reserve(void* port_buffer,
jack_nframes_t time, size_t data_size);
EXPORT int jack_midi_event_write(void* port_buffer,
jack_nframes_t time, const jack_midi_data_t* data, size_t data_size);
EXPORT jack_nframes_t jack_midi_get_lost_event_count(void* port_buffer);
#ifdef __cplusplus
}
#endif
using namespace Jack;
EXPORT
jack_nframes_t jack_midi_get_event_count(void* port_buffer)
{
JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
if (!buf || !buf->IsValid())
return 0;
return buf->event_count;
}
EXPORT
int jack_midi_event_get(jack_midi_event_t *event, void* port_buffer, jack_nframes_t event_index)
{
JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
if (!buf || !buf->IsValid())
return -EINVAL;
if (event_index < 0 || event_index >= buf->event_count)
return -ENOBUFS;
JackMidiEvent* ev = &buf->events[event_index];
event->time = ev->time;
event->size = ev->size;
event->buffer = ev->GetData(buf);
return 0;
}
EXPORT
void jack_midi_clear_buffer(void* port_buffer)
{
JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
if (buf && buf->IsValid())
buf->Reset(buf->nframes);
}
EXPORT
size_t jack_midi_max_event_size(void* port_buffer)
{
JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
if (buf && buf->IsValid())
return buf->MaxEventSize();
return 0;
}
EXPORT
jack_midi_data_t* jack_midi_event_reserve(void* port_buffer, jack_nframes_t time, size_t data_size)
{
JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
if (!buf && !buf->IsValid())
return 0;
if (time < 0 || time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time))
return 0;
return buf->ReserveEvent(time, data_size);
}
EXPORT
int jack_midi_event_write(void* port_buffer,
jack_nframes_t time, const jack_midi_data_t* data, size_t data_size)
{
JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
if (!buf && !buf->IsValid())
return -EINVAL;
if (time < 0 || time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time))