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.

343 lines
8.2KB

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