diff --git a/dacp.c b/dacp.c
index ba43689a5..4ba7a8289 100644
--- a/dacp.c
+++ b/dacp.c
@@ -121,6 +121,7 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
// 495 Error receiving response
// 494 This client is already busy
// 493 Client failed to send a message
+ // 492 Argement out of range
// try to do this transaction on the DACP server, but don't wait for more than 20 ms to be allowed
// to do it.
@@ -162,7 +163,7 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
// only do this one at a time -- not sure it is necessary, but better safe than sorry
-// int mutex_reply = pthread_mutex_timedlock(&dacp_conversation_lock, &mutex_wait_time);
+ // int mutex_reply = pthread_mutex_timedlock(&dacp_conversation_lock, &mutex_wait_time);
int mutex_reply = pthread_mutex_lock(&dacp_conversation_lock);
if (mutex_reply == 0) {
@@ -662,12 +663,12 @@ int dacp_get_client_volume(int32_t *result) {
}
int dacp_set_include_speaker_volume(int64_t machine_number, int32_t vo) {
- debug(1, "dacp_set_include_speaker_volume to %" PRId32 ".", vo);
+ debug(2, "dacp_set_include_speaker_volume to %" PRId32 ".", vo);
char message[1000];
memset(message, 0, sizeof(message));
sprintf(message, "setproperty?include-speaker-id=%" PRId64 "&dmcp.volume=%" PRId32 "",
machine_number, vo);
- debug(1, "sending \"%s\"", message);
+ debug(2, "sending \"%s\"", message);
return send_simple_dacp_command(message);
// should return 204
}
@@ -677,7 +678,7 @@ int dacp_set_speaker_volume(int64_t machine_number, int32_t vo) {
memset(message, 0, sizeof(message));
sprintf(message, "setproperty?speaker-id=%" PRId64 "&dmcp.volume=%" PRId32 "", machine_number,
vo);
- debug(1, "sending \"%s\"", message);
+ debug(2, "sending \"%s\"", message);
return send_simple_dacp_command(message);
// should return 204
}
@@ -852,3 +853,108 @@ int dacp_get_volume(int32_t *the_actual_volume) {
}
return http_response;
}
+
+int dacp_set_volume(int32_t vo) {
+ int http_response = 492; // argument out of range
+ if ((vo >= 0) && (vo <= 100)) {
+ // get the information we need -- the absolute volume, the speaker list, our ID
+ struct dacp_speaker_stuff speaker_info[50];
+ int32_t overall_volume;
+ http_response = dacp_get_client_volume(&overall_volume);
+ if (http_response == 200) {
+ int speaker_count;
+ http_response = dacp_get_speaker_list((dacp_spkr_stuff *)&speaker_info, 50, &speaker_count);
+ if (http_response == 200) {
+ // get our machine number
+ uint16_t *hn = (uint16_t *)config.hw_addr;
+ uint32_t *ln = (uint32_t *)(config.hw_addr + 2);
+ uint64_t t1 = ntohs(*hn);
+ uint64_t t2 = ntohl(*ln);
+ int64_t machine_number = (t1 << 32) + t2; // this form is useful
+
+ // Let's find our own speaker in the array and pick up its relative volume
+ int i;
+ int32_t active_speakers = 0;
+ for (i = 0; i < speaker_count; i++) {
+ if (speaker_info[i].speaker_number == machine_number) {
+ debug(2, "Our speaker number found: %ld with relative volume.", machine_number,
+ speaker_info[i].volume);
+ }
+ if (speaker_info[i].active == 1) {
+ active_speakers++;
+ }
+ }
+
+ if (active_speakers == 1) {
+ // must be just this speaker
+ debug(2, "Remote-setting volume to %d on just one speaker.", vo);
+ http_response = dacp_set_include_speaker_volume(machine_number, vo);
+ } else if (active_speakers == 0) {
+ debug(2, "No speakers!");
+ } else {
+ debug(2, "Speakers: %d, active: %d", speaker_count, active_speakers);
+ if (vo >= overall_volume) {
+ debug(2, "Multiple speakers active, but desired new volume is highest");
+ http_response = dacp_set_include_speaker_volume(machine_number, vo);
+ } else {
+ // the desired volume is less than the current overall volume and there is more than
+ // one
+ // speaker
+ // we must find out the highest other speaker volume.
+ // If the desired volume is less than it, we must set the current_overall volume to
+ // that
+ // highest volume
+ // and set our volume relative to it.
+ // If the desired volume is greater than the highest current volume, then we can just
+ // go
+ // ahead
+ // with dacp_set_include_speaker_volume, setting the new current overall volume to the
+ // desired new level
+ // with the speaker at 100%
+
+ int32_t highest_other_volume = 0;
+ for (i = 0; i < speaker_count; i++) {
+ if ((speaker_info[i].speaker_number != machine_number) &&
+ (speaker_info[i].active == 1) &&
+ (speaker_info[i].volume > highest_other_volume)) {
+ highest_other_volume = speaker_info[i].volume;
+ }
+ }
+ highest_other_volume = (highest_other_volume * overall_volume + 50) / 100;
+ if (highest_other_volume <= vo) {
+ debug(2,
+ "Highest other volume %d is less than or equal to the desired new volume %d.",
+ highest_other_volume, vo);
+ http_response = dacp_set_include_speaker_volume(machine_number, vo);
+ } else {
+ debug(2, "Highest other volume %d is greater than the desired new volume %d.",
+ highest_other_volume, vo);
+ // if the present overall volume is higher than the highest other volume at present,
+ // then bring it down to it.
+ if (overall_volume > highest_other_volume) {
+ debug(2, "Lower overall volume to new highest volume.");
+ http_response = dacp_set_include_speaker_volume(
+ machine_number,
+ highest_other_volume); // set the overall volume to the highest one
+ }
+ int32_t desired_relative_volume =
+ (vo * 100 + (highest_other_volume / 2)) / highest_other_volume;
+ debug(2, "Set our speaker volume relative to the highest volume.");
+ http_response = dacp_set_speaker_volume(
+ machine_number,
+ desired_relative_volume); // set the overall volume to the highest one
+ }
+ }
+ }
+ } else {
+ debug(2, "Can't get speakers list");
+ }
+ } else {
+ debug(2, "Can't get client volume");
+ }
+
+ } else {
+ debug(2, "Invalid volume: %d -- ignored.", vo);
+ }
+ return http_response;
+}
diff --git a/dacp.h b/dacp.h
index bd43300c6..1a04e0166 100644
--- a/dacp.h
+++ b/dacp.h
@@ -32,3 +32,4 @@ int dacp_set_include_speaker_volume(int64_t machine_number, int32_t vo);
int dacp_get_client_volume(int32_t *result);
int dacp_get_volume(
int32_t *the_actual_volume); // get the speaker volume information from the DACP source
+int dacp_set_volume(int32_t vo); // set the volume of our speaker
diff --git a/dbus-service.c b/dbus-service.c
index a9b7f67df..753d62180 100644
--- a/dbus-service.c
+++ b/dbus-service.c
@@ -44,118 +44,12 @@ gboolean notify_loudness_threshold_callback(ShairportSync *skeleton,
return TRUE;
}
-gboolean notify_volume_callback(ShairportSync *skeleton,
- __attribute__((unused)) gpointer user_data) {
- metadata_hub_read_prolog();
- int md_speaker_volume = metadata_store.speaker_volume;
- metadata_hub_read_epilog();
- gint gvo = shairport_sync_get_volume(skeleton);
- int32_t vo = gvo;
- if ((vo >= 0) && (vo <= 100)) {
- if (vo !=
- md_speaker_volume) { // this is to stop an infinite loop of setting->checking->setting...
- // get the information we need -- the absolute volume, the speaker list, our ID
- struct dacp_speaker_stuff speaker_info[50];
- int32_t overall_volume;
- int http_response = dacp_get_client_volume(&overall_volume);
- if (http_response == 200) {
- int speaker_count;
- http_response = dacp_get_speaker_list((dacp_spkr_stuff *)&speaker_info, 50, &speaker_count);
- if (http_response == 200) {
- // get our machine number
- uint16_t *hn = (uint16_t *)config.hw_addr;
- uint32_t *ln = (uint32_t *)(config.hw_addr + 2);
- uint64_t t1 = ntohs(*hn);
- uint64_t t2 = ntohl(*ln);
- int64_t machine_number = (t1 << 32) + t2; // this form is useful
-
- // Let's find our own speaker in the array and pick up its relative volume
- int i;
- int32_t active_speakers = 0;
- for (i = 0; i < speaker_count; i++) {
- if (speaker_info[i].speaker_number == machine_number) {
- debug(2, "Our speaker number found: %ld with relative volume.", machine_number,
- speaker_info[i].volume);
- }
- if (speaker_info[i].active == 1) {
- active_speakers++;
- }
- }
-
- if (active_speakers == 1) {
- // must be just this speaker
- debug(2, "Remote-setting volume to %d on just one speaker.", vo);
- dacp_set_include_speaker_volume(machine_number, vo);
- } else if (active_speakers == 0) {
- debug(2, "No speakers!");
- } else {
- debug(2, "Speakers: %d, active: %d", speaker_count, active_speakers);
- if (vo >= overall_volume) {
- debug(2, "Multiple speakers active, but desired new volume is highest");
- dacp_set_include_speaker_volume(machine_number, vo);
- } else {
- // the desired volume is less than the current overall volume and there is more than
- // one
- // speaker
- // we must find out the highest other speaker volume.
- // If the desired volume is less than it, we must set the current_overall volume to
- // that
- // highest volume
- // and set our volume relative to it.
- // If the desired volume is greater than the highest current volume, then we can just
- // go
- // ahead
- // with dacp_set_include_speaker_volume, setting the new current overall volume to the
- // desired new level
- // with the speaker at 100%
-
- int32_t highest_other_volume = 0;
- for (i = 0; i < speaker_count; i++) {
- if ((speaker_info[i].speaker_number != machine_number) &&
- (speaker_info[i].active == 1) &&
- (speaker_info[i].volume > highest_other_volume)) {
- highest_other_volume = speaker_info[i].volume;
- }
- }
- highest_other_volume = (highest_other_volume * overall_volume + 50) / 100;
- if (highest_other_volume <= vo) {
- debug(2,
- "Highest other volume %d is less than or equal to the desired new volume %d.",
- highest_other_volume, vo);
- dacp_set_include_speaker_volume(machine_number, vo);
- } else {
- debug(2, "Highest other volume %d is greater than the desired new volume %d.",
- highest_other_volume, vo);
- // if the present overall volume is higher than the highest other volume at present,
- // then bring it down to it.
- if (overall_volume > highest_other_volume) {
- debug(2, "Lower overall volume to new highest volume.");
- dacp_set_include_speaker_volume(
- machine_number,
- highest_other_volume); // set the overall volume to the highest one
- }
- int32_t desired_relative_volume =
- (vo * 100 + (highest_other_volume / 2)) / highest_other_volume;
- debug(2, "Set our speaker volume relative to the highest volume.");
- dacp_set_speaker_volume(
- machine_number,
- desired_relative_volume); // set the overall volume to the highest one
- }
- }
- }
- } else {
- debug(2, "Can't get speakers list");
- }
- } else {
- debug(2, "Can't get client volume");
- }
- } // else {
- // debug(1, "No need to remote-set volume to %d, as it is already set to this value.", vo);
- // }
-
- } else {
- debug(2, "Invalid volume: %d -- ignored.", vo);
- }
+static gboolean on_handle_set_volume(ShairportSync *skeleton, GDBusMethodInvocation *invocation,
+ const gint volume,
+ __attribute__((unused)) gpointer user_data) {
+ // debug(1, "1 Set volume to d.", volume);
+ dacp_set_volume(volume);
+ shairport_sync_complete_set_volume(skeleton, invocation);
return TRUE;
}
@@ -194,10 +88,10 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name
G_CALLBACK(notify_loudness_filter_active_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::loudness-threshold",
G_CALLBACK(notify_loudness_threshold_callback), NULL);
- g_signal_connect(shairportSyncSkeleton, "notify::volume", G_CALLBACK(notify_volume_callback),
- &metadata_store);
g_signal_connect(shairportSyncSkeleton, "handle-remote-command",
G_CALLBACK(on_handle_remote_command), NULL);
+ g_signal_connect(shairportSyncSkeleton, "handle-set-volume", G_CALLBACK(on_handle_set_volume),
+ NULL);
add_metadata_watcher(dbus_metadata_watcher, NULL);
diff --git a/org.gnome.ShairportSync.xml b/org.gnome.ShairportSync.xml
index 8bba3609d..5d5da742b 100644
--- a/org.gnome.ShairportSync.xml
+++ b/org.gnome.ShairportSync.xml
@@ -3,9 +3,12 @@
-
+
+
+
+
diff --git a/org.mpris.MediaPlayer2.Player.xml b/org.mpris.MediaPlayer2.Player.xml
index 8ef73584a..72362379b 100755
--- a/org.mpris.MediaPlayer2.Player.xml
+++ b/org.mpris.MediaPlayer2.Player.xml
@@ -29,7 +29,7 @@
-
+
diff --git a/shairport-sync-dbus-test-client.c b/shairport-sync-dbus-test-client.c
index 05ec5f7bb..eb464b02c 100644
--- a/shairport-sync-dbus-test-client.c
+++ b/shairport-sync-dbus-test-client.c
@@ -132,13 +132,13 @@ int main(int argc, char *argv[]) {
g_print("Starting test...\n");
- shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 20);
+ shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 20, NULL, NULL, 0);
sleep(5);
- shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 100);
+ shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 100, NULL, NULL, 0);
sleep(5);
- shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 40);
+ shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 40, NULL, NULL, 0);
sleep(5);
- shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 60);
+ shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 60, NULL, NULL, 0);
// sleep(1);
/*
shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 10);