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.

313 lines
7.5KB

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