]> code.delx.au - pulseaudio/blobdiff - src/modules/bluetooth/module-bluetooth-device.c
core: make fixed latency dynamically changeable
[pulseaudio] / src / modules / bluetooth / module-bluetooth-device.c
index 40093cf2e798482eec50b610df7efbfcfc83ad7c..93b14a1203232f249389658713f06f57d99aa4da 100644 (file)
 #include <linux/sockios.h>
 #include <arpa/inet.h>
 
-#include <pulse/xmalloc.h>
-#include <pulse/timeval.h>
-#include <pulse/sample.h>
 #include <pulse/i18n.h>
+#include <pulse/rtclock.h>
+#include <pulse/sample.h>
+#include <pulse/timeval.h>
+#include <pulse/xmalloc.h>
 
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
+#include <pulsecore/core-rtclock.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/socket-util.h>
@@ -44,7 +46,6 @@
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
 #include <pulsecore/time-smoother.h>
-#include <pulsecore/rtclock.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/dbus-shared.h>
 
@@ -773,7 +774,7 @@ static int start_stream_fd(struct userdata *u) {
                 TRUE,
                 TRUE,
                 10,
-                pa_rtclock_usec(),
+                pa_rtclock_now(),
                 TRUE);
 
     return 0;
@@ -867,20 +868,20 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             if (u->read_smoother) {
                 pa_usec_t wi, ri;
 
-                ri = pa_smoother_get(u->read_smoother, pa_rtclock_usec());
+                ri = pa_smoother_get(u->read_smoother, pa_rtclock_now());
                 wi = pa_bytes_to_usec(u->write_index + u->block_size, &u->sample_spec);
 
                 *((pa_usec_t*) data) = wi > ri ? wi - ri : 0;
             } else {
                 pa_usec_t ri, wi;
 
-                ri = pa_rtclock_usec() - u->started_at;
+                ri = pa_rtclock_now() - u->started_at;
                 wi = pa_bytes_to_usec(u->write_index, &u->sample_spec);
 
                 *((pa_usec_t*) data) = wi > ri ? wi - ri : 0;
             }
 
-            *((pa_usec_t*) data) += u->sink->fixed_latency;
+            *((pa_usec_t*) data) += u->sink->thread_info.fixed_latency;
             return 0;
         }
     }
@@ -912,7 +913,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                         stop_stream_fd(u);
 
                     if (u->read_smoother)
-                        pa_smoother_pause(u->read_smoother, pa_rtclock_usec());
+                        pa_smoother_pause(u->read_smoother, pa_rtclock_now());
                     break;
 
                 case PA_SOURCE_IDLE:
@@ -939,10 +940,10 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
         case PA_SOURCE_MESSAGE_GET_LATENCY: {
             pa_usec_t wi, ri;
 
-            wi = pa_smoother_get(u->read_smoother, pa_rtclock_usec());
+            wi = pa_smoother_get(u->read_smoother, pa_rtclock_now());
             ri = pa_bytes_to_usec(u->read_index, &u->sample_spec);
 
-            *((pa_usec_t*) data) = (wi > ri ? wi - ri : 0) + u->source->fixed_latency;
+            *((pa_usec_t*) data) = (wi > ri ? wi - ri : 0) + u->source->thread_info.fixed_latency;
             return 0;
         }
 
@@ -1086,7 +1087,7 @@ static int hsp_process_push(struct userdata *u) {
 
         if (!found_tstamp) {
             pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!");
-            tstamp = pa_rtclock_usec();
+            tstamp = pa_rtclock_now();
         }
 
         pa_smoother_put(u->read_smoother, tstamp, pa_bytes_to_usec(u->read_index, &u->sample_spec));
@@ -1265,7 +1266,6 @@ static void thread_func(void *userdata) {
         goto fail;
 
     pa_thread_mq_install(&u->thread_mq);
-    pa_rtpoll_install(u->rtpoll);
 
     for (;;) {
         struct pollfd *pollfd;
@@ -1309,7 +1309,7 @@ static void thread_func(void *userdata) {
                     /* Hmm, there is no input stream we could synchronize
                      * to. So let's do things by time */
 
-                    time_passed = pa_rtclock_usec() - u->started_at;
+                    time_passed = pa_rtclock_now() - u->started_at;
                     audio_sent = pa_bytes_to_usec(u->write_index, &u->sample_spec);
 
                     if (audio_sent <= time_passed) {
@@ -1341,7 +1341,7 @@ static void thread_func(void *userdata) {
                     int n_written;
 
                     if (u->write_index <= 0)
-                        u->started_at = pa_rtclock_usec();
+                        u->started_at = pa_rtclock_now();
 
                     if (u->profile == PROFILE_A2DP) {
                         if ((n_written = a2dp_process_render(u)) < 0)
@@ -1351,17 +1351,20 @@ static void thread_func(void *userdata) {
                             goto fail;
                     }
 
+                    if (n_written == 0)
+                        pa_log("Broken kernel: we got EAGAIN on write() after POLLOUT!");
+
                     do_write -= n_written;
                     writable = FALSE;
                 }
 
-                if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && do_write <= 0) {
+                if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && do_write <= 0 && writable) {
                     pa_usec_t time_passed, next_write_at, sleep_for;
 
                     /* Hmm, there is no input stream we could synchronize
                      * to. So let's estimate when we need to wake up the latest */
 
-                    time_passed = pa_rtclock_usec() - u->started_at;
+                    time_passed = pa_rtclock_now() - u->started_at;
                     next_write_at = pa_bytes_to_usec(u->write_index, &u->sample_spec);
                     sleep_for = time_passed < next_write_at ? next_write_at - time_passed : 0;
 
@@ -1920,7 +1923,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
 
     if (!(device = pa_bluetooth_discovery_get_by_path(u->discovery, u->path))) {
         pa_log_error("Failed to get device object.");
-        return -1;
+        return -PA_ERR_IO;
     }
 
     /* The state signal is sent by bluez, so it is racy to check
@@ -1930,15 +1933,15 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
        module will be unloaded. */
     if (device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) {
         pa_log_warn("HSP is not connected, refused to switch profile");
-        return -1;
+        return -PA_ERR_IO;
     }
     else if (device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP) {
         pa_log_warn("A2DP is not connected, refused to switch profile");
-        return -1;
+        return -PA_ERR_IO;
     }
 
     if (u->sink) {
-        inputs = pa_sink_move_all_start(u->sink);
+        inputs = pa_sink_move_all_start(u->sink, NULL);
 #ifdef NOKIA
         if (!USE_SCO_OVER_PCM(u))
 #endif
@@ -1946,7 +1949,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
     }
 
     if (u->source) {
-        outputs = pa_source_move_all_start(u->source);
+        outputs = pa_source_move_all_start(u->source, NULL);
 #ifdef NOKIA
         if (!USE_SCO_OVER_PCM(u))
 #endif
@@ -2082,6 +2085,15 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
     u->card->userdata = u;
     u->card->set_profile = card_set_profile;
 
+    d = PA_CARD_PROFILE_DATA(u->card->active_profile);
+
+    if ((device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) ||
+        (device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP)) {
+        pa_log_warn("Default profile not connected, selecting off profile");
+        u->card->active_profile = pa_hashmap_get(u->card->profiles, "off");
+        u->card->save_profile = FALSE;
+    }
+
     d = PA_CARD_PROFILE_DATA(u->card->active_profile);
     u->profile = *d;