Advertisement
Guest User

Untitled

a guest
Apr 18th, 2018
309
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 60.24 KB | None | 0 0
  1. /****************************************
  2. * a2dp-alsa.c
  3. * Enable A2DP sink and source on ALSA devices using bluez DBus API.
  4. * In short - it enables remote devices to send sound to the computer (sink)
  5. * and enables the computer (source) to send sound to bluetooth speakers.
  6. *
  7. * For bluez 4.x.
  8. *
  9. * Copyright (C) James Budiono 2013
  10. * License: GNU GPL Version 3 or later
  11. * Version 1: June 2013
  12. ****************************************/
  13. // std includes
  14. #include <unistd.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdint.h>
  19. #include <pthread.h>
  20. #include <fcntl.h>
  21. #include <dbus/dbus.h>
  22. #include <errno.h>
  23. #include <arpa/inet.h>
  24. #include <getopt.h>
  25. #include <poll.h>
  26. #include "uthash.h"
  27.  
  28.  
  29. #include "config.h"
  30. #include "system.h"
  31. #include "kernel.h"
  32. #include "panic.h"
  33. #include "core_alloc.h"
  34. #include "sound.h"
  35. #include "ata.h"
  36. #include "codecs.h"
  37. #include "codec_thread.h"
  38. #include "voice_thread.h"
  39. #include "metadata.h"
  40. #include "cuesheet.h"
  41. #include "buffering.h"
  42. #include "talk.h"
  43. #include "playlist.h"
  44. #include "abrepeat.h"
  45. #include "pcmbuf.h"
  46. #include "audio_thread.h"
  47. #include "playback.h"
  48. #include "misc.h"
  49. #include "settings.h"
  50. #include "pcm_mixer.h"
  51.  
  52.  
  53.  
  54. // our own defines
  55. //#define MAX(x, y) (((x) > (y)) ? (x) : (y))
  56. //#define MIN(x, y) (((x) < (y)) ? (x) : (y))
  57.  
  58. #define DEBUG
  59. #ifdef DEBUG
  60. #define debug_print(...) (fprintf (stderr, __VA_ARGS__))
  61. #else
  62. #define debug_print(...)
  63. #endif
  64.  
  65. // bluez specific defines & includes
  66. #define FIND_ADAPTER "FindAdapter"
  67. #define DEFAULT_ADAPTER "DefaultAdapter"
  68. #define ACCESS_TYPE "rw"
  69.  
  70. // sink and source uuid and endpoints
  71. #define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
  72. #define A2DP_SINK_ENDPOINT "/MediaEndpoint/A2DPSink" // bt --> alsa (sink for bt)
  73. #define A2DP_SOURCE_UUID "0000110a-0000-1000-8000-00805f9b34fb"
  74. #define A2DP_SOURCE_ENDPOINT "/MediaEndpoint/A2DPSource" // alsa --> bt (source for bt)
  75.  
  76. #include "a2dp-codecs.h" // from bluez - some sbc constants
  77. #include "ipc.h" // from bluez - some sbc constants
  78. #include "rtp.h" // from bluez - packet headers
  79.  
  80. // sbc stuff
  81. #include "sbc/sbc.h"
  82.  
  83. // structs and prototypes
  84.  
  85. typedef struct {
  86. // sync and command management
  87. pthread_cond_t cond;
  88. pthread_mutex_t mutex;
  89. pthread_t t_handle; //thread handle
  90. volatile enum {
  91. IO_CMD_IDLE = 0,
  92. IO_CMD_RUNNING,
  93. IO_CMD_TERMINATE
  94. } command;
  95. enum {
  96. STATE_DISCONNECTED = 0,
  97. STATE_CONNECTED,
  98. STATE_PLAYING
  99. } prev_state;
  100.  
  101. // transport_path - required to get fd and mtus
  102. char *transport_path; // also the hash key
  103. char *dev_path; // so that audiosource/sink event can find us
  104.  
  105. // the actual fd and mtus for streaming
  106. int fd, read_mtu, write_mtu;
  107. int write; //false = read, true - write
  108.  
  109. // codec stuff
  110. a2dp_sbc_t cap;
  111. sbc_t sbc;
  112.  
  113. // persistent stuff for encoding purpose
  114. uint16_t seq_num; //cumulative packet number
  115. uint32_t timestamp; //timestamp
  116.  
  117. //hashtable management
  118. UT_hash_handle hh;
  119. } io_thread_tcb_s; //the I/O thread control block.
  120.  
  121. void *io_thread_run(void *ptr);
  122. void io_thread_set_command (io_thread_tcb_s *data, int command);
  123. io_thread_tcb_s *create_io_thread();
  124. void destroy_io_thread(io_thread_tcb_s *p);
  125. int transport_acquire (DBusConnection *conn, char *transport_path, int *fd, int *read_mtu, int *write_mtu);
  126. int transport_release (DBusConnection *conn, char *transport_path);
  127.  
  128. // globals
  129. int quit=0; // when set to 1, program terminates
  130. int run_once = 0; // only run output once, then exit
  131.  
  132.  
  133. //#define BT_SBC_DEFAULT_FREQ BT_SBC_SAMPLING_FREQ_44100
  134. //#define BT_AUDIO_FREQ 44100
  135.  
  136. #define BT_SBC_DEFAULT_FREQ BT_SBC_SAMPLING_FREQ_48000
  137. #define BT_AUDIO_FREQ 48000
  138.  
  139. void *decode_buf = NULL;
  140. size_t decode_bufsize = 0;
  141. size_t decode_buf_fill = 0;
  142.  
  143.  
  144. //#define BUFFERS_MS 30 // ms of audio for buffering
  145. //#define BUFFERS_MS 50 // ms of audio for buffering
  146. //#define BUFFERS_MS 80 // ms of audio for buffering
  147. #define BUFFERS_MS 100 // ms of audio for buffering
  148. //#define BUFFERS_MS 300 // ms of audio for buffering
  149. //#define BUFFERS_MS 150 // ms of audio for buffering
  150. //#define FRAME_LEN 1024
  151. //#define FRAME_LEN 2048
  152. #define FRAME_LEN 512
  153. //#define FRAME_LEN (115 * 4)
  154. // http://soundexpert.org/news/-/blogs/bluetooth-audio-quality-a2dp
  155. // https://www.rtings.com/headphones/learn/sbc-aptx-which-bluetooth-codec-is-the-best
  156.  
  157. //#define BT_POLL_DELAY 300 // ms
  158. #define BT_POLL_DELAY (BUFFERS_MS/10) // ms
  159.  
  160. #define FRAME_SECONDS (FRAME_LEN / (float)(BT_AUDIO_FREQ * 2 * 2))
  161. #define FRAME_MS (FRAME_SECONDS * 1000)
  162. //#define FRAME_BUFFERS 12
  163. //#define FRAME_BUFFERS 24
  164. #define FRAME_BUFFERS (int)(BUFFERS_MS / FRAME_MS)
  165.  
  166. struct frame_buffer {
  167. void *data;
  168. int written;
  169. };
  170.  
  171. struct frame_buffer frame_buffer[FRAME_BUFFERS];
  172.  
  173. // it should be possible to do this without mutexes because these are accessed with atomic operations
  174. int frame_buffer_write_i = 0;
  175. int frame_buffer_read_i = 0;
  176.  
  177. void frame_buffer_init() {
  178. struct frame_buffer *fb;
  179.  
  180. for (int i = 0; i < FRAME_BUFFERS; i++) {
  181. fb = &frame_buffer[i];
  182. fb->data = malloc(FRAME_LEN);
  183. fb->written = 0;
  184. }
  185.  
  186. }
  187.  
  188. struct frame_buffer *frame_buffer_get_writable() {
  189. if (frame_buffer_write_i - frame_buffer_read_i >= FRAME_BUFFERS-2)
  190. return NULL; // full
  191.  
  192. return &frame_buffer[frame_buffer_write_i % FRAME_BUFFERS];
  193. }
  194.  
  195. int frame_buffer_get_num_filled() {
  196. return frame_buffer_write_i - frame_buffer_read_i;
  197. }
  198.  
  199. void frame_buffer_done_writing(struct frame_buffer *fb) {
  200. if (fb->written == FRAME_LEN)
  201. frame_buffer_write_i++; // next buffer
  202. }
  203.  
  204.  
  205. struct frame_buffer *frame_buffer_get_readable() {
  206. if (frame_buffer_write_i == frame_buffer_read_i)
  207. return NULL; // empty
  208. return &frame_buffer[frame_buffer_read_i % FRAME_BUFFERS];
  209. }
  210. /*
  211. void frame_buffer_done_reading(struct frame_buffer *fb) {
  212. if (fb->written == FRAME_LEN)
  213. frame_buffer_write_i++; // next buffer
  214. }
  215. */
  216. int gave_bytes = 0;
  217. int wanted_bytes = 0;
  218. int16_t empty[FRAME_LEN/2] = { 0 };
  219. bool wait_for_fill = false;
  220.  
  221. /* ISR handler to get next block of data */
  222. static void get_more(const void **start, size_t *size)
  223. {
  224. struct frame_buffer *fb = frame_buffer_get_readable();
  225. if (fb == NULL || wait_for_fill) {
  226. wait_for_fill = true;
  227. *start = empty;
  228. *size = FRAME_LEN;
  229. //debug_print("put empty\n");
  230.  
  231. #if 1
  232. if (frame_buffer_get_writable())
  233. return;
  234. wait_for_fill = false;
  235. #else
  236. // over half full, continue playback
  237. if (frame_buffer_get_num_filled() >= FRAME_BUFFERS / 2)
  238. wait_for_fill = false;
  239.  
  240. return;
  241. #endif
  242. }
  243.  
  244. *start = fb->data;
  245. *size = fb->written;
  246.  
  247. // it is kind of wrong to free the current frame immediately since it is currently being accessed
  248. // the trick is frame_buffer_get_writable() wont give access to it
  249. fb->written = 0;
  250. frame_buffer_read_i++;
  251.  
  252. }
  253.  
  254.  
  255. //////////////////////////////// DBUS HELPERS ////////////////////////////////
  256.  
  257. /*****************//**
  258. * Handle dbus error and clear error message block
  259. *
  260. * @param [in] The error object
  261. * @param [in] function where the error happens
  262. * @param [in] line number where the error happens
  263. * @returns TRUE if successful, FALSE otherwise
  264. ********************/
  265. int handle_dbus_error (DBusError *err, const char *func, int line) {
  266. if (dbus_error_is_set (err)) {
  267. fprintf(stderr, "DBus error %s at %u: %s\n", func, line, err->message);
  268. dbus_error_free(err);
  269. return 1;
  270. }
  271. return 0;
  272. }
  273.  
  274. /*****************//**
  275. * Connect to the system message bus
  276. *
  277. * @param [out] connection object, if function is successful, other wise it is unchanged.
  278. * @returns TRUE if successful, FALSE otherwise
  279. ********************/
  280. int get_system_bus(DBusConnection **system_bus) {
  281. DBusError err;
  282. DBusConnection* conn;
  283.  
  284. dbus_error_init(&err);
  285. conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
  286. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  287. if (NULL == conn) return 0;
  288.  
  289. *system_bus = conn;
  290. debug_print("Name %s\n", dbus_bus_get_unique_name (conn));
  291. return 1;
  292. }
  293.  
  294. /*****************//**
  295. * Get the bluetooth device's path
  296. *
  297. * @param [in] connection to use
  298. * @param [in] adapter to use (hci0, or bluetooth address, or NULL to use default)
  299. * @param [out] the object path, if function is successful, other wise it is unchanged.
  300. * @returns TRUE if successful, FALSE otherwise
  301. ********************/
  302. int get_bluetooth_object(DBusConnection* conn, char *device, char **dev_path) {
  303. DBusMessage *msg, *reply;
  304. DBusMessageIter iter;
  305. DBusError err;
  306. char *s, *method = FIND_ADAPTER;
  307.  
  308. dbus_error_init(&err);
  309. debug_print("Getting object path for adapter %s\n", device);
  310.  
  311. // create a new method call msg
  312. if (!device) method = DEFAULT_ADAPTER;
  313. msg = dbus_message_new_method_call("org.bluez",
  314. "/", // object to call on
  315. "org.bluez.Manager", // interface to call on
  316. method); // method name
  317.  
  318. // append arguments
  319. dbus_message_iter_init_append(msg, &iter);
  320. if (device) dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
  321.  
  322. // send message and wait for reply, -1 means wait forever
  323. reply = dbus_connection_send_with_reply_and_block (conn, msg, -1, &err);
  324. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  325. if (!reply) {
  326. fprintf(stderr, "Reply Null\n");
  327. return 0;
  328. }
  329.  
  330. // read the parameters
  331. if (dbus_message_iter_init(reply, &iter) &&
  332. DBUS_TYPE_OBJECT_PATH == dbus_message_iter_get_arg_type(&iter))
  333. dbus_message_iter_get_basic(&iter, &s);
  334. else return 0;
  335.  
  336. // free reply and close connection
  337. debug_print("Object path for %s is %s\n", device, s);
  338. dbus_message_unref(msg);
  339. dbus_message_unref(reply);
  340. *dev_path = strdup (s);
  341. return 1;
  342. }
  343.  
  344. /*****************//**
  345. * Add a dict entry of a variant of simple types
  346. *
  347. * @param [in] array iter to add to
  348. * @param [in] key
  349. * @param [in] type (must be simple types)
  350. * @param [in] value
  351. ********************/
  352. void util_add_dict_variant_entry (DBusMessageIter *iter, char *key, int type, void *value) {
  353. DBusMessageIter dict, variant;
  354. dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
  355. dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &key);
  356. dbus_message_iter_open_container (&dict, DBUS_TYPE_VARIANT, (char *)&type, &variant);
  357. dbus_message_iter_append_basic (&variant, type, &value);
  358. dbus_message_iter_close_container (&dict, &variant);
  359. dbus_message_iter_close_container (iter, &dict);
  360. }
  361.  
  362. /*****************//**
  363. * Add a dict entry of an array of of simple types
  364. *
  365. * @param [in] array iter to add to
  366. * @param [in] key
  367. * @param [in] type (must be simple types)
  368. * @param [in] pointer to the array
  369. * @param [in] number of elements (not size in bytes!)
  370. ********************/
  371. void util_add_dict_array_entry (DBusMessageIter *iter, char *key, int type, void *buf, int elements) {
  372. DBusMessageIter dict, variant, array;
  373. char array_type[5] = "a";
  374. strncat (array_type, (char*)&type, sizeof(array_type));
  375.  
  376. dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
  377. dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &key);
  378. dbus_message_iter_open_container (&dict, DBUS_TYPE_VARIANT, array_type, &variant);
  379. dbus_message_iter_open_container (&variant, DBUS_TYPE_ARRAY, (char *)&type, &array);
  380. dbus_message_iter_append_fixed_array (&array, type, &buf, elements);
  381. dbus_message_iter_close_container (&variant, &array);
  382. dbus_message_iter_close_container (&dict, &variant);
  383. dbus_message_iter_close_container (iter, &dict);
  384. }
  385.  
  386. #define BLUETOOTH_ONLY_HIGH_CAP
  387.  
  388. //////////////////////////////// BLUEZ AUDIO/MEDIA HELPERS ////////////////////////////////
  389.  
  390. /*****************//**
  391. * Register our "endpoint" handler to bluez audio system.
  392. * As part of its job, it returns supported codecs and codec parameters, as well
  393. * as what functions are we doing here (A2DP source, A2DP sink, HFP, etc - for
  394. * this program it will be A2DP sink).
  395. *
  396. * @param [in] system bus connection
  397. * @param [in] bluetooth object to register to
  398. * @returns TRUE means ok, FALSE means something is wrong
  399. ********************/
  400. int media_register_endpoint(DBusConnection* conn, char *bt_object, char *endpoint, char *uuid) {
  401. DBusMessage *msg, *reply;
  402. DBusMessageIter iter, iterarray;
  403. DBusError err;
  404.  
  405. a2dp_sbc_t capabilities;
  406. #ifdef BLUETOOTH_ONLY_HIGH_CAP
  407. capabilities.channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL |
  408. BT_A2DP_CHANNEL_MODE_STEREO | BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
  409. capabilities.frequency = BT_SBC_SAMPLING_FREQ_44100 | BT_SBC_SAMPLING_FREQ_48000;
  410. // capabilities.allocation_method = /*BT_A2DP_ALLOCATION_SNR |*/ BT_A2DP_ALLOCATION_LOUDNESS;
  411. capabilities.allocation_method = BT_A2DP_ALLOCATION_SNR;
  412. capabilities.subbands = BT_A2DP_SUBBANDS_8;
  413. // capabilities.subbands = BT_A2DP_SUBBANDS_4;
  414. // capabilities.block_length = BT_A2DP_BLOCK_LENGTH_16;
  415. capabilities.block_length = BT_A2DP_BLOCK_LENGTH_4;
  416. #else
  417. capabilities.channel_mode = BT_A2DP_CHANNEL_MODE_MONO | BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL |
  418. BT_A2DP_CHANNEL_MODE_STEREO | BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
  419. capabilities.frequency = BT_SBC_SAMPLING_FREQ_16000 | BT_SBC_SAMPLING_FREQ_32000 |
  420. BT_SBC_SAMPLING_FREQ_44100 | BT_SBC_SAMPLING_FREQ_48000;
  421. capabilities.allocation_method = BT_A2DP_ALLOCATION_SNR | BT_A2DP_ALLOCATION_LOUDNESS;
  422. capabilities.subbands = BT_A2DP_SUBBANDS_4 | BT_A2DP_SUBBANDS_8;
  423. capabilities.block_length = BT_A2DP_BLOCK_LENGTH_4 | BT_A2DP_BLOCK_LENGTH_8 |
  424. BT_A2DP_BLOCK_LENGTH_12 | BT_A2DP_BLOCK_LENGTH_16;
  425. #endif
  426.  
  427. capabilities.min_bitpool = MIN_BITPOOL;
  428. capabilities.max_bitpool = MAX_BITPOOL;
  429.  
  430. dbus_error_init(&err);
  431. msg = dbus_message_new_method_call("org.bluez",
  432. bt_object, // object to call on
  433. "org.bluez.Media", // interface to call on
  434. "RegisterEndpoint"); // method name
  435.  
  436. //build the parameters
  437. dbus_message_iter_init_append (msg, &iter);
  438.  
  439. //first param - object path
  440. dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &endpoint);
  441. //second param - properties
  442. dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &iterarray);
  443. util_add_dict_variant_entry (&iterarray, "UUID", DBUS_TYPE_STRING, uuid);
  444. util_add_dict_variant_entry (&iterarray, "Codec", DBUS_TYPE_BYTE, A2DP_CODEC_SBC);
  445. util_add_dict_array_entry (&iterarray, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof (capabilities));
  446. dbus_message_iter_close_container (&iter, &iterarray);
  447.  
  448. //char *buf; int buflen; dbus_message_marshal (msg, &buf, &buflen); write (1, buf, buflen); return 0;
  449.  
  450. //make the call
  451. reply = dbus_connection_send_with_reply_and_block (conn, msg, -1, &err);
  452. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  453. if (!reply) {
  454. fprintf(stderr, "Reply Null\n");
  455. return 0;
  456. }
  457.  
  458. dbus_message_unref(msg);
  459. dbus_message_unref(reply);
  460. return 1;
  461. }
  462.  
  463. // looking at bluez sources on how to do this
  464. int media_unregister_endpoint(DBusConnection* conn, char *bt_object, char *endpoint) {
  465. DBusMessage *msg, *reply;
  466. DBusMessageIter iter, iterarray;
  467. DBusError err;
  468.  
  469. dbus_error_init(&err);
  470. msg = dbus_message_new_method_call("org.bluez",
  471. bt_object, // object to call on
  472. "org.bluez.Media", // interface to call on
  473. "UnregisterEndpoint"); // method name
  474.  
  475. //build the parameters
  476. dbus_message_iter_init_append (msg, &iter);
  477.  
  478. //first param - object path
  479. dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &endpoint);
  480. // dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &iterarray);
  481. // dbus_message_iter_close_container (&iter, &iterarray);
  482.  
  483. //make the call
  484. reply = dbus_connection_send_with_reply_and_block (conn, msg, -1, &err);
  485. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  486. if (!reply) {
  487. fprintf(stderr, "Reply Null\n");
  488. return 0;
  489. }
  490.  
  491. dbus_message_unref(msg);
  492. dbus_message_unref(reply);
  493. return 1;
  494. }
  495.  
  496. /*****************//**
  497. * Get the transport (ie, the actual file descriptor) for streaming (ie, read/write)
  498. * the audio data
  499. *
  500. * @param [in] system bus connection
  501. * @param [in] transport object path (must come from MediaEndpoint.SetConfiguration)
  502. * @param [out] file descriptor
  503. * @param [out] maximum size to read per transaction
  504. * @param [out] maximum size to write per transaction
  505. * @returns TRUE if ok, FALSE means something is wrong
  506. ********************/
  507. int transport_acquire (DBusConnection *conn, char *transport_path, int *fd, int *read_mtu, int *write_mtu) {
  508. DBusMessage *msg, *reply;
  509. DBusMessageIter iter;
  510. DBusError err;
  511. char *access_type = ACCESS_TYPE;
  512.  
  513. debug_print ("acquire %s\n", transport_path);
  514. dbus_error_init(&err);
  515. msg = dbus_message_new_method_call("org.bluez",
  516. transport_path, // object to call on
  517. "org.bluez.MediaTransport", // interface to call on
  518. "Acquire"); // method name
  519.  
  520. //build the parameters
  521. dbus_message_iter_init_append (msg, &iter);
  522. dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &access_type);
  523.  
  524. //make the call
  525. reply = dbus_connection_send_with_reply_and_block (conn, msg, -1, &err);
  526. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  527. if (!reply) {
  528. fprintf(stderr, "Reply Null\n");
  529. return 0;
  530. }
  531.  
  532. //read the reply
  533. if (!dbus_message_get_args(reply, &err,
  534. DBUS_TYPE_UNIX_FD, fd,
  535. DBUS_TYPE_UINT16, read_mtu,
  536. DBUS_TYPE_UINT16, write_mtu,
  537. DBUS_TYPE_INVALID))
  538. {
  539. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  540. return 0;
  541. }
  542.  
  543. //clean up
  544. dbus_message_unref(msg);
  545. dbus_message_unref(reply);
  546. return 1;
  547. }
  548.  
  549. /*****************//**
  550. * Release the transport (ie, the file descriptor)
  551. * Note: this doesn't need to be called if transport is closed by
  552. * "MediaEndpoint.ClearConfiguration". It is only needed if the app wishes to
  553. * release control of the fd while the stream is still active (e.g - suspend
  554. * stream, pausing, etc).
  555. *
  556. * @param [in] system bus connection
  557. * @param [in] transport object path (must come from MediaEndpoint.SetConfiguration)
  558. ********************/
  559. int transport_release (DBusConnection *conn, char *transport_path) {
  560. DBusMessage *msg, *reply;
  561. DBusMessageIter iter;
  562. DBusError err;
  563. char *access_type = ACCESS_TYPE;
  564.  
  565. debug_print ("release %s\n", transport_path);
  566. dbus_error_init(&err);
  567. msg = dbus_message_new_method_call("org.bluez",
  568. transport_path, // object to call on
  569. "org.bluez.MediaTransport", // interface to call on
  570. "Release"); // method name
  571.  
  572. //build the parameters
  573. dbus_message_iter_init_append (msg, &iter);
  574. dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &access_type);
  575.  
  576. //make the call
  577. reply = dbus_connection_send_with_reply_and_block (conn, msg, -1, &err);
  578. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  579. if (!reply) {
  580. fprintf(stderr, "Reply Null\n");
  581. return 0;
  582. }
  583.  
  584. //clean up
  585. dbus_message_unref(msg);
  586. dbus_message_unref(reply);
  587. return 1;
  588. }
  589.  
  590. /*****************//**
  591. * Helper to calculate the optimum bitpool, given the sampling frequency,
  592. * and number of channels.
  593. * Taken verbatim from pulseaudio 2.1
  594. * (which took it from bluez audio - a2dp.c & pcm_bluetooth.c - default_bitpool)
  595. *
  596. * @param [in] frequency
  597. * @param [in] channel mode
  598. * @returns coded SBC bitpool
  599. *********************/
  600. static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) {
  601.  
  602. switch (freq) {
  603. case BT_SBC_SAMPLING_FREQ_16000:
  604. case BT_SBC_SAMPLING_FREQ_32000:
  605. return 53;
  606.  
  607. case BT_SBC_SAMPLING_FREQ_44100:
  608.  
  609. switch (mode) {
  610. case BT_A2DP_CHANNEL_MODE_MONO:
  611. case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
  612. return 31;
  613.  
  614. case BT_A2DP_CHANNEL_MODE_STEREO:
  615. case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
  616. return 53;
  617.  
  618. default:
  619. fprintf (stderr, "Invalid channel mode %u", mode);
  620. return 53;
  621. }
  622.  
  623. case BT_SBC_SAMPLING_FREQ_48000:
  624.  
  625. switch (mode) {
  626. case BT_A2DP_CHANNEL_MODE_MONO:
  627. case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
  628. return 29;
  629.  
  630. case BT_A2DP_CHANNEL_MODE_STEREO:
  631. case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
  632. return 51;
  633.  
  634. default:
  635. fprintf (stderr, "Invalid channel mode %u", mode);
  636. return 51;
  637. }
  638.  
  639. default:
  640. fprintf (stderr, "Invalid sampling freq %u", freq);
  641. return 53;
  642. }
  643. }
  644.  
  645. /*****************//**
  646. * Helper to setup sbc params from a2dp_sbc_t
  647. * Modified from pulseaudio 2.1 (which took it from bluez - pcm_bluetooth.c
  648. * - bluetooth_a2dp_setup)
  649. *
  650. * @param [in] sbc codec configuration
  651. * @param [in] bluez codec capability configuration
  652. *********************/
  653. void setup_sbc(sbc_t *sbc, a2dp_sbc_t *cap) {
  654.  
  655. switch (cap->frequency) {
  656. case BT_SBC_SAMPLING_FREQ_16000:
  657. sbc->frequency = SBC_FREQ_16000;
  658. break;
  659. case BT_SBC_SAMPLING_FREQ_32000:
  660. sbc->frequency = SBC_FREQ_32000;
  661. break;
  662. case BT_SBC_SAMPLING_FREQ_44100:
  663. sbc->frequency = SBC_FREQ_44100;
  664. break;
  665. case BT_SBC_SAMPLING_FREQ_48000:
  666. sbc->frequency = SBC_FREQ_48000;
  667. break;
  668. default:
  669. fprintf (stderr, "No supported frequency");
  670. }
  671.  
  672. switch (cap->channel_mode) {
  673. case BT_A2DP_CHANNEL_MODE_MONO:
  674. sbc->mode = SBC_MODE_MONO;
  675. break;
  676. case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
  677. sbc->mode = SBC_MODE_DUAL_CHANNEL;
  678. break;
  679. case BT_A2DP_CHANNEL_MODE_STEREO:
  680. sbc->mode = SBC_MODE_STEREO;
  681. break;
  682. case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
  683. sbc->mode = SBC_MODE_JOINT_STEREO;
  684. break;
  685. default:
  686. fprintf (stderr, "No supported channel_mode");
  687. }
  688.  
  689. switch (cap->allocation_method) {
  690. case BT_A2DP_ALLOCATION_SNR:
  691. sbc->allocation = SBC_AM_SNR;
  692. break;
  693. case BT_A2DP_ALLOCATION_LOUDNESS:
  694. sbc->allocation = SBC_AM_LOUDNESS;
  695. break;
  696. default:
  697. fprintf (stderr, "No supported allocation");
  698. }
  699.  
  700. switch (cap->subbands) {
  701. case BT_A2DP_SUBBANDS_4:
  702. sbc->subbands = SBC_SB_4;
  703. break;
  704. case BT_A2DP_SUBBANDS_8:
  705. sbc->subbands = SBC_SB_8;
  706. break;
  707. default:
  708. fprintf (stderr, "No supported subbands");
  709. }
  710.  
  711. switch (cap->block_length) {
  712. case BT_A2DP_BLOCK_LENGTH_4:
  713. sbc->blocks = SBC_BLK_4;
  714. break;
  715. case BT_A2DP_BLOCK_LENGTH_8:
  716. sbc->blocks = SBC_BLK_8;
  717. break;
  718. case BT_A2DP_BLOCK_LENGTH_12:
  719. sbc->blocks = SBC_BLK_12;
  720. break;
  721. case BT_A2DP_BLOCK_LENGTH_16:
  722. sbc->blocks = SBC_BLK_16;
  723. break;
  724. default:
  725. fprintf (stderr, "No supported block length");
  726. }
  727.  
  728. sbc->bitpool = cap->max_bitpool;
  729. }
  730.  
  731. //////////////////////////////// BLUEZ AUDIO CALLBACK HANDLER ////////////////////////////////
  732.  
  733.  
  734. /*****************//**
  735. * Implement MediaEndpoint.SelectConfiguration.
  736. * Called by bluez to negotiate which configuration (=codec, codec parameter)
  737. * for audio streaming.
  738. * This function will examine what the requested configuration and returns back
  739. * a reply with the supported / agreed configuration.
  740. *
  741. * Chosen configuration isn't cached because it will be returned with SetConfiguration.
  742. *
  743. * Contains modified code taken from pulseaudio 2.1 (which took it from
  744. * bluez audio, select_sbc_params (a2dp.c)
  745. *
  746. * @param [in] original "call" message from bluez
  747. * @returns reply message (success or failure)
  748. *********************/
  749. DBusMessage* endpoint_select_configuration (DBusMessage *msg) {
  750. a2dp_sbc_t *cap, config;
  751. uint8_t *pconf = (uint8_t *) &config;
  752. int size;
  753. DBusMessage *reply;
  754. DBusError err;
  755.  
  756. debug_print ("Select configuration\n");
  757. dbus_error_init(&err);
  758.  
  759. if (!dbus_message_get_args(msg, &err, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cap, &size, DBUS_TYPE_INVALID)) {
  760. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  761. goto fail;
  762. }
  763.  
  764. //taken from pulseaudio with modification
  765. memset(&config, 0, sizeof(config));
  766. config.frequency = BT_SBC_DEFAULT_FREQ;
  767. if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
  768. config.channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
  769. else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
  770. config.channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
  771. else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
  772. config.channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
  773. else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
  774. config.channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
  775. } else {
  776. fprintf (stderr, "No supported channel modes");
  777. goto fail;
  778. }
  779.  
  780. if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
  781. config.block_length = BT_A2DP_BLOCK_LENGTH_16;
  782. else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
  783. config.block_length = BT_A2DP_BLOCK_LENGTH_12;
  784. else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
  785. config.block_length = BT_A2DP_BLOCK_LENGTH_8;
  786. else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
  787. config.block_length = BT_A2DP_BLOCK_LENGTH_4;
  788. else {
  789. fprintf (stderr, "No supported block lengths");
  790. goto fail;
  791. }
  792.  
  793. if (cap->subbands & BT_A2DP_SUBBANDS_8)
  794. config.subbands = BT_A2DP_SUBBANDS_8;
  795. else if (cap->subbands & BT_A2DP_SUBBANDS_4)
  796. config.subbands = BT_A2DP_SUBBANDS_4;
  797. else {
  798. fprintf (stderr, "No supported subbands");
  799. goto fail;
  800. }
  801.  
  802. if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
  803. config.allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
  804. else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
  805. config.allocation_method = BT_A2DP_ALLOCATION_SNR;
  806.  
  807. config.min_bitpool = (uint8_t) MAX(MIN_BITPOOL, cap->min_bitpool);
  808. config.max_bitpool = (uint8_t) MIN(a2dp_default_bitpool(config.frequency, config.channel_mode), cap->max_bitpool);
  809.  
  810. reply = dbus_message_new_method_return(msg);
  811. dbus_message_append_args (reply,
  812. DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pconf, size,
  813. DBUS_TYPE_INVALID);
  814. return reply;
  815.  
  816. fail:
  817. return dbus_message_new_error(msg, "org.bluez.MediaEndpoint.Error.InvalidArguments",
  818. "Unable to select configuration");
  819. }
  820.  
  821. /*****************//**
  822. * Implement MediaEndpoint.SetConfiguration.
  823. * Called by bluez to confirm that this will be the configuration chosen.
  824. * The most important thing here is the "transport object path", which we will
  825. * need to get the actual file-descriptor for streaming later (see transport_acquire).
  826. *
  827. * In theory the transport_acquire could be called from here with some delays,
  828. * in reality it is a lot better to do it after we've received confirmation that
  829. * audio is "connected" (this is done by watching AudioSource.PropertyChange signal)
  830. *
  831. * This function is too complicated for what it does, for our (simple) purpose
  832. * we actually only need the transport_path so we don't have to parse all the parameters,
  833. * but we do anyway.
  834. *
  835. * @param [in] original "call" message from bluez
  836. * @param [in] io thread hashtable
  837. * @returns reply message (success or failure)
  838. *********************/
  839. DBusMessage* endpoint_set_configuration (DBusMessage *msg, io_thread_tcb_s **io_threads_table) {
  840. const char *transport_path, *dev_path = NULL, *uuid = NULL, *cmd_path = NULL;
  841. uint8_t *config = NULL;
  842. int size = 0;
  843. DBusMessageIter iter, iterprop, iterentry, itervalue, iterarray;
  844. io_thread_tcb_s *head = *io_threads_table;
  845. io_thread_tcb_s *io_data = NULL;
  846.  
  847. dbus_message_iter_init(msg, &iter);
  848. dbus_message_iter_get_basic(&iter, &transport_path);
  849. if (!dbus_message_iter_next(&iter))
  850. goto fail;
  851.  
  852. dbus_message_iter_recurse(&iter, &iterprop);
  853. if (dbus_message_iter_get_arg_type(&iterprop) != DBUS_TYPE_DICT_ENTRY)
  854. goto fail;
  855.  
  856. /* Read transport properties */
  857. while (dbus_message_iter_get_arg_type(&iterprop) == DBUS_TYPE_DICT_ENTRY) {
  858. const char *key;
  859. int var;
  860.  
  861. dbus_message_iter_recurse(&iterprop, &iterentry);
  862. dbus_message_iter_get_basic(&iterentry, &key);
  863.  
  864. dbus_message_iter_next(&iterentry);
  865. dbus_message_iter_recurse(&iterentry, &itervalue);
  866.  
  867. var = dbus_message_iter_get_arg_type(&itervalue);
  868. if (strcasecmp(key, "UUID") == 0) {
  869. if (var != DBUS_TYPE_STRING)
  870. goto fail;
  871. dbus_message_iter_get_basic(&itervalue, &uuid);
  872. } else if (strcasecmp(key, "Device") == 0) {
  873. if (var != DBUS_TYPE_OBJECT_PATH)
  874. goto fail;
  875. dbus_message_iter_get_basic(&itervalue, &dev_path);
  876. } else if (strcasecmp(key, "Configuration") == 0) {
  877. if (var != DBUS_TYPE_ARRAY)
  878. goto fail;
  879. dbus_message_iter_recurse(&itervalue, &iterarray);
  880. dbus_message_iter_get_fixed_array(&iterarray, &config, &size);
  881. }
  882. dbus_message_iter_next(&iterprop);
  883. }
  884. debug_print ("Set configuration %s\n",transport_path);
  885.  
  886. //capture the transport_path and allocate the transport later, when the audiosource is "connected".
  887. HASH_FIND_STR (head, transport_path, io_data);
  888. if (!io_data) {
  889. io_data = create_io_thread();
  890. io_data->dev_path = strdup (dev_path);
  891. io_data->transport_path = strdup (transport_path);
  892. io_data->cap = *((a2dp_sbc_t*) config);
  893.  
  894. //read or write
  895. cmd_path = (char *)dbus_message_get_path (msg);
  896. if ( strcasecmp (cmd_path, A2DP_SINK_ENDPOINT) == 0)
  897. io_data->write = 0;
  898. else if ( strcasecmp (cmd_path, A2DP_SOURCE_ENDPOINT) == 0)
  899. io_data->write = 1;
  900.  
  901. HASH_ADD_KEYPTR (hh, head, io_data->transport_path, strlen(io_data->transport_path), io_data);
  902. *io_threads_table = head;
  903. }
  904.  
  905. return dbus_message_new_method_return(msg);
  906.  
  907. fail:
  908. return dbus_message_new_error(msg, "org.bluez.MediaEndpoint.Error.InvalidArguments",
  909. "Unable to select configuration");
  910. }
  911.  
  912. /*****************//**
  913. * Implement MediaEndpoint.ClearConfiguration.
  914. * Called by bluez to let us know that the audio streaming process has been reset
  915. * for whatever reason, and we should do our own clean-up.
  916. * Here we tell our I/O thread to stop.
  917. *
  918. * It is not necessary to call transport_release here because by the time we got here,
  919. * the 'transport' has already been released.
  920. *
  921. * @param [in] original "call" message from bluez
  922. * @param [in] io thread's data - to command I/O thread to stop.
  923. * @returns reply message (success or failure)
  924. *********************/
  925. DBusMessage* endpoint_clear_configuration (DBusMessage *msg, io_thread_tcb_s **io_threads_table) {
  926. DBusMessage *reply;
  927. DBusError err;
  928. DBusMessageIter iter;
  929. char *transport_path;
  930. io_thread_tcb_s *head = *io_threads_table;
  931. io_thread_tcb_s *io_data = NULL;
  932.  
  933. dbus_error_init(&err);
  934. dbus_message_iter_init(msg, &iter);
  935. dbus_message_iter_get_basic(&iter, &transport_path);
  936. debug_print ("Clear configuration %s\n",transport_path);
  937.  
  938. // stop stream
  939. HASH_FIND_STR (head, transport_path, io_data);
  940. if (io_data) {
  941. debug_print ("stopping thread %p\n",io_data);
  942. HASH_DEL (head, io_data);
  943. *io_threads_table = head;
  944. destroy_io_thread (io_data);
  945. }
  946.  
  947. reply = dbus_message_new_method_return(msg);
  948. return reply;
  949. }
  950.  
  951. /*****************//**
  952. * Implement MediaEndpoint.Release
  953. * Called by bluez to let us know our registration (see register_endpoint) has been
  954. * cancelled (or 'released'). The next logical action after this, is either:
  955. * a) to exit
  956. * b) to re-register.
  957. *
  958. * There is no need to 'Unregister' because by the time we get here, our endpoint
  959. * has already been de-registered.
  960. *
  961. * @param [in] original "call" message from bluez
  962. * @returns reply message (success or failure)
  963. *********************/
  964. DBusMessage* endpoint_release (DBusMessage *msg) {
  965. debug_print ("Release endpoint\n");
  966. DBusMessage *reply;
  967. DBusError err;
  968.  
  969. dbus_error_init(&err);
  970. reply = dbus_message_new_method_return(msg);
  971. return reply;
  972. }
  973.  
  974.  
  975.  
  976. //////////////////////////////// BLUEZ-DBUS SIGNAL HANDLERS ////////////////////////////////
  977.  
  978. /*****************//**
  979. * Handle AudioSource.PropertyChanged
  980. * Signalled by bluez to let us know that the state of the audio source has changed.
  981. * We use this signal as a trigger for 'delayed' transport_acquire to get the file
  982. * descriptor, as well as to start the I/O thread.
  983. *
  984. * We don't use the corresponding transport_release because for the time being
  985. * we will never willingly release a transport, until it is closed by
  986. * MediaEndpoint.ClearConfiguration (the I/O thread will be stopped there).
  987. *
  988. * Note: The 'source' and 'sink' terms used in bluez is super-confusing because
  989. * they are not consistent - sometimes they view it from the bluez side
  990. * (in this case, it's a 'source' because the bluez is the 'source' of the data,
  991. * sometimes they view it as 'sink' because this application receives and acts as data sink
  992. * for the remote-end.
  993. *
  994. * Note: There is a corresponding signal for AudioSink, which we don't use.
  995. *
  996. * @param [in] connection object to talk to DBus
  997. * @param [in] original "call" message from bluez
  998. * @param [in] write==0 -> audiosink, write==1 --> audiosource
  999. * @param [in] head of I/O thread hashtable
  1000. * @returns reply message (success or failure)
  1001. *********************/
  1002. #define audiosink_property_changed audiosource_property_changed
  1003. void audiosource_property_changed (DBusConnection *conn, DBusMessage *msg, int write, io_thread_tcb_s **io_threads_table) {
  1004. DBusMessageIter iter, itervariant;
  1005. char *key;
  1006. char *dev_path;
  1007. char *state;
  1008. io_thread_tcb_s *head = *io_threads_table;
  1009. io_thread_tcb_s *io_data;
  1010. int new_state, transition, when_to_acquire, when_to_release;
  1011.  
  1012. dbus_message_iter_init (msg, &iter);
  1013. dbus_message_iter_get_basic (&iter, &key);
  1014. if (strcasecmp (key, "State") != 0) return; //we are only interested in this.
  1015.  
  1016. if (!dbus_message_iter_next(&iter)) goto fail;
  1017. dbus_message_iter_recurse(&iter, &itervariant);
  1018. if (dbus_message_iter_get_arg_type(&itervariant) != DBUS_TYPE_STRING) goto fail;
  1019. dbus_message_iter_get_basic (&itervariant, &state);
  1020.  
  1021. dev_path = (char *)dbus_message_get_path (msg);
  1022. debug_print ("state for %s: %s\n", dev_path, state);
  1023.  
  1024. //look for our thread
  1025. if (!head) return;
  1026. io_data = head;
  1027. do {
  1028. if (strcasecmp (dev_path, io_data->dev_path) == 0 &&
  1029. io_data->write == write)
  1030. break;
  1031. else io_data = io_data->hh.next;
  1032. } while (io_data && io_data != head);
  1033. if (!io_data) return;
  1034.  
  1035. //decode state & transition
  1036. new_state = transition = -1;
  1037. if ( strcasecmp (state, "connected") == 0 ) {
  1038. new_state = STATE_CONNECTED;
  1039. } else if ( strcasecmp (state, "playing") == 0 ) {
  1040. new_state = STATE_PLAYING;
  1041. //static void get_more(const void **start, size_t *size)
  1042. debug_print("state to playing\n");
  1043.  
  1044. pcm_set_frequency(BT_AUDIO_FREQ);
  1045. pcm_play_data(get_more, NULL, NULL, 0);
  1046.  
  1047. // mixer_channel_play_data(PCM_MIXER_BLUETOOTH_0, get_more,
  1048. // /*frame->pcm, frame->size*/NULL, 0);
  1049. } else if ( strcasecmp (state, "disconnected") == 0 ) {
  1050. new_state = STATE_DISCONNECTED;
  1051. }
  1052.  
  1053. if (new_state >= 0) {
  1054. transition = io_data->prev_state << 4 | new_state;
  1055. io_data->prev_state = new_state;
  1056. }
  1057.  
  1058. //our treatment of sink and source is a bit different
  1059. switch (write) {
  1060. case 0: // bt sink: bt --> alsa
  1061. when_to_acquire = STATE_CONNECTED << 4 | STATE_PLAYING;
  1062. when_to_release = STATE_PLAYING << 4 | STATE_CONNECTED;
  1063. break;
  1064.  
  1065. case 1: // bt source: alsa --> bt
  1066. when_to_acquire = STATE_DISCONNECTED << 4 | STATE_CONNECTED;
  1067. when_to_release = STATE_CONNECTED << 4 | STATE_DISCONNECTED;
  1068. break;
  1069. }
  1070.  
  1071. //acquire or release transport depending on the transitions
  1072. if (transition == when_to_acquire) {
  1073. if (transport_acquire (conn, io_data->transport_path, &io_data->fd, &io_data->read_mtu, &io_data->write_mtu)) {
  1074. debug_print ("fd: %d read mtu %d write mtu %d\n", io_data->fd, io_data->read_mtu, io_data->write_mtu);
  1075. io_thread_set_command (io_data, IO_CMD_RUNNING);
  1076. }
  1077. } else if (transition == when_to_release) {
  1078. transport_release (conn, io_data->transport_path);
  1079. io_thread_set_command (io_data, IO_CMD_IDLE);
  1080. }
  1081. return;
  1082.  
  1083. fail:
  1084. debug_print ("bad signal\n");
  1085. }
  1086.  
  1087.  
  1088.  
  1089. //////////////////////////////// IO THREAD HELPERS ////////////////////////////////
  1090.  
  1091.  
  1092. /*****************//**
  1093. * Send command to I/O thread in a thread-safe manner.
  1094. * Once given, it will also trigger I/O thread to start running (if it is not
  1095. * already is).
  1096. *
  1097. * Note: Once IO_CMD_TERMINATE is issued, it cannot be cancelled.
  1098. *
  1099. * @param [in] I/O thread control block
  1100. * @param [in] command to send
  1101. * @returns reply message (success or failure)
  1102. *********************/
  1103. void io_thread_set_command (io_thread_tcb_s *data, int command) {
  1104. pthread_mutex_lock (&data->mutex);
  1105. debug_print ("io cmd: %d\n", command);
  1106. if (data->command != IO_CMD_TERMINATE)
  1107. data->command = command;
  1108. pthread_mutex_unlock (&data->mutex);
  1109. pthread_cond_signal (&data->cond);
  1110. }
  1111.  
  1112. #include <pthread.h>
  1113. #include <sched.h>
  1114.  
  1115. /*****************//**
  1116. * Create an I/O thread.
  1117. * This will create the thread control block and the thread itself.
  1118. * The created thread is already running but in suspended state.
  1119. *
  1120. * @returns newly created thread control block
  1121. *********************/
  1122. void *io_thread_run(void *ptr);
  1123. io_thread_tcb_s *create_io_thread() {
  1124. io_thread_tcb_s *p;
  1125.  
  1126. pthread_attr_t tattr;
  1127. struct sched_param param;
  1128.  
  1129. /// set priority,
  1130. /*
  1131. (void) pthread_attr_init (&tattr);
  1132. (void) pthread_attr_getschedparam (&tattr, &param);
  1133. param.sched_priority = -20;
  1134. (void) pthread_attr_setschedparam (&tattr, &param);
  1135. */
  1136.  
  1137.  
  1138. p = malloc (sizeof (io_thread_tcb_s));
  1139. memset (p, 0, sizeof (io_thread_tcb_s));
  1140. pthread_cond_init (&p->cond, NULL);
  1141. pthread_mutex_init (&p->mutex, NULL);
  1142. pthread_create (&p->t_handle, NULL/*&tattr*/, io_thread_run, p);
  1143. return p;
  1144. }
  1145.  
  1146. /*****************//**
  1147. * Destroy and existing an I/O thread.
  1148. * This will stop the terminate the thread, wait until it is really terminated,
  1149. * release the resources held by the thread, then free the tcb itself.
  1150. *
  1151. * @param [in] thread control block
  1152. *********************/
  1153. void destroy_io_thread(io_thread_tcb_s *p) {
  1154. if (p) {
  1155. io_thread_set_command (p, IO_CMD_TERMINATE);
  1156. pthread_join (p->t_handle, NULL);
  1157. pthread_cond_destroy (&p->cond);
  1158. pthread_mutex_destroy (&p->mutex);
  1159. if (p->transport_path) {
  1160. free (p->transport_path);
  1161. p->transport_path = NULL;
  1162. }
  1163. if (p->dev_path) {
  1164. free (p->dev_path);
  1165. p->dev_path = NULL;
  1166. }
  1167. free (p);
  1168. }
  1169. }
  1170.  
  1171.  
  1172. //////////////////////////////// IO THREAD ////////////////////////////////
  1173.  
  1174. /*****************//**
  1175. * Read stdin, encode it, and write output to bluez stream output
  1176. * Encoding function is taken from pulseaudio 2.1
  1177. *
  1178. * @param [in] I/O thread control block
  1179. * @param [in] run_once global variable
  1180. * @param [out] quit global variable (if the app should quit)
  1181. *********************/
  1182. void stream_bt_output(io_thread_tcb_s *data) {
  1183. void *buf, *encode_buf;
  1184. size_t bufsize, encode_bufsize;
  1185. struct pollfd pollin = { 0, POLLIN, 0 }, pollout = { data->fd, POLLOUT, 0 };
  1186. int timeout;
  1187.  
  1188. debug_print ("write to bt\n");
  1189.  
  1190. // get buffers
  1191. encode_bufsize = data->write_mtu;
  1192. encode_buf = malloc (encode_bufsize);
  1193. bufsize = (encode_bufsize / sbc_get_frame_length (&data->sbc)) * // max frames allowed in a packet
  1194. sbc_get_codesize(&data->sbc); // ensure all of our source will fit in a single packet
  1195. buf = malloc (bufsize);
  1196. //debug_print ("encode_buf %d buf %d", encode_bufsize, bufsize);
  1197.  
  1198. // stream
  1199. while (data->command == IO_CMD_RUNNING) {
  1200. ssize_t readlen;
  1201.  
  1202. // wait until stdin has some data
  1203. //debug_print ("waiting stdin\n");
  1204. pthread_mutex_unlock (&data->mutex);
  1205. timeout = poll (&pollin, 1, 1000); //delay 1s to allow others to update our state
  1206. pthread_mutex_lock (&data->mutex);
  1207. if (timeout == 0) continue;
  1208. if (timeout < 0) {
  1209. fprintf (stderr, "bt_write/stdin: %d\n", errno);
  1210. break;
  1211. }
  1212.  
  1213. // read stdin
  1214. readlen = read (0, buf, bufsize);
  1215. if (readlen == 0) { // stream closed
  1216. data->command = IO_CMD_TERMINATE;
  1217. if (run_once) quit = 1;
  1218. continue;
  1219. }
  1220. if (readlen < 0) continue;
  1221.  
  1222. // encode bluetooth
  1223. // all of our source is guaranteed to fit in a single packet
  1224. //debug_print ("encoding\n");
  1225.  
  1226. struct rtp_header *header;
  1227. struct rtp_payload *payload;
  1228. size_t nbytes;
  1229.  
  1230. header = encode_buf;
  1231. payload = (struct rtp_payload*) ((uint8_t*) encode_buf + sizeof(*header));
  1232.  
  1233. void *p = buf;
  1234. void *d = encode_buf + sizeof(*header) + sizeof(*payload);
  1235. size_t to_write = encode_bufsize - sizeof(*header) - sizeof(*payload);
  1236. size_t to_encode = readlen;
  1237. unsigned frame_count = 0;
  1238.  
  1239. while (to_encode >= sbc_get_codesize(&data->sbc)) {
  1240. //fprintf (stderr, "%zu ", to_encode);
  1241. ssize_t written;
  1242. ssize_t encoded;
  1243.  
  1244. //debug_print ("%p %d %d\n", d, to_write, sbc_get_frame_length (&data->sbc));
  1245. encoded = sbc_encode(&data->sbc,
  1246. p, to_encode,
  1247. d, to_write,
  1248. &written);
  1249.  
  1250. if (encoded <= 0) {
  1251. fprintf (stderr, "SBC encoding error %zd\n", encoded);
  1252. break; // make do with what have
  1253. }
  1254.  
  1255. p = (uint8_t*) p + encoded;
  1256. to_encode -= encoded;
  1257. d = (uint8_t*) d + written;
  1258. to_write -= written;
  1259.  
  1260. frame_count++;
  1261. }
  1262.  
  1263. // encapsulate it in a2dp RTP packets
  1264. memset(encode_buf, 0, sizeof(*header) + sizeof(*payload));
  1265. header->v = 2;
  1266. header->pt = 1;
  1267. header->sequence_number = htons(data->seq_num++);
  1268. header->timestamp = htonl(data->timestamp);
  1269. header->ssrc = htonl(1);
  1270. payload->frame_count = frame_count;
  1271.  
  1272. // next timestamp
  1273. data->timestamp += sbc_get_frame_duration(&data->sbc) * frame_count;
  1274.  
  1275. // how much to output
  1276. nbytes = (uint8_t*) d - (uint8_t*) encode_buf;
  1277.  
  1278. //debug_print ("nbytes: %zu\n", nbytes);
  1279. if (!nbytes) break; // don't write if there is nothing to write
  1280.  
  1281. // wait until bluetooth is ready
  1282. while (data->command == IO_CMD_RUNNING) {
  1283. //debug_print ("waiting for bluetooth\n");
  1284. pthread_mutex_unlock (&data->mutex);
  1285. timeout = poll (&pollout, 1, 1000); //delay 1s to allow others to update our state
  1286. pthread_mutex_lock (&data->mutex);
  1287. if (timeout == 0) continue;
  1288. if (timeout < 0) fprintf (stderr, "bt_write/bluetooth: %d\n", errno);
  1289. break;
  1290. }
  1291.  
  1292. // write bluetooth
  1293. if (timeout > 0) {
  1294. //debug_print ("flush bluetooth\n");
  1295. write (data->fd, encode_buf, nbytes);
  1296. }
  1297. }
  1298.  
  1299. // cleanup
  1300. free (buf);
  1301. free (encode_buf);
  1302. }
  1303.  
  1304.  
  1305. /*****************//**
  1306. * Read bluez stream data input, decode it, and write output to stdout
  1307. * Decoding function is taken from pulseaudio 2.1
  1308. *
  1309. * @param [in] I/O thread control block
  1310. *********************/
  1311. void stream_bt_input(io_thread_tcb_s *data) {
  1312. void *buf/*, *decode_buf*/;
  1313. size_t bufsize/*, decode_bufsize*/;
  1314. struct pollfd pollin = { data->fd, POLLIN, 0 }, pollout = { 1, POLLOUT, 0 };
  1315. int timeout;
  1316.  
  1317. debug_print ("read from bt\n");
  1318.  
  1319. // get buffers
  1320. bufsize = data->read_mtu;
  1321. buf = malloc (bufsize);
  1322. decode_bufsize = (bufsize / sbc_get_frame_length (&data->sbc) + 1 ) * //max frames in a packet
  1323. sbc_get_codesize(&data->sbc);
  1324. decode_buf = malloc (decode_bufsize);
  1325. //debug_print ("codesize %d framelen %d", sbc_get_codesize(&data->sbc), sbc_get_frame_length(&data->sbc));
  1326.  
  1327. // stream
  1328. while (data->command == IO_CMD_RUNNING) {
  1329. //debug_print ("spinning\n");
  1330.  
  1331. ssize_t readlen=0;
  1332.  
  1333. // wait until bluetooth has some data
  1334. //debug_print ("waiting bluetooth\n");
  1335. pthread_mutex_unlock (&data->mutex);
  1336. // timeout = poll (&pollin, 1, 1000); //delay 1s to allow others to update our state
  1337. timeout = poll (&pollin, 1, BT_POLL_DELAY); //delay 1s to allow others to update our state
  1338. pthread_mutex_lock (&data->mutex);
  1339. if (timeout == 0) continue;
  1340. if (timeout < 0) {
  1341. fprintf (stderr, "bt_read/bluetooth: %d\n", errno);
  1342. break;
  1343. }
  1344.  
  1345. // read bluetooth
  1346. readlen = read (data->fd, buf, bufsize);
  1347. if (readlen == 0) { // stream closed
  1348. data->command = IO_CMD_TERMINATE;
  1349. continue;
  1350. }
  1351. if (readlen < 0) continue;
  1352.  
  1353.  
  1354.  
  1355.  
  1356. // decode a2dp/sbc from pulseaudio
  1357. //debug_print ("decoding\n");
  1358. void *p = buf + sizeof(struct rtp_header) + sizeof(struct rtp_payload);
  1359. size_t to_decode = readlen - sizeof(struct rtp_header) - sizeof(struct rtp_payload);
  1360. void *d = decode_buf;
  1361. size_t to_write = decode_bufsize;
  1362.  
  1363. while (to_decode > 0) {
  1364. size_t written;
  1365. size_t decoded;
  1366.  
  1367. decoded = sbc_decode(&data->sbc,
  1368. p, to_decode,
  1369. d, to_write,
  1370. &written);
  1371.  
  1372. if (decoded <= 0) {
  1373. fprintf (stderr, "SBC decoding error %zd\n", decoded);
  1374. break; // make do with what we have
  1375. }
  1376.  
  1377. p = (uint8_t*) p + decoded;
  1378. to_decode -= decoded;
  1379. // debug_print("want to write %d\n", written);
  1380. void *vp = d;
  1381.  
  1382. while (written > 0) {
  1383. struct frame_buffer *fb = NULL;
  1384.  
  1385. yield();
  1386.  
  1387. // get buffer
  1388. do {
  1389. pthread_mutex_unlock (&data->mutex);
  1390. fb = frame_buffer_get_writable();
  1391. if (fb == NULL)
  1392. sleep(HZ * FRAME_SECONDS * 3); // sleep for ~3 frames
  1393. pthread_mutex_lock (&data->mutex);
  1394. } while (fb == NULL);
  1395.  
  1396. // max size we can write
  1397. int len = MIN(written, FRAME_LEN - fb->written);
  1398.  
  1399. if (len > sizeof(int16_t)) {
  1400. /* Do not reset poweroff timer if it seems we are being fed silence */
  1401. if (((int16_t *)d)[0] != 0)
  1402. reset_poweroff_timer();
  1403. }
  1404. /*
  1405. written;
  1406. if (FRAME_LEN - fb->written < len)
  1407. len = FRAME_LEN - fb->written;
  1408. */
  1409. memcpy((uint8_t *)fb->data + fb->written, d, len);
  1410. fb->written += len;
  1411. frame_buffer_done_writing(fb);
  1412. vp = (uint8_t*) vp + len;
  1413.  
  1414. written -= len;
  1415. }
  1416.  
  1417. // debug_print("write done\n");
  1418.  
  1419. //d = (uint8_t*) d + written;
  1420. //to_write -= written;
  1421. //debug_print ("%zu ", decode_bufsize - to_write);
  1422. }
  1423. // debug_print ("\n");
  1424. /*
  1425. int write_i = 0;
  1426. //decode_bufsize - to_write;
  1427.  
  1428. while (data->command == IO_CMD_RUNNING && write_i < decode_bufsize - to_write) {
  1429. pthread_mutex_unlock (&data->mutex);
  1430. struct frame_buffer *fb = frame_buffer_get_writable();
  1431. if (fb == NULL)
  1432. sleep(HZ/10);
  1433. pthread_mutex_lock (&data->mutex);
  1434.  
  1435. if (fb == NULL)
  1436. continue;
  1437.  
  1438. int can_write = decode_bufsize - to_write - write_i;
  1439. if (
  1440. FRAME_LEN - fb->written
  1441. }*/
  1442.  
  1443.  
  1444. #if 0
  1445. // wait until stdout is ready
  1446. while (data->command == IO_CMD_RUNNING) {
  1447. //debug_print ("waiting for stdout\n");
  1448. pthread_mutex_unlock (&data->mutex);
  1449. timeout = poll (&pollout, 1, 1000); //delay 1s to allow others to update our state
  1450. pthread_mutex_lock (&data->mutex);
  1451. if (timeout == 0) continue;
  1452. else if (timeout < 0) fprintf (stderr, "bt_read/stdout: %d\n", errno);
  1453. break;
  1454. }
  1455.  
  1456. // write stdout
  1457. if (timeout > 0) {
  1458. gave_bytes += decode_bufsize - to_write;
  1459. decode_buf_fill = decode_bufsize - to_write;
  1460. // debug_print ("writing %d\n", decode_bufsize - to_write);
  1461. //debug_print ("flushing stdout\n");
  1462. /////write (1, decode_buf, decode_bufsize - to_write);
  1463. }
  1464. #endif
  1465. }
  1466. debug_print("exit loop\n");
  1467.  
  1468. // cleanup
  1469. free (buf);
  1470. free (decode_buf);
  1471. }
  1472.  
  1473. /*****************//**
  1474. * Main I/O thread function
  1475. * This function will perform actual streaming of data.
  1476. * It is simple: read the data from bluez' descriptor, and write to stdout!
  1477. *
  1478. * The rest is just management overhead.
  1479. *
  1480. * In output mode, the output (on stdout) will raw S16_LE, 44.1kHz, stereo/mono (depends on source).
  1481. * See "endpoint_select_configuration" if you want to change this.
  1482. * aplay -f cd can play this correctly
  1483. *
  1484. * In input mode, the input (on stdin) must be raw S16_LE, 48kHz, stereo/mono (depends on target).
  1485. * See "endpoint_select_configuration" if you want to change this.
  1486. * The encoding function is taken from pulseaudio 2.1 (simplified).
  1487. *
  1488. * @param [in] control-block for this thread.
  1489. * @returns NULL
  1490. *********************/
  1491. void *io_thread_run(void *ptr) {
  1492. io_thread_tcb_s *data = ptr;
  1493.  
  1494. // prepare
  1495. debug_print ("starting %p\n", ptr);
  1496. pthread_mutex_lock (&data->mutex);
  1497. sbc_init (&data->sbc, 0);
  1498.  
  1499. // run
  1500. while (1) {
  1501. yield();
  1502.  
  1503. switch (data->command) {
  1504. case IO_CMD_IDLE:
  1505. pthread_cond_wait (&data->cond, &data->mutex);
  1506. break;
  1507.  
  1508. case IO_CMD_RUNNING:
  1509. debug_print ("running %p\n", ptr);
  1510. setup_sbc (&data->sbc, &data->cap);
  1511. if (data->write)
  1512. stream_bt_output(data);
  1513. else
  1514. stream_bt_input(data);
  1515. break;
  1516.  
  1517. case IO_CMD_TERMINATE:
  1518. debug_print ("terminate %p\n", ptr);
  1519. goto end;
  1520. }
  1521.  
  1522. }
  1523.  
  1524. end:
  1525. // cleanup
  1526. sbc_finish(&data->sbc);
  1527. pthread_mutex_unlock (&data->mutex);
  1528. return NULL;
  1529. }
  1530. /*
  1531. #define BT_PCM_BUFFER_SIZE (320*5)
  1532.  
  1533. //////////////////////////////// MAIN ////////////////////////////////
  1534. int16_t bt_pcm_buffer[BT_PCM_BUFFER_SIZE];
  1535. */
  1536.  
  1537. #define BT_QUIT BUTTON_POWER
  1538. #define BT_FFWD BUTTON_RIGHT
  1539. #define BT_REWIND BUTTON_LEFT
  1540. #define BT_VOL_UP BUTTON_VOLUP
  1541. #define BT_VOL_DOWN BUTTON_VOLDOWN
  1542. #define BT_PLAYPAUSE BUTTON_SELECT
  1543.  
  1544. bool handle_rb() {
  1545. bool quit = false;
  1546. int vol;
  1547.  
  1548. switch (button_get(false))
  1549. {
  1550. case BUTTON_UP:
  1551. case BT_VOL_UP | BUTTON_REPEAT:
  1552. {
  1553. debug_print("vol up\n");
  1554. vol = global_settings.volume;
  1555. if (vol < sound_max(SOUND_VOLUME))
  1556. {
  1557. vol+=5;
  1558. sound_set(SOUND_VOLUME, vol);
  1559. global_settings.volume = vol;
  1560. }
  1561. break;
  1562. }
  1563.  
  1564. case BUTTON_DOWN:
  1565. case BT_VOL_DOWN | BUTTON_REPEAT:
  1566. {
  1567. vol = global_settings.volume;
  1568. if (vol > sound_min(SOUND_VOLUME))
  1569. {
  1570. vol-=5;
  1571. sound_set(SOUND_VOLUME, vol);
  1572. global_settings.volume = vol;
  1573. }
  1574. break;
  1575. }
  1576. /*
  1577. case MIDI_PLAYPAUSE:
  1578. {
  1579. if (is_playing)
  1580. {
  1581. midi_debug("Paused at %d:%02d\n", playing_time/60, playing_time%60);
  1582. is_playing = false;
  1583. rb->pcm_play_stop();
  1584. } else
  1585. {
  1586. midi_debug("Playing from %d:%02d\n", playing_time/60, playing_time%60);
  1587. is_playing = true;
  1588. rb->pcm_play_data(&get_more, NULL, NULL, 0);
  1589. }
  1590. break;
  1591. }
  1592. */
  1593. case BT_QUIT:
  1594. quit = true;
  1595. }
  1596. return quit;
  1597.  
  1598. }
  1599.  
  1600. void run_player() {
  1601. // Control variables
  1602. DBusConnection* system_bus;
  1603. char *bt_object; // bluetooth device objectpath
  1604. io_thread_tcb_s *io_threads_table = NULL; // hashtable of io_threads
  1605. int msg_waiting_time = -1; //default is wait forever
  1606.  
  1607. // scratch variables
  1608. DBusMessage *msg, *reply;
  1609. DBusError err;
  1610.  
  1611. quit = 0;
  1612.  
  1613. /*
  1614. // 0. check options
  1615. const struct option options[] = {
  1616. {"help", no_argument, 0, 'h' },
  1617. {"sink", no_argument, 0, 's' },
  1618. {"source", no_argument, 0, 'o' },
  1619. {"run-once", no_argument, 0, 'r' },
  1620. {0, 0, 0, 0 }
  1621. };
  1622. int option, run_sink=0, run_source=0;
  1623. while ((option = getopt_long (argc, argv, "h", (const struct option *) &options, NULL)) != -1) {
  1624. switch (option) {
  1625. case 'h':
  1626. fprintf (stderr,"Usage: a2dp-alsa [--sink|--source|--run-once] [hciX]\n");
  1627. return 0;
  1628. case 's':
  1629. debug_print ("run sink\n");
  1630. run_sink=1;
  1631. break;
  1632. case 'o':
  1633. debug_print ("run source\n");
  1634. run_source=1;
  1635. break;
  1636. case 'r':
  1637. debug_print ("run once\n");
  1638. run_once=1;
  1639. msg_waiting_time = 1000; //1000 ms = 1 s
  1640. break;
  1641. }
  1642. }
  1643.  
  1644. */
  1645. // msg_waiting_time = 200;
  1646. msg_waiting_time = 50;
  1647. /*
  1648. if (!system("/bin/umount /dev/mmcblk0p1")) {
  1649. sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/lun/file", "/dev/mmcblk0");
  1650. } else {
  1651. return 1;
  1652. }
  1653. */
  1654. frame_buffer_init();
  1655.  
  1656. // system("/bin/sync");
  1657.  
  1658. // bt is acting up
  1659. for (int i = 0; i < 2; i++) {
  1660. debug_print ("bt_disable\n");
  1661. system("/usr/bin/bt_disable");
  1662.  
  1663. debug_print ("bt_enable\n");
  1664. system("/usr/bin/bt_enable");
  1665. }
  1666. system("/usr/bin/obex_start");
  1667.  
  1668.  
  1669. // 1. init - get bus and adapter
  1670. debug_print ("a2dp started\n");
  1671. dbus_threads_init_default();
  1672. dbus_error_init(&err);
  1673. if (get_system_bus(&system_bus)) {
  1674. if (!get_bluetooth_object(system_bus, /*argv[optind]*/"hci0", &bt_object)){
  1675. debug_print ("no object\n");
  1676.  
  1677. return 1;
  1678. }
  1679. } else {
  1680. debug_print ("no bus\n");
  1681. return 1;
  1682. }
  1683. // 2. register endpoint
  1684. // if (run_sink)
  1685. int run_sink = media_register_endpoint(system_bus, bt_object, A2DP_SINK_ENDPOINT, A2DP_SINK_UUID); // bt --> alsa
  1686. if (run_sink == 0) {
  1687. debug_print ("no sink\n");
  1688. return;
  1689. }
  1690.  
  1691. /*
  1692. if (run_source)
  1693. run_source = media_register_endpoint(system_bus, bt_object, A2DP_SOURCE_ENDPOINT, A2DP_SOURCE_UUID); // alsa --> bt
  1694. if (!run_source && !run_sink) return 1;
  1695. */
  1696. // 3. capture signals
  1697. // if (run_sink) { // bt --> alsa
  1698. dbus_bus_add_match (system_bus, "type='signal',interface='org.bluez.AudioSource',member='PropertyChanged'", &err);
  1699. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  1700. /* }
  1701. if (run_source) { // alsa --> bt
  1702. dbus_bus_add_match (system_bus, "type='signal',interface='org.bluez.AudioSink',member='PropertyChanged'", &err);
  1703. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  1704. }
  1705. */
  1706.  
  1707.  
  1708. debug_print ("enter main loop\n");
  1709.  
  1710. // 4. main-loop
  1711. while (!quit && dbus_connection_read_write (system_bus, msg_waiting_time)) { //block
  1712. yield();
  1713.  
  1714. //quit = handle_rb();
  1715. if (handle_rb()) {
  1716. // 6. unregister endpoint
  1717. debug_print ("unregister endpoint\n");
  1718. if (media_unregister_endpoint(system_bus, bt_object, A2DP_SINK_ENDPOINT) == 0) {
  1719. debug_print ("unregister failed\n");
  1720. }
  1721. debug_print ("unregister done\n");
  1722. }
  1723.  
  1724. while (!quit && (msg = dbus_connection_pop_message (system_bus))) { //get the message
  1725. // dispatch
  1726. reply = NULL;
  1727. if (dbus_message_is_signal (msg, "org.bluez.AudioSource", "PropertyChanged")) {// bt --> alsa
  1728. debug_print("source prpba change\n");
  1729. audiosource_property_changed (system_bus, msg, 0, &io_threads_table);
  1730. } else if (dbus_message_is_signal (msg, "org.bluez.AudioSink", "PropertyChanged")) {// alsa --> bt
  1731. debug_print("sink prob change\n");
  1732. audiosink_property_changed (system_bus, msg, 1, &io_threads_table);
  1733. } else if (dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "SetConfiguration")) {
  1734. debug_print("set conf\n");
  1735. reply = endpoint_set_configuration (msg, &io_threads_table);
  1736. } else if (dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "SelectConfiguration")) {
  1737. debug_print("select config\n");
  1738. reply = endpoint_select_configuration (msg);
  1739. } else if(dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "ClearConfiguration")) {
  1740. debug_print("clear config\n");
  1741. reply = endpoint_clear_configuration (msg, &io_threads_table);
  1742. } else if (dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "Release")) {
  1743. debug_print("relesas\n");
  1744. reply = endpoint_release (msg); quit=1;
  1745.  
  1746. }
  1747. if (reply) {
  1748. // send the reply
  1749. dbus_connection_send(system_bus, reply, NULL);
  1750. dbus_message_unref(reply);
  1751. }
  1752. dbus_message_unref(msg);
  1753. }
  1754. }
  1755. debug_print ("exit main loop\n");
  1756.  
  1757. // 5. destroy all existing I/O threads
  1758. if (io_threads_table) {
  1759. io_thread_tcb_s *p = io_threads_table, *next;
  1760. do {
  1761. next = p->hh.next;
  1762. destroy_io_thread (p);
  1763. p = next;
  1764. } while (p && p != io_threads_table);
  1765. }
  1766.  
  1767.  
  1768. // 7. cleanup and exit
  1769. dbus_connection_flush (system_bus);
  1770. dbus_connection_unref (system_bus);
  1771. debug_print ("a2dp ended\n\n");
  1772. /*
  1773. sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/lun/file", "");
  1774.  
  1775. system("/bin/mount /dev/mmcblk0p1 /mnt/sd_0");
  1776. */
  1777. return 0;
  1778. }
  1779.  
  1780. void bluetooth_screen(void)
  1781. {
  1782. fprintf (stderr,"I am here!!!\n");
  1783.  
  1784. //pcm_play_data(get_more, NULL, NULL, 0);
  1785.  
  1786. run_player();
  1787. // mixer_channel_play_data(PCM_MIXER_BLUETOOTH_0, get_more,
  1788. // /*frame->pcm, frame->size*/NULL, 0);
  1789.  
  1790.  
  1791. // for (;;) {
  1792. //int button = skin_wait_for_action(
  1793. // }
  1794. }
  1795.  
  1796. int mif_main(int argc, char** argv)
  1797. {
  1798. // Control variables
  1799. DBusConnection* system_bus;
  1800. char *bt_object; // bluetooth device objectpath
  1801. io_thread_tcb_s *io_threads_table = NULL; // hashtable of io_threads
  1802. int msg_waiting_time = -1; //default is wait forever
  1803.  
  1804. // scratch variables
  1805. DBusMessage *msg, *reply;
  1806. DBusError err;
  1807.  
  1808. // 0. check options
  1809. const struct option options[] = {
  1810. {"help", no_argument, 0, 'h' },
  1811. {"sink", no_argument, 0, 's' },
  1812. {"source", no_argument, 0, 'o' },
  1813. {"run-once", no_argument, 0, 'r' },
  1814. {0, 0, 0, 0 }
  1815. };
  1816. int option, run_sink=0, run_source=0;
  1817. while ((option = getopt_long (argc, argv, "h", (const struct option *) &options, NULL)) != -1) {
  1818. switch (option) {
  1819. case 'h':
  1820. fprintf (stderr,"Usage: a2dp-alsa [--sink|--source|--run-once] [hciX]\n");
  1821. return 0;
  1822. case 's':
  1823. debug_print ("run sink\n");
  1824. run_sink=1;
  1825. break;
  1826. case 'o':
  1827. debug_print ("run source\n");
  1828. run_source=1;
  1829. break;
  1830. case 'r':
  1831. debug_print ("run once\n");
  1832. run_once=1;
  1833. msg_waiting_time = 1000; //1000 ms = 1 s
  1834. break;
  1835. }
  1836. }
  1837.  
  1838. // 1. init - get bus and adapter
  1839. debug_print ("a2dp started\n");
  1840. dbus_threads_init_default();
  1841. dbus_error_init(&err);
  1842. if (get_system_bus(&system_bus)) {
  1843. if (!get_bluetooth_object(system_bus, argv[optind], &bt_object)) return 1;
  1844. } else return 1;
  1845.  
  1846. // 2. register endpoint
  1847. if (run_sink)
  1848. run_sink = media_register_endpoint(system_bus, bt_object, A2DP_SINK_ENDPOINT, A2DP_SINK_UUID); // bt --> alsa
  1849. if (run_source)
  1850. run_source = media_register_endpoint(system_bus, bt_object, A2DP_SOURCE_ENDPOINT, A2DP_SOURCE_UUID); // alsa --> bt
  1851. if (!run_source && !run_sink) return 1;
  1852.  
  1853. // 3. capture signals
  1854. if (run_sink) { // bt --> alsa
  1855. dbus_bus_add_match (system_bus, "type='signal',interface='org.bluez.AudioSource',member='PropertyChanged'", &err);
  1856. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  1857. }
  1858. if (run_source) { // alsa --> bt
  1859. dbus_bus_add_match (system_bus, "type='signal',interface='org.bluez.AudioSink',member='PropertyChanged'", &err);
  1860. handle_dbus_error (&err, __FUNCTION__, __LINE__);
  1861. }
  1862.  
  1863. // 4. main-loop
  1864. while (!quit && dbus_connection_read_write (system_bus, msg_waiting_time)) { //block
  1865. while (!quit && (msg = dbus_connection_pop_message (system_bus))) { //get the message
  1866. // dispatch
  1867. reply = NULL;
  1868. if (dbus_message_is_signal (msg, "org.bluez.AudioSource", "PropertyChanged")) // bt --> alsa
  1869. audiosource_property_changed (system_bus, msg, 0, &io_threads_table);
  1870. else if (dbus_message_is_signal (msg, "org.bluez.AudioSink", "PropertyChanged")) // alsa --> bt
  1871. audiosink_property_changed (system_bus, msg, 1, &io_threads_table);
  1872. else if (dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "SetConfiguration"))
  1873. reply = endpoint_set_configuration (msg, &io_threads_table);
  1874. else if (dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "SelectConfiguration"))
  1875. reply = endpoint_select_configuration (msg);
  1876. else if(dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "ClearConfiguration"))
  1877. reply = endpoint_clear_configuration (msg, &io_threads_table);
  1878. else if (dbus_message_is_method_call (msg, "org.bluez.MediaEndpoint", "Release"))
  1879. { reply = endpoint_release (msg); quit=1; }
  1880. if (reply) {
  1881. // send the reply
  1882. dbus_connection_send(system_bus, reply, NULL);
  1883. dbus_message_unref(reply);
  1884. }
  1885. dbus_message_unref(msg);
  1886. }
  1887. }
  1888.  
  1889. // 5. destroy all existing I/O threads
  1890. if (io_threads_table) {
  1891. io_thread_tcb_s *p = io_threads_table, *next;
  1892. do {
  1893. next = p->hh.next;
  1894. destroy_io_thread (p);
  1895. p = next;
  1896. } while (p && p != io_threads_table);
  1897. }
  1898.  
  1899. // 6. cleanup and exit
  1900. dbus_connection_flush (system_bus);
  1901. dbus_connection_unref (system_bus);
  1902. debug_print ("a2dp ended\n\n");
  1903. return 0;
  1904. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement