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.

359 lines
8.6KB

  1. /* SpiralSound
  2. * Copyleft (C) 2002 David Griffiths <dave@pawfal.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "ChannelHandler.h"
  19. #include <unistd.h>
  20. using namespace std;
  21. //#define CHANNEL_DEBUG
  22. ChannelHandler::ChannelHandler() :
  23. m_UpdateIndicator(false)
  24. {
  25. m_Mutex = new pthread_mutex_t;
  26. m_Command[0]=0;
  27. m_Command[1]=0;
  28. m_BulkSrc=NULL;
  29. m_BulkSize=0;
  30. m_BulkPos=-1;
  31. pthread_mutex_init(m_Mutex,NULL);
  32. }
  33. ChannelHandler::~ChannelHandler()
  34. {
  35. for(map<string,Channel*>::iterator i=m_ChannelMap.begin();
  36. i!=m_ChannelMap.end(); i++)
  37. {
  38. free(i->second->data_buf);
  39. delete i->second;
  40. }
  41. pthread_mutex_destroy(m_Mutex);
  42. delete m_Mutex;
  43. }
  44. ///////////////////////////////////////////////////////////////
  45. void ChannelHandler::UpdateDataNow()
  46. {
  47. #ifdef CHANNEL_DEBUG
  48. cerr<<"Started update"<<endl;
  49. #endif
  50. // make sure the command is cleared even if
  51. // we can't get a lock on the data
  52. m_Command[0]=0;
  53. if (pthread_mutex_trylock(m_Mutex))
  54. {
  55. #ifdef CHANNEL_DEBUG
  56. cerr<<"Got lock"<<endl;
  57. #endif
  58. m_UpdateIndicator=!m_UpdateIndicator;
  59. for(map<string, Channel*>::iterator i=m_ChannelMap.begin();
  60. i!=m_ChannelMap.end(); i++)
  61. {
  62. Channel *ch = i->second;
  63. switch (ch->type)
  64. {
  65. case INPUT :
  66. {
  67. #ifdef CHANNEL_DEBUG
  68. cerr<<"memcpy input channel: ["<<i->first<<"]"<<endl;
  69. #endif
  70. memcpy(ch->data,ch->data_buf,ch->size);
  71. } break;
  72. case OUTPUT :
  73. {
  74. #ifdef CHANNEL_DEBUG
  75. cerr<<"memcpy output channel: ["<<i->first<<"]"<<endl;
  76. #endif
  77. memcpy(ch->data_buf,ch->data,ch->size);
  78. } break;
  79. // one off request type
  80. case OUTPUT_REQUEST :
  81. {
  82. if (m_BulkPos!=-1 && m_BulkID==i->first)
  83. {
  84. // doing a bulk transfer
  85. if (m_BulkPos+ch->size>m_BulkSize)
  86. {
  87. // last transfer
  88. #ifdef CHANNEL_DEBUG
  89. cerr<<"memcpy (last) bulk output channel: ["<<i->first<<"]"<<endl;
  90. #endif
  91. memcpy(ch->data_buf,((char*)m_BulkSrc)+m_BulkPos,m_BulkSize-m_BulkPos);
  92. m_BulkPos=-1;
  93. }
  94. else
  95. {
  96. #ifdef CHANNEL_DEBUG
  97. cerr<<"memcpy bulk output channel: ["<<i->first<<"]"<<endl;
  98. #endif
  99. memcpy(ch->data_buf,((char*)m_BulkSrc)+m_BulkPos,ch->size);
  100. m_BulkPos+=ch->size;
  101. }
  102. ch->updated=true;
  103. }
  104. else
  105. {
  106. // normal request transfer
  107. if (ch->requested)
  108. {
  109. #ifdef CHANNEL_DEBUG
  110. cerr<<"memcpy output channel: ["<<i->first<<"]"<<endl;
  111. #endif
  112. memcpy(ch->data_buf,ch->data,ch->size);
  113. ch->updated=true;
  114. }
  115. }
  116. } break;
  117. }
  118. }
  119. m_Command[0]=m_Command[1];
  120. // make sure the command only lasts one update
  121. m_Command[1]=0;
  122. pthread_mutex_unlock(m_Mutex);
  123. //cerr<<"audio out mutex"<<endl;
  124. //cerr<<"Update succeeded"<<endl;
  125. }
  126. else
  127. {
  128. //cerr<<"Couldn't get lock"<<endl;
  129. }
  130. #ifdef CHANNEL_DEBUG
  131. cerr<<"Ended update"<<endl;
  132. #endif
  133. }
  134. void ChannelHandler::RegisterData(const string &ID, Type t,void* pData, int size)
  135. {
  136. // probably don't need to lock here, as if get/set are called before
  137. // the channels have been set up they won't work anyway, but...
  138. //pthread_mutex_lock(m_Mutex);
  139. #ifdef CHANNEL_DEBUG
  140. cerr<<"Registering ["<<ID<<"] "<<hex<<pData<<dec<<" as "<<size<<" bytes big"<<endl;
  141. #endif
  142. map<string,Channel*>::iterator i=m_ChannelMap.find(ID);
  143. if (i!=m_ChannelMap.end())
  144. {
  145. cerr<<"Channel with ID ["<<ID<<"] already exists"<<endl;
  146. }
  147. Channel *NewCh=new Channel(t);
  148. NewCh->data_buf = malloc(size);
  149. NewCh->size = size;
  150. NewCh->data = pData;
  151. NewCh->requested = false;
  152. NewCh->updated = false;
  153. memcpy(NewCh->data_buf,NewCh->data,size);
  154. m_ChannelMap[ID]=NewCh;
  155. //pthread_mutex_unlock(m_Mutex);
  156. }
  157. /////////////////////////////////////////////////////////////////////////
  158. void ChannelHandler::GetData(const string &ID, void *data)
  159. {
  160. map<string,Channel*>::iterator i=m_ChannelMap.find(ID);
  161. if (i==m_ChannelMap.end())
  162. {
  163. cerr<<"ChannelHandler: Channel ["<<ID<<"] does not exist"<<endl;
  164. return;
  165. }
  166. if (!data)
  167. {
  168. cerr<<"ChannelHandler: Can't copy data to uninitialised mem"<<endl;
  169. return;
  170. }
  171. pthread_mutex_lock(m_Mutex);
  172. if (i->second->type==OUTPUT || i->second->type==OUTPUT_REQUEST)
  173. {
  174. memcpy(data,i->second->data_buf,i->second->size);
  175. }
  176. else
  177. {
  178. cerr<<"ChannelHandler: Tried to Get() data registered as input"<<endl;
  179. }//cerr<<"unlock 1"<<endl;
  180. pthread_mutex_unlock(m_Mutex);
  181. }
  182. void ChannelHandler::SetData(const string &ID, void *s)
  183. {
  184. map<string,Channel*>::iterator i=m_ChannelMap.find(ID);
  185. if (i==m_ChannelMap.end())
  186. {
  187. cerr<<"ChannelHandler: Channel ["<<ID<<"] does not exist"<<endl;
  188. return;
  189. }
  190. //cerr<<"lock 2"<<endl;
  191. pthread_mutex_lock(m_Mutex);
  192. //cerr<<"lock 2 ok"<<endl;
  193. if (i->second->type==INPUT)
  194. {
  195. memcpy(i->second->data_buf,s,i->second->size);
  196. }
  197. else
  198. {
  199. cerr<<"ChannelHandler: Tried to Set() data registered as output"<<endl;
  200. }//cerr<<"unlock 2"<<endl;
  201. pthread_mutex_unlock(m_Mutex);
  202. }
  203. void ChannelHandler::SetCommand(char command)
  204. {
  205. pthread_mutex_lock(m_Mutex);
  206. m_Command[1]=command;
  207. pthread_mutex_unlock(m_Mutex);
  208. }
  209. void ChannelHandler::FlushChannels()
  210. {
  211. pthread_mutex_lock(m_Mutex);
  212. for(map<string, Channel*>::iterator i=m_ChannelMap.begin();
  213. i!=m_ChannelMap.end(); i++)
  214. {
  215. memcpy(i->second->data_buf,i->second->data,i->second->size);
  216. }
  217. pthread_mutex_unlock(m_Mutex);
  218. }
  219. void ChannelHandler::RequestChannelAndWait(const string &ID)
  220. {
  221. map<string,Channel*>::iterator i=m_ChannelMap.find(ID);
  222. if (i==m_ChannelMap.end())
  223. {
  224. cerr<<"ChannelHandler: Channel ["<<ID<<"] does not exist"<<endl;
  225. return;
  226. }
  227. if (i->second->type!=OUTPUT_REQUEST)
  228. {
  229. cerr<<"ChannelHandler: Trying to request ["<<ID<<"] which is not a requestable channel"<<endl;
  230. return;
  231. }
  232. pthread_mutex_lock(m_Mutex);
  233. i->second->requested=true;
  234. pthread_mutex_unlock(m_Mutex);
  235. bool ready=false;
  236. while (!ready)
  237. {
  238. usleep(10); // random amount of time :)
  239. pthread_mutex_lock(m_Mutex);
  240. ready=i->second->updated;
  241. pthread_mutex_unlock(m_Mutex);
  242. }
  243. pthread_mutex_lock(m_Mutex);
  244. i->second->requested=false;
  245. i->second->updated=false;
  246. pthread_mutex_unlock(m_Mutex);
  247. }
  248. void ChannelHandler::BulkTransfer(const string &ID, void *dest, int size)
  249. {
  250. map<string,Channel*>::iterator i=m_ChannelMap.find(ID);
  251. if (i==m_ChannelMap.end())
  252. {
  253. cerr<<"ChannelHandler: Channel ["<<ID<<"] does not exist"<<endl;
  254. return;
  255. }
  256. if (i->second->type!=OUTPUT_REQUEST)
  257. {
  258. cerr<<"ChannelHandler: Trying to bulk transfer on ["<<ID<<"] which is not a OUTPUT_REQUEST channel"<<endl;
  259. return;
  260. }
  261. m_BulkPos=0;
  262. m_BulkSize = size;
  263. m_BulkID = ID;
  264. int pos=0;
  265. int buffersize=i->second->size;
  266. // fill up the destination buffer
  267. while (m_BulkPos!=-1)
  268. {
  269. RequestChannelAndWait(ID);
  270. if (pos+buffersize>size)
  271. {
  272. // last copy
  273. char *tempbuf = (char*)malloc(buffersize);
  274. GetData(ID,(void*)tempbuf);
  275. memcpy(((char*)dest)+pos,(void*)tempbuf,size-pos);
  276. free(tempbuf);
  277. }
  278. else
  279. {
  280. GetData(ID,((char*)dest)+pos);
  281. }
  282. pos+=buffersize;
  283. }
  284. }
  285. void ChannelHandler::Wait()
  286. {
  287. pthread_mutex_lock(m_Mutex);
  288. bool current=m_UpdateIndicator;
  289. bool last=m_UpdateIndicator;
  290. pthread_mutex_unlock(m_Mutex);
  291. while (current==last)
  292. {
  293. usleep(10);
  294. pthread_mutex_lock(m_Mutex);
  295. current=m_UpdateIndicator;
  296. pthread_mutex_unlock(m_Mutex);
  297. }
  298. // do this twice (messages have to get there and back?)
  299. pthread_mutex_lock(m_Mutex);
  300. current=m_UpdateIndicator;
  301. last=m_UpdateIndicator;
  302. pthread_mutex_unlock(m_Mutex);
  303. while (current==last)
  304. {
  305. usleep(10);
  306. pthread_mutex_lock(m_Mutex);
  307. current=m_UpdateIndicator;
  308. pthread_mutex_unlock(m_Mutex);
  309. }
  310. }