2 * This file is part of Shairport Sync.
3 * Copyright (c) Mike Brady 2019
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "dbus-interface.h"
34 void on_properties_changed(__attribute__((unused
)) GDBusProxy
*proxy
, GVariant
*changed_properties
,
35 const gchar
*const *invalidated_properties
, gpointer user_data
) {
36 /* Note that we are guaranteed that changed_properties and
37 * invalidated_properties are never NULL
40 if (g_variant_n_children(changed_properties
) > 0) {
44 g_print(" *** Properties Changed:\n");
45 g_variant_get(changed_properties
, "a{sv}", &iter
);
46 while (g_variant_iter_loop(iter
, "{&sv}", &key
, &value
)) {
48 value_str
= g_variant_print(value
, TRUE
);
50 g_print(" %s.%s -> %s\n", (char *)user_data
, key
, value_str
);
52 g_print(" %s -> %s\n", key
, value_str
);
55 g_variant_iter_free(iter
);
58 if (g_strv_length((GStrv
)invalidated_properties
) > 0) {
60 g_print(" *** Properties Invalidated:\n");
61 for (n
= 0; invalidated_properties
[n
] != NULL
; n
++) {
62 const gchar
*key
= invalidated_properties
[n
];
63 g_print(" %s\n", key
);
68 void notify_loudness_callback(ShairportSync
*proxy
, __attribute__((unused
)) gpointer user_data
) {
69 // printf("\"notify_loudness_callback\" called with a gpointer of
70 // %lx.\n",(int64_t)user_data);
71 gboolean ebl
= shairport_sync_get_loudness(proxy
);
73 printf("Client reports loudness is enabled.\n");
75 printf("Client reports loudness is disabled.\n");
78 void notify_loudness_threshold_callback(ShairportSync
*proxy
,
79 __attribute__((unused
)) gpointer user_data
) {
80 gdouble th
= shairport_sync_get_loudness_threshold(proxy
);
81 printf("Client reports loudness threshold set to %.2f dB.\n", th
);
84 void notify_volume_callback(ShairportSyncAdvancedRemoteControl
*proxy
,
85 __attribute__((unused
)) gpointer user_data
) {
86 gdouble th
= shairport_sync_advanced_remote_control_get_volume(proxy
);
87 printf("Client reports volume set to %.2f.\n", th
);
90 pthread_t dbus_thread
;
91 void *dbus_thread_func(__attribute__((unused
)) void *arg
) {
93 loop
= g_main_loop_new(NULL
, FALSE
);
95 g_main_loop_run(loop
);
97 // dbus_service_main(); // let it run inside a thread
98 return NULL
; // this is just to quieten a compiler warning.
101 int main(int argc
, char *argv
[]) {
103 GBusType gbus_type_selected
= G_BUS_TYPE_SYSTEM
; // set default
104 // get the options --system or --session for system bus or session bus
105 signed char c
; /* used for argument parsing */
106 poptContext optCon
; /* context for parsing command-line options */
108 struct poptOption optionsTable
[] = {
109 {"system", '\0', POPT_ARG_VAL
, &gbus_type_selected
, G_BUS_TYPE_SYSTEM
,
110 "Listen on the D-Bus system bus -- pick this option or the \'--session\' option, but not "
111 "both. This is the default if no option is chosen.",
113 {"session", '\0', POPT_ARG_VAL
, &gbus_type_selected
, G_BUS_TYPE_SESSION
,
114 "Listen on the D-Bus session bus -- pick this option or the \'--system\' option, but not "
117 POPT_AUTOHELP
{NULL
, 0, 0, NULL
, 0, NULL
, NULL
}};
119 optCon
= poptGetContext(NULL
, argc
, (const char **)argv
, optionsTable
, 0);
120 poptSetOtherOptionHelp(optCon
, "[--system | --session]");
123 poptPrintHelp(optCon
, stderr
, 0);
127 /* Now do options processing */
128 while ((c
= poptGetNextOpt(optCon
)) >= 0) {
132 /* an error occurred during option processing */
133 fprintf(stderr
, "%s: %s\n", poptBadOption(optCon
, POPT_BADOPTION_NOALIAS
), poptStrerror(c
));
137 poptFreeContext(optCon
);
139 printf("Listening on the D-Bus %s bus.\n",
140 (gbus_type_selected
== G_BUS_TYPE_SYSTEM
) ? "system" : "session");
142 pthread_create(&dbus_thread
, NULL
, &dbus_thread_func
, NULL
);
144 ShairportSync
*proxy
;
145 GError
*error
= NULL
;
147 proxy
= shairport_sync_proxy_new_for_bus_sync(gbus_type_selected
, G_DBUS_PROXY_FLAGS_NONE
,
148 "org.gnome.ShairportSync",
149 "/org/gnome/ShairportSync", NULL
, &error
);
151 // g_signal_connect(proxy, "notify::loudness-filter-active",
152 // G_CALLBACK(notify_loudness_filter_active_callback), NULL);
154 g_signal_connect(proxy
, "g-properties-changed", G_CALLBACK(on_properties_changed
),
156 g_signal_connect(proxy
, "notify::loudness-threshold",
157 G_CALLBACK(notify_loudness_threshold_callback
), "ShairportSync");
159 // Now, add notification of changes in diagnostics
161 ShairportSyncDiagnostics
*proxy2
;
162 GError
*error2
= NULL
;
163 proxy2
= shairport_sync_diagnostics_proxy_new_for_bus_sync(
164 gbus_type_selected
, G_DBUS_PROXY_FLAGS_NONE
, "org.gnome.ShairportSync",
165 "/org/gnome/ShairportSync", NULL
, &error2
);
166 g_signal_connect(proxy2
, "g-properties-changed", G_CALLBACK(on_properties_changed
),
167 "ShairportSync.Diagnostics");
169 // Now, add notification of changes in remote control
171 ShairportSyncRemoteControl
*proxy3
;
172 GError
*error3
= NULL
;
173 proxy3
= shairport_sync_remote_control_proxy_new_for_bus_sync(
174 gbus_type_selected
, G_DBUS_PROXY_FLAGS_NONE
, "org.gnome.ShairportSync",
175 "/org/gnome/ShairportSync", NULL
, &error3
);
176 g_signal_connect(proxy3
, "g-properties-changed", G_CALLBACK(on_properties_changed
),
177 "ShairportSync.RemoteControl");
179 ShairportSyncAdvancedRemoteControl
*proxy4
;
180 GError
*error4
= NULL
;
181 proxy4
= shairport_sync_advanced_remote_control_proxy_new_for_bus_sync(
182 gbus_type_selected
, G_DBUS_PROXY_FLAGS_NONE
, "org.gnome.ShairportSync",
183 "/org/gnome/ShairportSync", NULL
, &error4
);
184 g_signal_connect(proxy4
, "g-properties-changed", G_CALLBACK(on_properties_changed
),
185 "ShairportSync.AdvancedRemoteControl");
186 g_signal_connect(proxy4
, "notify::volume", G_CALLBACK(notify_volume_callback
),
187 "ShairportSync.AdvancedRemoteControl");
189 g_print("Starting test...\n");
191 g_print("Using the RemoteControl interface, play for five seconds, pause for five seconds and "
192 "then resume play...\n");
193 g_print("Play...\n");
194 shairport_sync_remote_control_call_play(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), NULL
, NULL
, 0);
196 g_print("Pause...\n");
197 shairport_sync_remote_control_call_pause(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), NULL
, NULL
, 0);
199 g_print("Play...\n");
200 shairport_sync_remote_control_call_play(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), NULL
, NULL
, 0);
202 g_print("Using the RemoteControl interface, set AirPlay Volume (range -30 to 0) to -30, -20, "
203 "-10, 0 and -15 for five seconds each...\n");
204 g_print("Set AirPlay Volume (range -30 to 0) to -30\n");
205 shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), -30,
208 g_print("Set AirPlay Volume (range -30 to 0) to -20\n");
209 shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), -20,
212 g_print("Set AirPlay Volume (range -30 to 0) to -10\n");
213 shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), -10,
216 g_print("Set AirPlay Volume (range -30 to 0) to -0\n");
217 shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), 0,
220 g_print("Set AirPlay Volume (range -30 to 0) to -15\n");
221 shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), -15,
225 g_print("Using the AdvancedRemoteControl interface, set Volume to 20%%, 100%%, 40%% and 60%% for "
226 "five seconds each...\n");
227 g_print("Set Volume to 20%%\n");
228 shairport_sync_advanced_remote_control_call_set_volume(
229 SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4
), 20, NULL
, NULL
, 0);
231 g_print("Set Volume to 100%%\n");
232 shairport_sync_advanced_remote_control_call_set_volume(
233 SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4
), 100, NULL
, NULL
, 0);
235 g_print("Set Volume to 40%%\n");
236 shairport_sync_advanced_remote_control_call_set_volume(
237 SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4
), 40, NULL
, NULL
, 0);
239 g_print("Set Volume to 50%%\n");
240 shairport_sync_advanced_remote_control_call_set_volume(
241 SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4
), 50, NULL
, NULL
, 0);
244 g_print("Using the RemoteControl interface, increase volume for five seconds...\n");
245 shairport_sync_remote_control_call_volume_up(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), NULL
, NULL
,
248 g_print("Using the RemoteControl interface, decrease volume...\n");
249 shairport_sync_remote_control_call_volume_down(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3
), NULL
, NULL
,
254 shairport_sync_set_loudness_filter_active(SHAIRPORT_SYNC(proxy), TRUE);
256 shairport_sync_set_loudness_threshold(SHAIRPORT_SYNC(proxy), -20.0);
258 shairport_sync_set_loudness_filter_active(SHAIRPORT_SYNC(proxy), FALSE);
260 shairport_sync_set_loudness_filter_active(SHAIRPORT_SYNC(proxy), TRUE);
262 shairport_sync_set_loudness_threshold(SHAIRPORT_SYNC(proxy), -10.0);
264 shairport_sync_set_loudness_filter_active(SHAIRPORT_SYNC(proxy), FALSE);
267 shairport_sync_call_remote_command(SHAIRPORT_SYNC(proxy), "string",NULL,NULL,NULL);
270 g_print("Finished test. Listening for property changes...\n");
271 // g_main_loop_quit(loop);
272 pthread_join(dbus_thread
, NULL
);
273 printf("exiting program.\n");
275 g_object_unref(proxy
);