PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/esound-0.2.41/players.c

#
C | 677 lines | 451 code | 124 blank | 102 comment | 112 complexity | 452a42d2f95d6176db39da0a430a3275 MD5 | raw file
Possible License(s): LGPL-2.0
  1. #include "esd-server.h"
  2. #include <errno.h>
  3. /*******************************************************************/
  4. /* globals */
  5. esd_player_t *esd_players_list = NULL;
  6. esd_player_t *esd_recorder_list = NULL;
  7. esd_player_t *esd_monitor_list = NULL;
  8. /*******************************************************************/
  9. /* for debugging purposes, dump the list of the clients and data */
  10. void dump_players(void)
  11. {
  12. esd_player_t *player = esd_players_list;
  13. if ( !esdbg_trace ) return;
  14. while ( player != NULL ) {
  15. printf( "-%02d- player: [%p]\n",
  16. player->source_id, player );
  17. player = player->next;
  18. }
  19. return;
  20. }
  21. /*******************************************************************/
  22. /* deallocate memory for the player */
  23. void free_player( esd_player_t *player )
  24. {
  25. esd_sample_t *sample;
  26. /* see if we need to do any housekeeping */
  27. if ( ( player->format & ESD_MASK_MODE ) == ESD_STREAM ) {
  28. /* TODO: erase client should be independent of players */
  29. erase_client( player->parent );
  30. } else if ( ( player->format & ESD_MASK_MODE ) == ESD_SAMPLE ) {
  31. sample = (esd_sample_t *) (player->parent);
  32. sample->ref_count--;
  33. esd_playing_samples--;
  34. ESDBG_TRACE( printf( "<%02d> free player: [%p] refs=%d erase?=%d samps=%d\n",
  35. player->source_id, player, sample->ref_count,
  36. sample->erase_when_done, esd_playing_samples ); );
  37. if ( sample->erase_when_done && !sample->ref_count ) {
  38. ESDBG_TRACE( printf( "<%02d> free_player: erasing sample\n",
  39. sample->sample_id ); );
  40. erase_sample( sample->sample_id, 0 );
  41. }
  42. }
  43. /* free any memory allocated with the player */
  44. free( player->data_buffer );
  45. /* free the player memory itself */
  46. free( player );
  47. return;
  48. }
  49. /*******************************************************************/
  50. /* add a complete new player into the list of players at head */
  51. void add_player( esd_player_t *player )
  52. {
  53. /* printf ( "adding player %p\n", new_player ); */
  54. if ( !player ) {
  55. ESDBG_TRACE( printf( "<NIL> can't add non-existent player!\n" ); );
  56. return;
  57. }
  58. player->next = esd_players_list;
  59. esd_players_list = player;
  60. return;
  61. }
  62. /*******************************************************************/
  63. /* erase a player from the player list */
  64. void erase_player( esd_player_t *player )
  65. {
  66. esd_player_t *previous = NULL;
  67. esd_player_t *current = esd_players_list;
  68. /* iterate until we hit a NULL */
  69. while ( current != NULL )
  70. {
  71. /* see if we hit the target player */
  72. if ( current == player ) {
  73. if( previous != NULL ){
  74. /* we are deleting in the middle of the list */
  75. previous->next = current->next;
  76. } else {
  77. /* we are deleting the head of the list */
  78. esd_players_list = current->next;
  79. }
  80. /* TODO: delete if needed */
  81. free_player( player );
  82. return;
  83. }
  84. /* iterate through the list */
  85. previous = current;
  86. current = current->next;
  87. }
  88. /* hmm, we didn't find the desired player, just get on with life */
  89. ESDBG_TRACE( printf( "-%02d- player not found\n", player->source_id ); );
  90. return;
  91. }
  92. /*******************************************************************/
  93. /* add a complete new recorder into the list of recorders at head */
  94. void add_recorder( esd_player_t *recorder )
  95. {
  96. /* printf ( "adding player %p\n", new_player ); */
  97. if ( !recorder ) {
  98. ESDBG_TRACE( printf( "<NIL> can't add non-existent recorder!\n" ); );
  99. return;
  100. }
  101. recorder->next = esd_recorder_list;
  102. esd_recorder_list = recorder;
  103. return;
  104. }
  105. /*******************************************************************/
  106. /* erase a recorder from the recorder list */
  107. void erase_recorder( esd_player_t *recorder )
  108. {
  109. esd_player_t **prevp = &esd_recorder_list;
  110. esd_player_t *current = esd_recorder_list;
  111. /* iterate until we hit a NULL */
  112. while ( current != NULL )
  113. {
  114. /* see if we hit the target player */
  115. if ( current == recorder ) {
  116. *prevp = current->next;
  117. /* TODO: delete if needed */
  118. free_player( recorder );
  119. return;
  120. }
  121. /* iterate through the list */
  122. prevp = &current->next;
  123. current = current->next;
  124. }
  125. /* hmm, we didn't find the desired recorder, just get on with life */
  126. ESDBG_TRACE( printf( "-%02d- recorder not found\n", recorder->source_id ); );
  127. return;
  128. }
  129. /*******************************************************************/
  130. /* erase a monitor from the monitor list */
  131. void erase_monitor( esd_player_t *monitor )
  132. {
  133. esd_player_t *previous = NULL;
  134. esd_player_t *current = esd_monitor_list;
  135. /* iterate until we hit a NULL */
  136. while ( current != NULL )
  137. {
  138. /* see if we hit the target monitor */
  139. if ( current == monitor ) {
  140. if( previous != NULL ){
  141. /* we are deleting in the middle of the list */
  142. previous->next = current->next;
  143. } else {
  144. /* we are deleting the head of the list */
  145. esd_monitor_list = current->next;
  146. }
  147. /* TODO: delete if needed */
  148. free_player( monitor );
  149. return;
  150. }
  151. /* iterate through the list */
  152. previous = current;
  153. current = current->next;
  154. }
  155. /* hmm, we didn't find the desired monitor, just get on with life */
  156. ESDBG_TRACE( printf( "-%02d- monitor not found\n", monitor->source_id ); );
  157. return;
  158. }
  159. /*******************************************************************/
  160. /* write block of data from client, return < 0 to have it erased */
  161. int write_player( esd_player_t *player, void *src_buffer, int src_length,
  162. int src_rate, int src_format )
  163. {
  164. fd_set wr_fds;
  165. fd_set rd_fds;
  166. int length = 0, actual = 0, ready = 0;
  167. struct timeval timeout;
  168. char message[ 100 ];
  169. unsigned short data, *pos; /* used for swapping */
  170. esd_client_t *client;
  171. unsigned short *buffer;
  172. /* use select to prevent blocking clients that are ready */
  173. timeout.tv_sec = 0;
  174. timeout.tv_usec = 0;
  175. FD_ZERO( &wr_fds );
  176. FD_ZERO( &rd_fds );
  177. FD_SET( player->source_id, &wr_fds );
  178. /* EOF is only indicated in the read set */
  179. FD_SET( player->source_id, &rd_fds );
  180. /* if the data is ready, read a block */
  181. ready = select( player->source_id + 1,
  182. &rd_fds, &wr_fds, NULL, &timeout ) ;
  183. if ( ready > 0 )
  184. {
  185. char ch;
  186. if ( FD_ISSET(player->source_id, &rd_fds)
  187. && (recv(player->source_id, &ch, 1, MSG_PEEK) < 1) ) {
  188. /* Error or EOF */
  189. return -1;
  190. }
  191. /* translate the data */
  192. length = player->translate_func( player->data_buffer,
  193. player->buffer_length,
  194. player->rate,
  195. player->format,
  196. src_buffer,
  197. src_length,
  198. src_rate,
  199. src_format );
  200. /* endian swap multi-byte data if we need to */
  201. client = (esd_client_t *) (player->parent);
  202. if ( client->swap_byte_order
  203. && ( (player->format & ESD_MASK_BITS) == ESD_BITS16 ) )
  204. {
  205. buffer = (unsigned short*) player->data_buffer;
  206. for ( pos = buffer
  207. ; pos < buffer + length / sizeof(unsigned short)
  208. ; pos ++ )
  209. {
  210. data = swap_endian_16( (*pos) );
  211. *pos = data;
  212. }
  213. }
  214. /* write out the data */
  215. ESD_WRITE_BIN( player->source_id, player->data_buffer,
  216. player->buffer_length, length, "str rd" );
  217. } else if ( ready < 0 ) {
  218. sprintf( message, "error writing client (%d)\n",
  219. player->source_id );
  220. perror( message );
  221. return -1;
  222. }
  223. /* check for end of stream */
  224. if ( length < 0 ) return -1;
  225. if ( length == 0 ) return 0;
  226. return actual;
  227. }
  228. /*******************************************************************/
  229. /* read block of data from client, return < 0 to have it erased */
  230. int read_player( esd_player_t *player )
  231. {
  232. fd_set rd_fds;
  233. int actual = 0, actual_2nd = 0, can_read = 0;
  234. struct timeval timeout;
  235. char message[ 100 ];
  236. unsigned short data, *pos; /* used for swapping */
  237. esd_client_t *client;
  238. unsigned short *buffer;
  239. switch( player->format & ESD_MASK_MODE ) {
  240. case ESD_STREAM:
  241. /* use select to prevent blocking clients that are ready */
  242. timeout.tv_sec = 0;
  243. timeout.tv_usec = 0;
  244. FD_ZERO( &rd_fds );
  245. FD_SET( player->source_id, &rd_fds );
  246. /* if the data is ready, read a block */
  247. can_read = (( player->actual_length < player->buffer_length ) &&
  248. select( player->source_id + 1, &rd_fds, NULL, NULL, &timeout ));
  249. if ( can_read > 0 )
  250. {
  251. ESD_READ_BIN( player->source_id,
  252. player->data_buffer + player->actual_length,
  253. player->buffer_length - player->actual_length,
  254. actual, "str rd" );
  255. /* check for end of stream */
  256. if ( actual == 0
  257. || ( actual < 0 && errno != EAGAIN && errno != EINTR ) )
  258. return -1;
  259. if (actual < player->buffer_length - player->actual_length)
  260. break;
  261. /* endian swap multi-byte data if we need to */
  262. client = (esd_client_t *) (player->parent);
  263. if ( client->swap_byte_order
  264. && ( (player->format & ESD_MASK_BITS) == ESD_BITS16 ) )
  265. {
  266. buffer = (unsigned short*) player->data_buffer+player->actual_length;
  267. for ( pos = buffer
  268. ; pos < buffer + actual / sizeof(short)
  269. ; pos ++ )
  270. {
  271. data = swap_endian_16( (*pos) );
  272. *pos = data;
  273. }
  274. }
  275. /* more data, save how much we got */
  276. player->actual_length += actual;
  277. } else if ( can_read < 0 ) {
  278. sprintf( message, "error reading client (%d)\n",
  279. player->source_id );
  280. perror( message );
  281. return -1;
  282. }
  283. break;
  284. case ESD_SAMPLE:
  285. /* printf( "player [%p], pos = %d, format = 0x%08x\n",
  286. player, player->last_pos, player->format ); */
  287. /* only keep going if we didn't want to stop looping */
  288. if ( ( player->last_pos ) == 0 &&
  289. ( ( ((esd_sample_t*)player->parent)->format & ESD_MASK_FUNC )
  290. == ESD_STOP ) )
  291. {
  292. return -1;
  293. }
  294. /* copy the data from the sample to the player */
  295. actual = ( ((esd_sample_t*)player->parent)->sample_length
  296. - player->last_pos > player->buffer_length-player->actual_length )
  297. ? player->buffer_length-player->actual_length
  298. : ((esd_sample_t*)player->parent)->sample_length - player->last_pos;
  299. if ( actual > 0 ) {
  300. memcpy( player->data_buffer+player->actual_length,
  301. ((esd_sample_t*)player->parent)->data_buffer
  302. + player->last_pos, actual );
  303. player->last_pos += actual;
  304. player->actual_length += actual;
  305. if ( player->actual_length == player->buffer_length || ( player->format & ESD_MASK_FUNC ) != ESD_LOOP ) {
  306. /* we're done for this iteration */
  307. break;
  308. }
  309. } else {
  310. /* something horrible has happened to the sample */
  311. return -1;
  312. }
  313. while ( player->actual_length < player->buffer_length ) {
  314. /* we are looping, see if we need to copy another block */
  315. if ( player->last_pos >= ((esd_sample_t*)player->parent)->sample_length ) {
  316. player->last_pos = 0;
  317. /* only keep going if we didn't want to stop looping */
  318. if ( ( ((esd_sample_t*)player->parent)->format & ESD_MASK_FUNC )
  319. == ESD_STOP )
  320. break;
  321. }
  322. /* copy the data from the sample to the player */
  323. actual_2nd = ( ((esd_sample_t*)player->parent)->sample_length
  324. - player->last_pos > player->buffer_length-player->actual_length )
  325. ? player->buffer_length-player->actual_length
  326. : ((esd_sample_t*)player->parent)->sample_length - player->last_pos;
  327. if ( actual_2nd > 0 ) {
  328. memcpy( player->data_buffer+player->actual_length,
  329. ((esd_sample_t*)player->parent)->data_buffer
  330. + player->last_pos, actual_2nd );
  331. player->last_pos += actual_2nd;
  332. actual += actual_2nd;
  333. player->actual_length += actual_2nd;
  334. /* make sure we're not at the end */
  335. if ( player->last_pos >= ((esd_sample_t*)player->parent)->sample_length ) {
  336. player->last_pos = 0;
  337. /* only keep going if we didn't want to stop looping */
  338. if ( ( ((esd_sample_t*)player->parent)->format & ESD_MASK_FUNC )
  339. == ESD_STOP )
  340. break;
  341. }
  342. }
  343. }
  344. /* sample data is swapped as it's cached, no swap needed here */
  345. break;
  346. default:
  347. ESDBG_TRACE( printf( "-%02d- read_player: format 0x%08x not supported\n",
  348. player->source_id, player->format ); );
  349. return -1;
  350. }
  351. return actual;
  352. }
  353. /*******************************************************************/
  354. /* send the players buffer to it's associated socket, erase if EOF */
  355. void monitor_write( void *output_buffer, int length ) {
  356. fd_set wr_fds;
  357. int can_write;
  358. struct timeval timeout;
  359. esd_player_t *monitor, *remove = NULL;
  360. /* make sure we have a monitor connected */
  361. if ( !esd_monitor_list )
  362. return;
  363. /* shuffle through the list of monitors */
  364. monitor = esd_monitor_list;
  365. while ( monitor != NULL ) {
  366. /* see if we can write to the socket */
  367. timeout.tv_sec = 0;
  368. timeout.tv_usec = 0;
  369. FD_ZERO( &wr_fds );
  370. FD_SET( monitor->source_id, &wr_fds );
  371. can_write = select( monitor->source_id + 1, NULL, &wr_fds, NULL, &timeout );
  372. if ( can_write > 0)
  373. {
  374. /* mix down the monitor's buffer */
  375. length = monitor->translate_func( monitor->data_buffer,
  376. monitor->buffer_length,
  377. monitor->rate,
  378. monitor->format,
  379. output_buffer,
  380. length,
  381. esd_audio_rate,
  382. esd_audio_format );
  383. /* write the data buffer to the socket */
  384. ESD_WRITE_BIN( monitor->source_id, monitor->data_buffer,
  385. monitor->buffer_length, length, "mon wr" );
  386. if ( length < 0 ) {
  387. /* error on write, close it down */
  388. ESDBG_TRACE( printf( "(%02d) closing monitor\n", monitor->source_id ); );
  389. remove = monitor;
  390. }
  391. }
  392. monitor = monitor->next;
  393. if ( remove ) {
  394. erase_client( remove->parent );
  395. erase_monitor( remove );
  396. remove = NULL;
  397. }
  398. }
  399. return;
  400. }
  401. int recorder_write( void *buffer, int length ) {
  402. esd_player_t *recorder, *remove = NULL;
  403. int wrote_len = 0;
  404. recorder = esd_recorder_list;
  405. while (recorder != NULL) {
  406. /* write it out */
  407. ESDBG_TRACE( printf( "(%02d) writing recorder data\n",
  408. recorder->source_id ); );
  409. wrote_len = write_player(recorder, buffer, length,
  410. esd_audio_rate, esd_audio_format);
  411. /* see how it went */
  412. if ( wrote_len < 0 ) {
  413. /* couldn't send anything, close it down */
  414. ESDBG_TRACE( printf( "(%02d) closing recorder\n",
  415. recorder->source_id ); );
  416. remove = recorder;
  417. }
  418. recorder = recorder->next;
  419. if ( remove ) {
  420. erase_client( remove->parent );
  421. erase_recorder( remove );
  422. remove = NULL;
  423. }
  424. }
  425. if (!esd_recorder_list) {
  426. /* stop recording */
  427. esd_audio_close();
  428. esd_audio_format &= ~ESD_RECORD;
  429. esd_audio_open();
  430. }
  431. return wrote_len;
  432. }
  433. /*******************************************************************/
  434. /* allocate and initialize a player from client stream */
  435. esd_player_t *new_stream_player( esd_client_t *client )
  436. {
  437. esd_player_t *player;
  438. /* make sure we have the memory to save the client... */
  439. player = (esd_player_t*) malloc( sizeof(esd_player_t) );
  440. if ( player == NULL ) {
  441. return NULL;
  442. }
  443. /* and initialize the player */
  444. player->next = NULL;
  445. player->parent = NULL;
  446. player->format = *(int*)(client->proto_data);
  447. player->rate = *(int*)(client->proto_data + sizeof(int));
  448. player->format = maybe_swap_32( client->swap_byte_order, player->format );
  449. player->format &= ~ESD_MASK_MODE; /* force to ESD_STREAM */
  450. player->rate = maybe_swap_32( client->swap_byte_order, player->rate );
  451. player->source_id = client->fd;
  452. strncpy( player->name, client->proto_data + 2 * sizeof(int), ESD_NAME_MAX );
  453. player->name[ ESD_NAME_MAX - 1 ] = '\0';
  454. ESDBG_TRACE( printf( "(%02d) stream %s: 0x%08x at %d Hz\n", client ->fd,
  455. player->name, player->format, player->rate ); );
  456. /* Reduce buffers on sockets to the minimum needed */
  457. esd_set_socket_buffers( player->source_id, player->format,
  458. player->rate, esd_audio_rate );
  459. /* calculate buffer length to match the mix buffer duration */
  460. player->buffer_length = esd_buf_size_octets * player->rate / esd_audio_rate;
  461. if ( (player->format & ESD_MASK_BITS) == ESD_BITS8 )
  462. player->buffer_length /= 2;
  463. if ( (player->format & ESD_MASK_CHAN) == ESD_MONO )
  464. player->buffer_length /= 2;
  465. /* force to an even multiple of 4 bytes (lower) */
  466. player->buffer_length -= (player->buffer_length % 4);
  467. player->actual_length = 0;
  468. /* everything's ok, set the easy stuff */
  469. player->left_vol_scale = player->right_vol_scale = ESD_VOLUME_BASE;
  470. if ((player->mix_func = get_mix_func( player )) == NULL) {
  471. free( player );
  472. return NULL;
  473. }
  474. player->translate_func = NULL; /* no translating, just mixing */
  475. player->data_buffer
  476. = (void *) malloc( player->buffer_length );
  477. /* if not enough room for data buffer, clean up, and return NULL */
  478. if ( player->data_buffer == NULL ) {
  479. free( player );
  480. return NULL;
  481. }
  482. ESDBG_TRACE( printf( "(%02d) player: [%p]\n", player->source_id, player ); );
  483. return player;
  484. }
  485. /*******************************************************************/
  486. /* allocate and initialize a player from client stream */
  487. esd_player_t *new_sample_player( int sample_id, int loop )
  488. {
  489. esd_player_t *player;
  490. esd_sample_t *sample;
  491. /* find the sample we want to play */
  492. for ( sample = esd_samples_list ; sample != NULL
  493. ; sample = sample->next )
  494. {
  495. if ( sample->sample_id == sample_id ) {
  496. break;
  497. }
  498. }
  499. /* if we didn't find it, return NULL */
  500. if ( sample == NULL ) {
  501. return NULL;
  502. }
  503. /* make sure we have the memory to save the player... */
  504. player = (esd_player_t*) malloc( sizeof(esd_player_t) );
  505. if ( player == NULL ) {
  506. return NULL;
  507. }
  508. /* and initialize the player */
  509. player->next = NULL;
  510. player->parent = sample;
  511. player->format = sample->format & ~ESD_MASK_MODE;
  512. player->format |= ESD_SAMPLE;
  513. if ( loop ) {
  514. player->format &= ~ESD_MASK_FUNC;
  515. player->format |= ESD_LOOP;
  516. }
  517. player->rate = sample->rate;
  518. player->source_id = sample->sample_id;
  519. player->left_vol_scale = sample->left_vol_scale;
  520. player->right_vol_scale = sample->right_vol_scale;
  521. ESDBG_TRACE( printf( "<%02d> connection format: 0x%08x at %d Hz\n",
  522. player->source_id, player->format, player->rate ); );
  523. /* calculate buffer length to match the mix buffer duration */
  524. player->buffer_length = esd_buf_size_octets * player->rate / esd_audio_rate;
  525. if ( (player->format & ESD_MASK_BITS) == ESD_BITS8 )
  526. player->buffer_length /= 2;
  527. if ( (player->format & ESD_MASK_CHAN) == ESD_MONO )
  528. player->buffer_length /= 2;
  529. /* force to an even multiple of 4 */
  530. player->buffer_length -= ( player->buffer_length % 4 );
  531. if ((player->mix_func = get_mix_func( player )) == NULL) {
  532. free( player );
  533. return NULL;
  534. }
  535. player->translate_func = NULL; /* no translating, just mixing */
  536. player->data_buffer
  537. = (void *) malloc( player->buffer_length );
  538. /* if not enough room for data buffer, clean up, and return NULL */
  539. if ( player->data_buffer == NULL ) {
  540. free( player );
  541. return NULL;
  542. }
  543. /* update housekeeping values */
  544. esd_playing_samples++;
  545. player->last_pos = 0;
  546. player->actual_length = 0;
  547. sample->ref_count++;
  548. ESDBG_TRACE( printf( "<%02d> new player: refs=%d samps=%d [%p]\n",
  549. player->source_id, sample->ref_count,
  550. esd_playing_samples, player ); );
  551. /* everything's ok, return the allocated player */
  552. return player;
  553. }