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> | |||
| * Latency callback must always be activated. | |||
| * Correct TopologicalSort. | |||
| 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++) { | |||
| 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) | |||
| @@ -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 <set> | |||
| #include <iostream> | |||
| #include <assert.h> | |||
| @@ -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<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) | |||
| { | |||
| 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 "JackError.h" | |||
| #include "JackCompilerDeps.h" | |||
| #include <vector> | |||
| #include <assert.h> | |||
| @@ -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 | |||
| <UL> | |||
| <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>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>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. | |||
| </UL> | |||
| */ | |||
| @@ -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<jack_int_t>& res); | |||
| public: | |||
| JackConnectionManager(); | |||
| @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include <iostream> | |||
| #include <fstream> | |||
| #include <set> | |||
| #include <assert.h> | |||
| #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<int,std::string>::iterator res = fReservationMap.find(uuid); | |||
| if (res != fReservationMap.end()) { | |||
| @@ -134,8 +134,8 @@ void JackGraphManager::TopologicalSort(std::vector<jack_int_t>& 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 | |||
| } | |||
| @@ -29,7 +29,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include "JackPlatformPlug.h" | |||
| #include "JackSystemDeps.h" | |||
| namespace Jack | |||
| { | |||
| @@ -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(); | |||
| } | |||
| }; | |||