aRts audio server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bus.cc 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. Copyright (C) 1998-2000 Stefan Westerfeld
  3. stefan@space.twc.de
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include "bus.h"
  18. #include "flowsystem.h"
  19. #include "debug.h"
  20. #include <iostream>
  21. #include <set>
  22. #ifdef __SUNPRO_CC
  23. /* SunPRO CC looses to link this when the_BusManager is static, because
  24. later a template implementation file references this symbol. */
  25. #define the_BusManager __internal_aRts_the_BusManager__Bahh__
  26. #else
  27. static
  28. #endif
  29. Arts::BusManager *the_BusManager = 0;
  30. using namespace Arts;
  31. using namespace std;
  32. // shutdown bus manager on termination
  33. namespace Arts {
  34. static class BusManagerShutdown :public StartupClass
  35. {
  36. public:
  37. void startup() { };
  38. void shutdown()
  39. {
  40. if(::the_BusManager)
  41. {
  42. delete ::the_BusManager;
  43. ::the_BusManager = 0;
  44. }
  45. }
  46. } The_BusManagerShutdown;
  47. }
  48. BusManager::BusManager()
  49. {
  50. // this constructor isn't public (Singleton)
  51. }
  52. BusManager *BusManager::the()
  53. {
  54. if(!::the_BusManager) ::the_BusManager = new BusManager;
  55. return(::the_BusManager);
  56. }
  57. BusManager::Bus *BusManager::findBus(const string& name)
  58. {
  59. list<Bus *>::iterator bi;
  60. for(bi = _busList.begin(); bi != _busList.end(); bi++)
  61. {
  62. if((*bi)->name == name) return(*bi);
  63. }
  64. Bus *bus = new Bus;
  65. bus->left.start();
  66. bus->right.start();
  67. bus->name = name;
  68. _busList.push_back(bus);
  69. return(bus);
  70. }
  71. vector<string> *BusManager::busList()
  72. {
  73. set<string> names;
  74. set<string>::iterator si;
  75. list<Bus *>::iterator bi;
  76. for(bi = _busList.begin(); bi != _busList.end(); bi++)
  77. names.insert((*bi)->name);
  78. vector<string> *bl = new vector<string>;
  79. for(si=names.begin();si != names.end();si++) bl->push_back(*si);
  80. return bl;
  81. }
  82. void BusManager::addClient(const string& busname, BusClient *client)
  83. {
  84. Bus *bus = findBus(busname);
  85. bus->clients.push_back(client);
  86. // attach the new client
  87. client->snode()->virtualize("left", bus->left._node(), "invalue");
  88. client->snode()->virtualize("right", bus->right._node(), "invalue");
  89. }
  90. void BusManager::removeClient(BusClient *client)
  91. {
  92. list<Bus *>::iterator bi;
  93. for(bi = _busList.begin(); bi != _busList.end(); bi++)
  94. {
  95. Bus *bus = *bi;
  96. list<BusClient *>::iterator ci;
  97. for(ci = bus->clients.begin(); ci != bus->clients.end(); ci++)
  98. {
  99. if(*ci == client)
  100. {
  101. bus->clients.erase(ci);
  102. if(bus->clients.empty() && bus->servers.empty())
  103. {
  104. _busList.erase(bi);
  105. delete bus;
  106. }
  107. else
  108. {
  109. client->snode()->devirtualize("left",
  110. bus->left._node(), "invalue");
  111. client->snode()->devirtualize("right",
  112. bus->right._node(), "invalue");
  113. }
  114. return;
  115. }
  116. }
  117. }
  118. }
  119. void BusManager::addServer(const string& busname, BusClient *server)
  120. {
  121. Bus *bus = findBus(busname);
  122. bus->servers.push_back(server);
  123. server->snode()->virtualize("left",bus->left._node(),"outvalue");
  124. server->snode()->virtualize("right",bus->right._node(),"outvalue");
  125. }
  126. void BusManager::removeServer(BusClient *server)
  127. {
  128. list<Bus *>::iterator bi;
  129. for(bi = _busList.begin(); bi != _busList.end(); bi++)
  130. {
  131. Bus *bus = *bi;
  132. list<BusClient *>::iterator si;
  133. for(si = bus->servers.begin(); si != bus->servers.end(); si++)
  134. {
  135. if(*si == server)
  136. {
  137. bus->servers.erase(si);
  138. if(bus->clients.empty() && bus->servers.empty())
  139. {
  140. _busList.erase(bi);
  141. delete bus;
  142. }
  143. else
  144. {
  145. server->snode()->devirtualize("left",
  146. bus->left._node(), "outvalue");
  147. server->snode()->devirtualize("right",
  148. bus->right._node(),"outvalue");
  149. }
  150. return;
  151. }
  152. }
  153. }
  154. }
  155. namespace Arts {
  156. class Synth_BUS_UPLINK_impl :public Synth_BUS_UPLINK_skel,
  157. public StdSynthModule, public BusClient
  158. {
  159. BusManager *bm;
  160. bool running, active, relink;
  161. string _busname;
  162. public:
  163. Synth_BUS_UPLINK_impl();
  164. string busname() { return _busname; }
  165. void busname(const string& newname);
  166. AutoSuspendState autoSuspend() { return asSuspend; }
  167. void streamInit();
  168. void streamEnd();
  169. ScheduleNode *snode() { return _node(); }
  170. void CallBack();
  171. void connect();
  172. void disconnect();
  173. };
  174. REGISTER_IMPLEMENTATION(Synth_BUS_UPLINK_impl);
  175. }
  176. Synth_BUS_UPLINK_impl::Synth_BUS_UPLINK_impl() :running(false)
  177. {
  178. bm = BusManager::the();
  179. }
  180. void Synth_BUS_UPLINK_impl::streamInit()
  181. {
  182. assert(!running);
  183. running = true;
  184. active = relink = false;
  185. connect(); // connect to the BusManager
  186. }
  187. void Synth_BUS_UPLINK_impl::busname(const string& newname)
  188. {
  189. _busname = newname;
  190. /* TODO */
  191. // to be sure that reconnection happens when outside the scheduling cycle
  192. if(running)
  193. {
  194. relink = true;
  195. CallBack();
  196. }
  197. }
  198. void Synth_BUS_UPLINK_impl::connect()
  199. {
  200. assert(active == false);
  201. if(!_busname.empty())
  202. {
  203. active = true;
  204. bm->addClient(_busname, this);
  205. }
  206. }
  207. void Synth_BUS_UPLINK_impl::disconnect()
  208. {
  209. if(active == true)
  210. {
  211. bm->removeClient(this);
  212. active = false;
  213. }
  214. }
  215. void Synth_BUS_UPLINK_impl::CallBack()
  216. {
  217. if(relink)
  218. {
  219. disconnect();
  220. connect();
  221. relink = false;
  222. }
  223. }
  224. void Synth_BUS_UPLINK_impl::streamEnd()
  225. {
  226. disconnect();
  227. assert(running);
  228. running = false;
  229. }
  230. namespace Arts {
  231. class Synth_BUS_DOWNLINK_impl :public Synth_BUS_DOWNLINK_skel,
  232. public StdSynthModule, public BusClient
  233. {
  234. bool running, active, relink;
  235. BusManager *bm;
  236. string _busname;
  237. void connect();
  238. void disconnect();
  239. public:
  240. string busname() { return _busname; }
  241. void busname(const string& newname);
  242. Synth_BUS_DOWNLINK_impl();
  243. AutoSuspendState autoSuspend() { return asSuspend; }
  244. void streamInit();
  245. void streamEnd();
  246. void CallBack();
  247. ScheduleNode *snode() { return _node(); }
  248. };
  249. REGISTER_IMPLEMENTATION(Synth_BUS_DOWNLINK_impl);
  250. }
  251. Synth_BUS_DOWNLINK_impl::Synth_BUS_DOWNLINK_impl() :running(false)
  252. {
  253. bm = BusManager::the();
  254. }
  255. void Synth_BUS_DOWNLINK_impl::streamInit()
  256. {
  257. assert(!running);
  258. running = true;
  259. active = relink = false;
  260. connect();
  261. }
  262. void Synth_BUS_DOWNLINK_impl::streamEnd()
  263. {
  264. assert(running);
  265. running = false;
  266. disconnect();
  267. }
  268. void Synth_BUS_DOWNLINK_impl::connect()
  269. {
  270. assert(active == false);
  271. if(!_busname.empty())
  272. {
  273. active = true;
  274. bm->addServer(_busname, this);
  275. }
  276. }
  277. void Synth_BUS_DOWNLINK_impl::disconnect()
  278. {
  279. if(active == true)
  280. {
  281. bm->removeServer(this);
  282. active = false;
  283. }
  284. }
  285. void Synth_BUS_DOWNLINK_impl::CallBack()
  286. {
  287. if(relink)
  288. {
  289. disconnect();
  290. connect();
  291. relink = false;
  292. }
  293. }
  294. void Synth_BUS_DOWNLINK_impl::busname(const string& newname)
  295. {
  296. _busname = newname;
  297. /* TODO */
  298. // to be sure that reconnection happens when outside the scheduling cycle
  299. if(running)
  300. {
  301. relink = true;
  302. CallBack();
  303. }
  304. }