git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4169 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.7
| @@ -37,6 +37,7 @@ Valerio Pilo | |||||
| 2011-03-10 Stephane Letz <letz@grame.fr> | 2011-03-10 Stephane Letz <letz@grame.fr> | ||||
| * Latency callback must always be activated. | * Latency callback must always be activated. | ||||
| * Correct TopologicalSort. | |||||
| 2011-03-09 Stephane Letz <letz@grame.fr> | 2011-03-09 Stephane Letz <letz@grame.fr> | ||||
| @@ -319,8 +319,7 @@ int JackClient::HandleLatencyCallback(int status) | |||||
| for (it = fPortList.begin(); it != fPortList.end(); it++) { | for (it = fPortList.begin(); it != fPortList.end(); it++) { | ||||
| JackPort* port = GetGraphManager()->GetPort(*it); | JackPort* port = GetGraphManager()->GetPort(*it); | ||||
| if ((port->GetFlags() & JackPortIsOutput) && (mode == JackPlaybackLatency)) { | |||||
| if ((port->GetFlags() & JackPortIsOutput) && (mode == JackPlaybackLatency)) { | |||||
| GetGraphManager()->RecalculateLatency(*it, mode); | GetGraphManager()->RecalculateLatency(*it, mode); | ||||
| } | } | ||||
| if ((port->GetFlags() & JackPortIsInput) && (mode == JackCaptureLatency)) { | if ((port->GetFlags() & JackPortIsInput) && (mode == JackCaptureLatency)) { | ||||
| @@ -339,10 +338,8 @@ int JackClient::HandleLatencyCallback(int status) | |||||
| */ | */ | ||||
| for (it = fPortList.begin(); it != fPortList.end(); it++) { | for (it = fPortList.begin(); it != fPortList.end(); it++) { | ||||
| JackPort* port = GetGraphManager()->GetPort(*it); | JackPort* port = GetGraphManager()->GetPort(*it); | ||||
| if (port->GetFlags() & JackPortIsOutput) { | |||||
| if (port->GetFlags() & JackPortIsOutput) { | |||||
| jack_latency_range_t other_latency; | jack_latency_range_t other_latency; | ||||
| port->GetLatencyRange(mode, &other_latency); | port->GetLatencyRange(mode, &other_latency); | ||||
| if (other_latency.max > latency.max) | if (other_latency.max > latency.max) | ||||
| latency.max = other_latency.max; | latency.max = other_latency.max; | ||||
| @@ -358,8 +355,7 @@ int JackClient::HandleLatencyCallback(int status) | |||||
| */ | */ | ||||
| for (it = fPortList.begin(); it != fPortList.end(); it++) { | for (it = fPortList.begin(); it != fPortList.end(); it++) { | ||||
| JackPort* port = GetGraphManager()->GetPort(*it); | JackPort* port = GetGraphManager()->GetPort(*it); | ||||
| if (port->GetFlags() & JackPortIsInput) { | |||||
| if (port->GetFlags() & JackPortIsInput) { | |||||
| port->SetLatencyRange(mode, &latency); | port->SetLatencyRange(mode, &latency); | ||||
| } | } | ||||
| } | } | ||||
| @@ -369,11 +365,9 @@ int JackClient::HandleLatencyCallback(int status) | |||||
| */ | */ | ||||
| for (it = fPortList.begin(); it != fPortList.end(); it++) { | for (it = fPortList.begin(); it != fPortList.end(); it++) { | ||||
| JackPort* port = GetGraphManager()->GetPort(*it); | JackPort* port = GetGraphManager()->GetPort(*it); | ||||
| if (port->GetFlags() & JackPortIsInput) { | if (port->GetFlags() & JackPortIsInput) { | ||||
| jack_latency_range_t other_latency; | jack_latency_range_t other_latency; | ||||
| port->GetLatencyRange(mode, &other_latency); | |||||
| port->GetLatencyRange(mode, &other_latency); | |||||
| if (other_latency.max > latency.max) | if (other_latency.max > latency.max) | ||||
| latency.max = other_latency.max; | latency.max = other_latency.max; | ||||
| if (other_latency.min < latency.min) | if (other_latency.min < latency.min) | ||||
| @@ -388,8 +382,7 @@ int JackClient::HandleLatencyCallback(int status) | |||||
| */ | */ | ||||
| for (it = fPortList.begin(); it != fPortList.end(); it++) { | for (it = fPortList.begin(); it != fPortList.end(); it++) { | ||||
| JackPort* port = GetGraphManager()->GetPort(*it); | JackPort* port = GetGraphManager()->GetPort(*it); | ||||
| if (port->GetFlags() & JackPortIsOutput) { | |||||
| if (port->GetFlags() & JackPortIsOutput) { | |||||
| port->SetLatencyRange(mode, &latency); | port->SetLatencyRange(mode, &latency); | ||||
| } | } | ||||
| } | } | ||||
| @@ -1246,9 +1239,9 @@ int JackClient::SessionReply(jack_session_event_t* ev) | |||||
| jack_log("JackClient::SessionReply... out of cb"); | jack_log("JackClient::SessionReply... out of cb"); | ||||
| int res; | |||||
| fChannel->SessionReply(GetClientControl()->fRefNum, &res); | |||||
| return res; | |||||
| int result = -1; | |||||
| fChannel->SessionReply(GetClientControl()->fRefNum, &result); | |||||
| return result; | |||||
| } | } | ||||
| char* JackClient::GetUUIDForClientName(const char* client_name) | char* JackClient::GetUUIDForClientName(const char* client_name) | ||||
| @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #include "JackEngineControl.h" | #include "JackEngineControl.h" | ||||
| #include "JackGlobals.h" | #include "JackGlobals.h" | ||||
| #include "JackError.h" | #include "JackError.h" | ||||
| #include <set> | |||||
| #include <iostream> | #include <iostream> | ||||
| #include <assert.h> | #include <assert.h> | ||||
| @@ -272,31 +273,42 @@ int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro* | |||||
| return res; | return res; | ||||
| } | } | ||||
| void JackConnectionManager::Visit(jack_int_t refnum, bool visited[CLIENT_NUM], std::vector<jack_int_t>& res) | |||||
| static bool HasNoConnection(jack_int_t* table) | |||||
| { | { | ||||
| if (!visited[refnum]) { | |||||
| visited[refnum] = true; | |||||
| jack_int_t output_ref[CLIENT_NUM]; | |||||
| fConnectionRef.GetOutputTable1(refnum, output_ref); | |||||
| //const jack_int_t* output_ref = fConnectionRef.GetItems(refnum); | |||||
| for (int i = 0; i < CLIENT_NUM; i++) { | |||||
| if (output_ref[i] > 0) | |||||
| Visit(i, visited, res); | |||||
| } | |||||
| res.push_back(refnum); | |||||
| for (int ref = 0; ref < CLIENT_NUM; ref++) { | |||||
| if (table[ref] > 0) return false; | |||||
| } | } | ||||
| return true; | |||||
| } | } | ||||
| // Using http://en.wikipedia.org/wiki/Topological_sorting | |||||
| void JackConnectionManager::TopologicalSort(std::vector<jack_int_t>& sorted) | void JackConnectionManager::TopologicalSort(std::vector<jack_int_t>& sorted) | ||||
| { | { | ||||
| bool visited[CLIENT_NUM]; | |||||
| for (int i = 0; i < CLIENT_NUM; i++) { | |||||
| visited[i] = false; | |||||
| JackFixedMatrix<CLIENT_NUM> tmp; | |||||
| std::set<jack_int_t> level; | |||||
| fConnectionRef.Copy(tmp); | |||||
| // Inputs of the graph | |||||
| level.insert(AUDIO_DRIVER_REFNUM); | |||||
| level.insert(FREEWHEEL_DRIVER_REFNUM); | |||||
| while (level.size() > 0) { | |||||
| jack_int_t refnum = *level.begin(); | |||||
| sorted.push_back(refnum); | |||||
| level.erase(level.begin()); | |||||
| const jack_int_t* output_ref1 = tmp.GetItems(refnum); | |||||
| for (int dst = 0; dst < CLIENT_NUM; dst++) { | |||||
| if (output_ref1[dst] > 0) { | |||||
| tmp.ClearItem(refnum, dst); | |||||
| jack_int_t output_ref2[CLIENT_NUM]; | |||||
| tmp.GetOutputTable1(dst, output_ref2); | |||||
| if (HasNoConnection(output_ref2)) | |||||
| level.insert(dst); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| Visit(AUDIO_DRIVER_REFNUM, visited, sorted); | |||||
| Visit(FREEWHEEL_DRIVER_REFNUM, visited, sorted); | |||||
| } | } | ||||
| /*! | /*! | ||||
| @@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #include "JackActivationCount.h" | #include "JackActivationCount.h" | ||||
| #include "JackError.h" | #include "JackError.h" | ||||
| #include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
| #include <vector> | #include <vector> | ||||
| #include <assert.h> | #include <assert.h> | ||||
| @@ -201,6 +200,11 @@ class JackFixedMatrix | |||||
| return fTable[index1][index2]; | return fTable[index1][index2]; | ||||
| } | } | ||||
| void ClearItem(jack_int_t index1, jack_int_t index2) | |||||
| { | |||||
| fTable[index1][index2] = 0; | |||||
| } | |||||
| /*! | /*! | ||||
| \brief Get the output indexes of a given index. | \brief Get the output indexes of a given index. | ||||
| */ | */ | ||||
| @@ -235,6 +239,14 @@ class JackFixedMatrix | |||||
| return false; | return false; | ||||
| } | } | ||||
| void Copy(JackFixedMatrix& copy) | |||||
| { | |||||
| for (int i = 0; i < SIZE; i++) { | |||||
| memcpy(copy.fTable[i], fTable[i], sizeof(jack_int_t) * SIZE); | |||||
| } | |||||
| } | |||||
| } POST_PACKED_STRUCTURE; | } POST_PACKED_STRUCTURE; | ||||
| /*! | /*! | ||||
| @@ -383,11 +395,9 @@ struct JackClientTiming | |||||
| <UL> | <UL> | ||||
| <LI>The <B>fConnection</B> array contains the list (array line) of connected ports for a given port. | <LI>The <B>fConnection</B> array contains the list (array line) of connected ports for a given port. | ||||
| <LI>The <B>fConnectionCount</B> array contains the number of connected ports to a given port. | |||||
| <LI>The <B>fInputPort</B> array contains the list (array line) of input connected ports for a given client. | <LI>The <B>fInputPort</B> array contains the list (array line) of input connected ports for a given client. | ||||
| <LI>The <B>fOutputPort</B> array contains the list (array line) of ouput connected ports for a given client. | <LI>The <B>fOutputPort</B> array contains the list (array line) of ouput connected ports for a given client. | ||||
| <LI>The <B>fConnectionRef</B> array contains the number of ports connected between two clients. | <LI>The <B>fConnectionRef</B> array contains the number of ports connected between two clients. | ||||
| <LI>The <B>fInputRef</B> array contains the number of input clients connected to a given client. | |||||
| <LI>The <B>fInputCounter</B> array contains the number of input clients connected to a given for activation purpose. | <LI>The <B>fInputCounter</B> array contains the number of input clients connected to a given for activation purpose. | ||||
| </UL> | </UL> | ||||
| */ | */ | ||||
| @@ -406,8 +416,6 @@ class SERVER_EXPORT JackConnectionManager | |||||
| bool IsLoopPathAux(int ref1, int ref2) const; | bool IsLoopPathAux(int ref1, int ref2) const; | ||||
| void Visit(jack_int_t refnum, bool visited[CLIENT_NUM], std::vector<jack_int_t>& res); | |||||
| public: | public: | ||||
| JackConnectionManager(); | JackConnectionManager(); | ||||
| @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| #include <iostream> | #include <iostream> | ||||
| #include <fstream> | #include <fstream> | ||||
| #include <set> | |||||
| #include <assert.h> | #include <assert.h> | ||||
| #include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
| @@ -222,11 +223,11 @@ int JackEngine::ComputeTotalLatencies() | |||||
| */ | */ | ||||
| for (it = sorted.begin(); it != sorted.end(); it++) { | for (it = sorted.begin(); it != sorted.end(); it++) { | ||||
| jack_log("ComputeTotalLatencies %d", *it); | |||||
| jack_log("Sorted %d", *it); | |||||
| NotifyClient(*it, kLatencyCallback, true, "", 0, 0); | NotifyClient(*it, kLatencyCallback, true, "", 0, 0); | ||||
| } | } | ||||
| /* now issue playback latency callbacks in reverse graph order | |||||
| /* now issue playback latency callbacks in reverse graph order. | |||||
| */ | */ | ||||
| for (rit = sorted.rbegin(); rit != sorted.rend(); rit++) { | for (rit = sorted.rbegin(); rit != sorted.rend(); rit++) { | ||||
| NotifyClient(*rit, kLatencyCallback, true, "", 1, 0); | NotifyClient(*rit, kLatencyCallback, true, "", 1, 0); | ||||
| @@ -554,7 +555,7 @@ int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref | |||||
| if (uuid < 0) { | if (uuid < 0) { | ||||
| uuid = GetNewUUID(); | uuid = GetNewUUID(); | ||||
| strncpy( real_name, name, JACK_CLIENT_NAME_SIZE ); | |||||
| strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); | |||||
| } else { | } else { | ||||
| std::map<int,std::string>::iterator res = fReservationMap.find(uuid); | std::map<int,std::string>::iterator res = fReservationMap.find(uuid); | ||||
| if (res != fReservationMap.end()) { | if (res != fReservationMap.end()) { | ||||
| @@ -134,8 +134,8 @@ void JackGraphManager::TopologicalSort(std::vector<jack_int_t>& sorted) | |||||
| do { | do { | ||||
| cur_index = GetCurrentIndex(); | cur_index = GetCurrentIndex(); | ||||
| JackConnectionManager* manager = ReadCurrentState(); | |||||
| manager->TopologicalSort(sorted); | |||||
| sorted.clear(); | |||||
| ReadCurrentState()->TopologicalSort(sorted); | |||||
| next_index = GetCurrentIndex(); | next_index = GetCurrentIndex(); | ||||
| } while (cur_index != next_index); // Until a coherent state has been read | } while (cur_index != next_index); // Until a coherent state has been read | ||||
| } | } | ||||
| @@ -29,7 +29,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
| #include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| @@ -2,19 +2,19 @@ | |||||
| * Copyright (C) 2004 Rui Nuno Capela, Steve Harris | * Copyright (C) 2004 Rui Nuno Capela, Steve Harris | ||||
| * Copyright (C) 2008 Nedko Arnaudov | * Copyright (C) 2008 Nedko Arnaudov | ||||
| * Copyright (C) 2008 Grame | * Copyright (C) 2008 Grame | ||||
| * | |||||
| * | |||||
| * This program is free software; you can redistribute it and/or modify | * This program is free software; you can redistribute it and/or modify | ||||
| * it under the terms of the GNU Lesser General Public License as published by | * it under the terms of the GNU Lesser General Public License as published by | ||||
| * the Free Software Foundation; either version 2.1 of the License, or | * the Free Software Foundation; either version 2.1 of the License, or | ||||
| * (at your option) any later version. | * (at your option) any later version. | ||||
| * | |||||
| * | |||||
| * This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | ||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| * GNU Lesser General Public License for more details. | * GNU Lesser General Public License for more details. | ||||
| * | |||||
| * | |||||
| * You should have received a copy of the GNU Lesser General Public License | * You should have received a copy of the GNU Lesser General Public License | ||||
| * along with this program; if not, write to the Free Software | |||||
| * along with this program; if not, write to the Free Software | |||||
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
| * | * | ||||
| */ | */ | ||||
| @@ -34,7 +34,7 @@ JackMessageBuffer::JackMessageBuffer() | |||||
| JackMessageBuffer::~JackMessageBuffer() | JackMessageBuffer::~JackMessageBuffer() | ||||
| {} | {} | ||||
| void JackMessageBuffer::Start() | void JackMessageBuffer::Start() | ||||
| { | { | ||||
| fRunning = true; | fRunning = true; | ||||
| @@ -44,9 +44,9 @@ void JackMessageBuffer::Start() | |||||
| void JackMessageBuffer::Stop() | void JackMessageBuffer::Stop() | ||||
| { | { | ||||
| if (fOverruns > 0) { | if (fOverruns > 0) { | ||||
| jack_error("WARNING: %d message buffer overruns!", fOverruns); | |||||
| jack_error("WARNING: %d message buffer overruns!", fOverruns); | |||||
| } else { | } else { | ||||
| jack_log("no message buffer overruns"); | |||||
| jack_log("no message buffer overruns"); | |||||
| } | } | ||||
| fGuard.Lock(); | fGuard.Lock(); | ||||
| fRunning = false; | fRunning = false; | ||||
| @@ -55,7 +55,7 @@ void JackMessageBuffer::Stop() | |||||
| fThread.Stop(); | fThread.Stop(); | ||||
| Flush(); | Flush(); | ||||
| } | } | ||||
| void JackMessageBuffer::Flush() | void JackMessageBuffer::Flush() | ||||
| { | { | ||||
| while (fOutBuffer != fInBuffer) { | while (fOutBuffer != fInBuffer) { | ||||
| @@ -76,7 +76,7 @@ void JackMessageBuffer::AddMessage(int level, const char *message) | |||||
| INC_ATOMIC(&fOverruns); | INC_ATOMIC(&fOverruns); | ||||
| } | } | ||||
| } | } | ||||
| bool JackMessageBuffer::Execute() | bool JackMessageBuffer::Execute() | ||||
| { | { | ||||
| while (fRunning) { | while (fRunning) { | ||||
| @@ -94,10 +94,10 @@ bool JackMessageBuffer::Execute() | |||||
| Flush(); | Flush(); | ||||
| fGuard.Unlock(); | fGuard.Unlock(); | ||||
| } | } | ||||
| return false; | |||||
| return false; | |||||
| } | } | ||||
| void JackMessageBuffer::Create() | |||||
| void JackMessageBuffer::Create() | |||||
| { | { | ||||
| if (fInstance == NULL) { | if (fInstance == NULL) { | ||||
| fInstance = new JackMessageBuffer(); | fInstance = new JackMessageBuffer(); | ||||
| @@ -105,7 +105,7 @@ void JackMessageBuffer::Create() | |||||
| } | } | ||||
| } | } | ||||
| void JackMessageBuffer::Destroy() | |||||
| void JackMessageBuffer::Destroy() | |||||
| { | { | ||||
| if (fInstance != NULL) { | if (fInstance != NULL) { | ||||
| fInstance->Stop(); | fInstance->Stop(); | ||||
| @@ -114,7 +114,7 @@ void JackMessageBuffer::Destroy() | |||||
| } | } | ||||
| } | } | ||||
| void JackMessageBufferAdd(int level, const char *message) | |||||
| void JackMessageBufferAdd(int level, const char *message) | |||||
| { | { | ||||
| if (Jack::JackMessageBuffer::fInstance == NULL) { | if (Jack::JackMessageBuffer::fInstance == NULL) { | ||||
| /* Unable to print message with realtime safety. Complain and print it anyway. */ | /* Unable to print message with realtime safety. Complain and print it anyway. */ | ||||
| @@ -137,7 +137,6 @@ void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *a | |||||
| /* and we're done */ | /* and we're done */ | ||||
| fGuard.Unlock(); | fGuard.Unlock(); | ||||
| } | } | ||||
| }; | }; | ||||