diff --git a/ChangeLog b/ChangeLog index f9ed740c..1f1b94ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,6 +37,7 @@ Valerio Pilo 2011-03-10 Stephane Letz * Latency callback must always be activated. + * Correct TopologicalSort. 2011-03-09 Stephane Letz diff --git a/common/JackClient.cpp b/common/JackClient.cpp index 986422c0..ae244688 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -319,8 +319,7 @@ int JackClient::HandleLatencyCallback(int status) for (it = fPortList.begin(); it != fPortList.end(); it++) { JackPort* port = GetGraphManager()->GetPort(*it); - - if ((port->GetFlags() & JackPortIsOutput) && (mode == JackPlaybackLatency)) { + if ((port->GetFlags() & JackPortIsOutput) && (mode == JackPlaybackLatency)) { GetGraphManager()->RecalculateLatency(*it, mode); } if ((port->GetFlags() & JackPortIsInput) && (mode == JackCaptureLatency)) { @@ -339,10 +338,8 @@ int JackClient::HandleLatencyCallback(int status) */ for (it = fPortList.begin(); it != fPortList.end(); it++) { JackPort* port = GetGraphManager()->GetPort(*it); - - if (port->GetFlags() & JackPortIsOutput) { + if (port->GetFlags() & JackPortIsOutput) { jack_latency_range_t other_latency; - port->GetLatencyRange(mode, &other_latency); if (other_latency.max > latency.max) latency.max = other_latency.max; @@ -358,8 +355,7 @@ int JackClient::HandleLatencyCallback(int status) */ for (it = fPortList.begin(); it != fPortList.end(); it++) { JackPort* port = GetGraphManager()->GetPort(*it); - - if (port->GetFlags() & JackPortIsInput) { + if (port->GetFlags() & JackPortIsInput) { port->SetLatencyRange(mode, &latency); } } @@ -369,11 +365,9 @@ int JackClient::HandleLatencyCallback(int status) */ for (it = fPortList.begin(); it != fPortList.end(); it++) { JackPort* port = GetGraphManager()->GetPort(*it); - if (port->GetFlags() & JackPortIsInput) { jack_latency_range_t other_latency; - - port->GetLatencyRange(mode, &other_latency); + port->GetLatencyRange(mode, &other_latency); if (other_latency.max > latency.max) latency.max = other_latency.max; if (other_latency.min < latency.min) @@ -388,8 +382,7 @@ int JackClient::HandleLatencyCallback(int status) */ for (it = fPortList.begin(); it != fPortList.end(); it++) { JackPort* port = GetGraphManager()->GetPort(*it); - - if (port->GetFlags() & JackPortIsOutput) { + if (port->GetFlags() & JackPortIsOutput) { port->SetLatencyRange(mode, &latency); } } @@ -1246,9 +1239,9 @@ int JackClient::SessionReply(jack_session_event_t* ev) 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) diff --git a/common/JackConnectionManager.cpp b/common/JackConnectionManager.cpp index fcc3a025..2be93fc9 100644 --- a/common/JackConnectionManager.cpp +++ b/common/JackConnectionManager.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackEngineControl.h" #include "JackGlobals.h" #include "JackError.h" +#include #include #include @@ -272,31 +273,42 @@ int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro* return res; } -void JackConnectionManager::Visit(jack_int_t refnum, bool visited[CLIENT_NUM], std::vector& 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& sorted) { - bool visited[CLIENT_NUM]; - for (int i = 0; i < CLIENT_NUM; i++) { - visited[i] = false; + JackFixedMatrix tmp; + std::set 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); } /*! diff --git a/common/JackConnectionManager.h b/common/JackConnectionManager.h index 7710d035..804ffcc3 100644 --- a/common/JackConnectionManager.h +++ b/common/JackConnectionManager.h @@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackActivationCount.h" #include "JackError.h" #include "JackCompilerDeps.h" - #include #include @@ -201,6 +200,11 @@ class JackFixedMatrix 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. */ @@ -235,6 +239,14 @@ class JackFixedMatrix 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; /*! @@ -383,11 +395,9 @@ struct JackClientTiming
  • The fConnection array contains the list (array line) of connected ports for a given port. -
  • The fConnectionCount array contains the number of connected ports to a given port.
  • The fInputPort array contains the list (array line) of input connected ports for a given client.
  • The fOutputPort array contains the list (array line) of ouput connected ports for a given client.
  • The fConnectionRef array contains the number of ports connected between two clients. -
  • The fInputRef array contains the number of input clients connected to a given client.
  • The fInputCounter array contains the number of input clients connected to a given for activation purpose.
*/ @@ -406,8 +416,6 @@ class SERVER_EXPORT JackConnectionManager bool IsLoopPathAux(int ref1, int ref2) const; - void Visit(jack_int_t refnum, bool visited[CLIENT_NUM], std::vector& res); - public: JackConnectionManager(); diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index 3a86a794..338e5a42 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include +#include #include #include "JackSystemDeps.h" @@ -222,11 +223,11 @@ int JackEngine::ComputeTotalLatencies() */ for (it = sorted.begin(); it != sorted.end(); it++) { - jack_log("ComputeTotalLatencies %d", *it); + jack_log("Sorted %d", *it); 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++) { 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) { uuid = GetNewUUID(); - strncpy( real_name, name, JACK_CLIENT_NAME_SIZE ); + strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); } else { std::map::iterator res = fReservationMap.find(uuid); if (res != fReservationMap.end()) { diff --git a/common/JackGraphManager.cpp b/common/JackGraphManager.cpp index 9276ad87..451d8cce 100644 --- a/common/JackGraphManager.cpp +++ b/common/JackGraphManager.cpp @@ -134,8 +134,8 @@ void JackGraphManager::TopologicalSort(std::vector& sorted) do { cur_index = GetCurrentIndex(); - JackConnectionManager* manager = ReadCurrentState(); - manager->TopologicalSort(sorted); + sorted.clear(); + ReadCurrentState()->TopologicalSort(sorted); next_index = GetCurrentIndex(); } while (cur_index != next_index); // Until a coherent state has been read } diff --git a/common/JackGraphManager.h b/common/JackGraphManager.h index 4f038ba8..5db84209 100644 --- a/common/JackGraphManager.h +++ b/common/JackGraphManager.h @@ -29,7 +29,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackPlatformPlug.h" #include "JackSystemDeps.h" - namespace Jack { diff --git a/common/JackMessageBuffer.cpp b/common/JackMessageBuffer.cpp index b9f28463..d867933d 100644 --- a/common/JackMessageBuffer.cpp +++ b/common/JackMessageBuffer.cpp @@ -2,19 +2,19 @@ * Copyright (C) 2004 Rui Nuno Capela, Steve Harris * Copyright (C) 2008 Nedko Arnaudov * Copyright (C) 2008 Grame - * + * * 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 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * + * * 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. * */ @@ -34,7 +34,7 @@ JackMessageBuffer::JackMessageBuffer() JackMessageBuffer::~JackMessageBuffer() {} - + void JackMessageBuffer::Start() { fRunning = true; @@ -44,9 +44,9 @@ void JackMessageBuffer::Start() void JackMessageBuffer::Stop() { if (fOverruns > 0) { - jack_error("WARNING: %d message buffer overruns!", fOverruns); + jack_error("WARNING: %d message buffer overruns!", fOverruns); } else { - jack_log("no message buffer overruns"); + jack_log("no message buffer overruns"); } fGuard.Lock(); fRunning = false; @@ -55,7 +55,7 @@ void JackMessageBuffer::Stop() fThread.Stop(); Flush(); } - + void JackMessageBuffer::Flush() { while (fOutBuffer != fInBuffer) { @@ -76,7 +76,7 @@ void JackMessageBuffer::AddMessage(int level, const char *message) INC_ATOMIC(&fOverruns); } } - + bool JackMessageBuffer::Execute() { while (fRunning) { @@ -94,10 +94,10 @@ bool JackMessageBuffer::Execute() Flush(); fGuard.Unlock(); } - return false; + return false; } -void JackMessageBuffer::Create() +void JackMessageBuffer::Create() { if (fInstance == NULL) { fInstance = new JackMessageBuffer(); @@ -105,7 +105,7 @@ void JackMessageBuffer::Create() } } -void JackMessageBuffer::Destroy() +void JackMessageBuffer::Destroy() { if (fInstance != NULL) { 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) { /* 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 */ fGuard.Unlock(); } - };