Merge lp:~cjcurran/indicator-sound/dynamic_sink_switch_smooth_sliding into lp:indicator-sound/0.1
- dynamic_sink_switch_smooth_sliding
- Merge into trunk
Proposed by
Conor Curran
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~cjcurran/indicator-sound/dynamic_sink_switch_smooth_sliding |
Merge into: | lp:indicator-sound/0.1 |
Diff against target: |
417 lines (+134/-86) 3 files modified
src/indicator-sound.c (+36/-55) src/pulse-manager.c (+89/-22) src/sound-service.c (+9/-9) |
To merge this branch: | bzr merge lp:~cjcurran/indicator-sound/dynamic_sink_switch_smooth_sliding |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cody Russell (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Conor Curran (cjcurran) wrote : | # |
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cody Russell (bratsche) wrote : | # |
It would be nice if you could remove some of the stuff that you're just commenting out, as it's kind of going to clutter up the code for other people reading it. But otherwise, +1
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/indicator-sound.c' |
2 | --- src/indicator-sound.c 2010-02-16 16:38:03 +0000 |
3 | +++ src/indicator-sound.c 2010-02-17 17:37:14 +0000 |
4 | @@ -82,7 +82,7 @@ |
5 | static GtkWidget *volume_slider = NULL; |
6 | static gboolean new_slider_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); |
7 | static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkWidget *widget); |
8 | -static gboolean user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data); |
9 | +/*static gboolean user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data);*/ |
10 | static gboolean value_changed_event_cb(GtkRange *range, gpointer user_data); |
11 | static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data); |
12 | |
13 | @@ -148,15 +148,6 @@ |
14 | } |
15 | |
16 | |
17 | -/*static void test_images_hash()*/ |
18 | -/*{*/ |
19 | -/* g_debug("about to test the images hash"); */ |
20 | -/* gchar* current_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));*/ |
21 | -/* g_debug("start up current image name = %s", current_name); */ |
22 | -/* gchar* previous_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(previous_state));*/ |
23 | -/* g_debug("start up previous image name = %s", previous_name); */ |
24 | -/*}*/ |
25 | - |
26 | /* |
27 | Prepare states Array. |
28 | */ |
29 | @@ -264,14 +255,7 @@ |
30 | // DEBUG |
31 | gdouble current_value = gtk_range_get_value(range); |
32 | g_debug("SIGNAL- update sink volume - current_value : %f and new value : %f", current_value, volume_percent); |
33 | - |
34 | - // Don't like this solution - too fuzzy |
35 | - // Need the ability to detect if the slider is grabbed |
36 | - if(floor(current_value) != floor(volume_percent)) |
37 | - { |
38 | - g_debug("Going to update slider value"); |
39 | - gtk_range_set_value(range, volume_percent); |
40 | - } |
41 | + gtk_range_set_value(range, volume_percent); |
42 | determine_state_from_volume(volume_percent); |
43 | } |
44 | |
45 | @@ -337,15 +321,6 @@ |
46 | gtk_image_set_from_icon_name(speaker_image, image_name, GTK_ICON_SIZE_MENU); |
47 | } |
48 | |
49 | -/*static void revert_state()*/ |
50 | -/*{*/ |
51 | - |
52 | -/* g_debug("revert state beginning - previous_state = %i", previous_state);*/ |
53 | -/* current_state = previous_state;*/ |
54 | -/* gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));*/ |
55 | -/* gtk_image_set_from_icon_name(speaker_image, image_name, GTK_ICON_SIZE_MENU);*/ |
56 | -/* g_debug("after reverting back to previous state of %i", current_state);*/ |
57 | -/*}*/ |
58 | |
59 | static void determine_state_from_volume(gdouble volume_percent) |
60 | { |
61 | @@ -377,12 +352,16 @@ |
62 | DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(menu); |
63 | dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_SLIDER_MENUITEM_TYPE, new_slider_item); |
64 | |
65 | - // register Key-press listening on the widget |
66 | + // register Key-press listening on the menu widget as the slider does not allow this. |
67 | g_signal_connect(menu, "key-press-event", G_CALLBACK(key_press_cb), NULL); |
68 | |
69 | return GTK_MENU(menu); |
70 | } |
71 | |
72 | +/** |
73 | +new_slider_item: |
74 | +Create a new dBusMenu Slider item, register the |
75 | +**/ |
76 | static gboolean new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) |
77 | { |
78 | g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); |
79 | @@ -398,7 +377,7 @@ |
80 | |
81 | // register slider changes listening on the range |
82 | GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); |
83 | - g_signal_connect(slider, "change-value", G_CALLBACK(user_change_value_event_cb), newitem); |
84 | +/* g_signal_connect(slider, "change-value", G_CALLBACK(user_change_value_event_cb), newitem); */ |
85 | g_signal_connect(slider, "value-changed", G_CALLBACK(value_changed_event_cb), newitem); |
86 | |
87 | // Set images on the ido |
88 | @@ -412,8 +391,10 @@ |
89 | return TRUE; |
90 | } |
91 | |
92 | -/* Whenever we have a property change on a DbusmenuMenuitem |
93 | - we need to be responsive to that. */ |
94 | +/** |
95 | +slider_prop_change_cb: |
96 | +Whenever we have a property change on a DbusmenuMenuitem this will be called. |
97 | +**/ |
98 | static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkWidget *widget) |
99 | { |
100 | g_debug("slider_prop_change_cb - dodgy updater "); |
101 | @@ -425,22 +406,21 @@ |
102 | } |
103 | |
104 | /** |
105 | -This callback will get triggered irregardless of whether its a user change or a programmatic change |
106 | -Our usecase for this particular callback is only interested if the slider is changed by the user hitting either icon |
107 | -which will result in a programmatic value change of 0 or 100 (work around). |
108 | +value_changed_event_cb: |
109 | +This callback will get triggered irregardless of whether its a user change or a programmatic change. |
110 | **/ |
111 | static gboolean value_changed_event_cb(GtkRange *range, gpointer user_data) |
112 | { |
113 | - gdouble current_value = gtk_range_get_value(range); |
114 | -/* if(current_value == 0 || current_value == 100)*/ |
115 | -/* {*/ |
116 | + gdouble current_value = CLAMP(gtk_range_get_value(range), 0, 100); |
117 | DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data; |
118 | GValue value = {0}; |
119 | g_value_init(&value, G_TYPE_DOUBLE); |
120 | g_value_set_double(&value, current_value); |
121 | g_debug("Value changed callback - = %f", current_value); |
122 | - dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0); |
123 | -/* }*/ |
124 | + dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0); |
125 | + // This is not ideal in that the icon ui will update on ui actions and not on actual service feedback. |
126 | + // but necessary for now as the server does not send volume update information if the source of change was this ui. |
127 | + determine_state_from_volume(current_value); |
128 | return FALSE; |
129 | } |
130 | |
131 | @@ -450,9 +430,8 @@ |
132 | static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data) |
133 | { |
134 | |
135 | - if(event->length > 0) |
136 | - g_debug("The key event's string is '%s'\n", event->string); |
137 | - |
138 | +/* if(event->length > 0)*/ |
139 | +/* g_debug("The key event's string is '%s'\n", event->string);*/ |
140 | GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); |
141 | GtkRange* range = (GtkRange*)slider; |
142 | gdouble current_value = gtk_range_get_value(range); |
143 | @@ -502,7 +481,7 @@ |
144 | new_value = CLAMP(new_value, 0, 100); |
145 | if(new_value != current_value) |
146 | { |
147 | - g_debug("Attempting to set the range to %f", new_value); |
148 | + g_debug("Attempting to set the range from the key listener to %f", new_value); |
149 | gtk_range_set_value(range, new_value); |
150 | } |
151 | return FALSE; |
152 | @@ -510,18 +489,20 @@ |
153 | |
154 | /** |
155 | This callback should only be called when the user actually drags the slider. |
156 | -Turned off for now in favour of the non descriminating call back. |
157 | +Turned off for now in favour of the non descriminating value-changed call back. |
158 | +Once the grabbing listener is implemented on the slider may revert to using this. |
159 | +Its another tool for filtering unwanted volume change updates. |
160 | **/ |
161 | -static gboolean user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data) |
162 | -{ |
163 | - DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data; |
164 | - gdouble clamped_input = CLAMP(input_value, 0, 100); |
165 | - GValue value = {0}; |
166 | - g_debug("User input on SLIDER - = %f", clamped_input); |
167 | - g_value_init(&value, G_TYPE_DOUBLE); |
168 | - g_value_set_double(&value, clamped_input); |
169 | - dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0); |
170 | - return FALSE; |
171 | -} |
172 | +/*static gboolean user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data)*/ |
173 | +/*{*/ |
174 | +/* DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data;*/ |
175 | +/* gdouble clamped_input = CLAMP(input_value, 0, 100);*/ |
176 | +/* GValue value = {0};*/ |
177 | +/* g_debug("User input on SLIDER - = %f", clamped_input);*/ |
178 | +/* g_value_init(&value, G_TYPE_DOUBLE);*/ |
179 | +/* g_value_set_double(&value, clamped_input);*/ |
180 | +/* dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0);*/ |
181 | +/* return FALSE; */ |
182 | +/*} */ |
183 | |
184 | |
185 | |
186 | === modified file 'src/pulse-manager.c' |
187 | --- src/pulse-manager.c 2010-02-17 11:15:00 +0000 |
188 | +++ src/pulse-manager.c 2010-02-17 17:37:14 +0000 |
189 | @@ -43,10 +43,16 @@ |
190 | static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_info *info, int eol, void *userdata); |
191 | static void pulse_server_info_callback(pa_context *c, const pa_server_info *info, void *userdata); |
192 | static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, void *userdata); |
193 | +static void pulse_source_info_callback(pa_context *c, const pa_source_info *i, int eol, void *userdata); |
194 | static void destroy_sink_info(void *value); |
195 | static gboolean determine_sink_availability(); |
196 | |
197 | |
198 | +/** |
199 | +Refactoring notes |
200 | +Push all UI updates out through update PA state in the service. |
201 | +**/ |
202 | + |
203 | /* |
204 | Entry point |
205 | */ |
206 | @@ -167,6 +173,13 @@ |
207 | { |
208 | sink_info *info = (sink_info*)value; |
209 | pa_operation_unref(pa_context_set_sink_mute_by_index(pulse_context, info->index, GPOINTER_TO_INT(user_data), context_success_callback, NULL)); |
210 | + if(GPOINTER_TO_INT(user_data) == 1){ |
211 | + sound_service_dbus_update_sink_mute(dbus_service, TRUE); |
212 | + } |
213 | + else{ |
214 | + sound_service_dbus_update_sink_volume(dbus_service, get_default_sink_volume()); |
215 | + } |
216 | + |
217 | g_debug("in the pulse manager: mute each sink %i", GPOINTER_TO_INT(user_data)); |
218 | } |
219 | |
220 | @@ -197,8 +210,9 @@ |
221 | g_debug("new volume calculated :%f", (gdouble)new_volume); |
222 | pa_cvolume dev_vol; |
223 | pa_cvolume_set(&dev_vol, s->volume.channels, new_volume); |
224 | - // TODO why don't you update the sink_info here with the appropriate pa_cvolume (&dev_vol) |
225 | + s->volume = dev_vol; |
226 | pa_operation_unref(pa_context_set_sink_volume_by_index(pulse_context, DEFAULT_SINK_INDEX, &dev_vol, NULL, NULL)); |
227 | + |
228 | } |
229 | |
230 | |
231 | @@ -242,9 +256,9 @@ |
232 | if(device_available == TRUE) |
233 | { |
234 | update_pa_state(TRUE, device_available, default_sink_is_muted(), get_default_sink_volume()); |
235 | - sound_service_dbus_update_sink_volume(dbus_service, get_default_sink_volume()); |
236 | - sound_service_dbus_update_sink_mute(dbus_service, default_sink_is_muted()); |
237 | - g_debug("default sink index : %d", DEFAULT_SINK_INDEX); |
238 | + //sound_service_dbus_update_sink_volume(dbus_service, get_default_sink_volume()); |
239 | + //sound_service_dbus_update_sink_mute(dbus_service, default_sink_is_muted()); |
240 | + //g_debug("default sink index : %d", DEFAULT_SINK_INDEX); |
241 | } |
242 | else{ |
243 | //Update the indicator to show PA either is not ready or has no available sink |
244 | @@ -281,7 +295,17 @@ |
245 | else{ |
246 | DEFAULT_SINK_INDEX = info->index; |
247 | g_debug("Just set the default sink index to %i", DEFAULT_SINK_INDEX); |
248 | - pa_operation_unref(pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL)); |
249 | + GList *keys = g_hash_table_get_keys(sink_hash); |
250 | + gint position = g_list_index(keys, GINT_TO_POINTER(info->index)); |
251 | + // Only update sink-list if the index is not in our already fetched list. |
252 | + if(position < 0) |
253 | + { |
254 | + pa_operation_unref(pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL)); |
255 | + } |
256 | + else |
257 | + { |
258 | + update_pa_state(TRUE, determine_sink_availability(), default_sink_is_muted(), get_default_sink_volume()); |
259 | + } |
260 | } |
261 | } |
262 | |
263 | @@ -322,19 +346,22 @@ |
264 | s->description = g_strdup(info->description); |
265 | s->icon_name = g_strdup(pa_proplist_gets(info->proplist, PA_PROP_DEVICE_ICON_NAME)); |
266 | s->active_port = (info->active_port != NULL); |
267 | - // NASTY!! |
268 | + s->mute = !!info->mute; |
269 | gboolean mute_changed = s->mute != !!info->mute; |
270 | - s->mute = !!info->mute; |
271 | + gboolean volume_changed = (pa_cvolume_equal(&info->volume, &s->volume) == 0); |
272 | s->volume = info->volume; |
273 | s->base_volume = info->base_volume; |
274 | s->channel_map = info->channel_map; |
275 | if(DEFAULT_SINK_INDEX == s->index) |
276 | { |
277 | //update the UI |
278 | - pa_volume_t vol = pa_cvolume_avg(&s->volume); |
279 | - gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; |
280 | - g_debug("Updating volume from PA manager with volume = %f", volume_percent); |
281 | - sound_service_dbus_update_sink_volume(dbus_service, volume_percent); |
282 | + if (volume_changed == TRUE) |
283 | + { |
284 | + pa_volume_t vol = pa_cvolume_avg(&s->volume); |
285 | + gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; |
286 | + g_debug("Updating volume from PA manager with volume = %f", volume_percent); |
287 | + sound_service_dbus_update_sink_volume(dbus_service, volume_percent); |
288 | + } |
289 | if (mute_changed == TRUE) |
290 | sound_service_dbus_update_sink_mute(dbus_service, s->mute); |
291 | update_mute_ui(s->mute); |
292 | @@ -382,24 +409,64 @@ |
293 | pa_operation_unref(operation); |
294 | } |
295 | |
296 | -static void subscribed_events_callback(pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata){ |
297 | - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { |
298 | +static void pulse_source_info_callback(pa_context *c, const pa_source_info *i, int eol, void *userdata) |
299 | +{ |
300 | + g_debug("pulse source info callback"); |
301 | +} |
302 | + |
303 | + |
304 | +static void subscribed_events_callback(pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) |
305 | +{ |
306 | + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) |
307 | + { |
308 | case PA_SUBSCRIPTION_EVENT_SINK: |
309 | - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { |
310 | - //TODO handle the remove event => if its our default sink - grey out the ui with update_pa_state |
311 | - } else { |
312 | + g_debug("PA_SUBSCRIPTION_EVENT_SINK event triggered"); |
313 | + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) |
314 | + { |
315 | + //TODO handle the remove event => if its our default sink - update date pa state |
316 | + } else |
317 | + { |
318 | pa_operation_unref(pa_context_get_sink_info_by_index(c, index, update_sink_info, userdata)); |
319 | } |
320 | break; |
321 | case PA_SUBSCRIPTION_EVENT_SINK_INPUT: |
322 | - // This will be triggered when the sink receives input from a new stream |
323 | - // If a playback client is paused and then resumed this will NOT trigger this event. |
324 | - pa_operation_unref(pa_context_get_sink_input_info(c, index, pulse_sink_input_info_callback, userdata)); |
325 | - break; |
326 | + g_debug("PA_SUBSCRIPTION_EVENT_SINK_INPUT event triggered!!"); |
327 | + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) |
328 | + { |
329 | + //TODO handle the remove event |
330 | + } |
331 | + else |
332 | + { |
333 | + pa_operation_unref(pa_context_get_sink_input_info(c, index, pulse_sink_input_info_callback, userdata)); |
334 | + } |
335 | + break; |
336 | + case PA_SUBSCRIPTION_EVENT_SOURCE: |
337 | + g_debug("PA_SUBSCRIPTION_EVENT_SOURCE of some description ???"); |
338 | + |
339 | + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) |
340 | + { |
341 | + //TODO handle the remove event |
342 | + } |
343 | + else |
344 | + { |
345 | + pa_operation *o; |
346 | + if (!(o = pa_context_get_source_info_by_index(c, index, pulse_source_info_callback, userdata))) { |
347 | + g_warning("pa_context_get_source_info_by_index() failed"); |
348 | + return; |
349 | + } |
350 | + pa_operation_unref(o); |
351 | + } |
352 | + break; |
353 | case PA_SUBSCRIPTION_EVENT_SERVER: |
354 | - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_SINK ) { |
355 | - g_debug("server change of some sink type ???"); |
356 | + g_debug("PA_SUBSCRIPTION_EVENT_SERVER change of some description ???"); |
357 | + pa_operation *o; |
358 | + if(!(o = pa_context_get_server_info(c, pulse_server_info_callback, userdata))) |
359 | + { |
360 | + g_warning("pa_context_get_server_info() failed"); |
361 | + return; |
362 | } |
363 | + pa_operation_unref(o); |
364 | + break; |
365 | } |
366 | } |
367 | |
368 | |
369 | === modified file 'src/sound-service.c' |
370 | --- src/sound-service.c 2010-02-17 11:15:00 +0000 |
371 | +++ src/sound-service.c 2010-02-17 17:37:14 +0000 |
372 | @@ -97,6 +97,7 @@ |
373 | { |
374 | b_all_muted = incoming_mute_value; |
375 | dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _(b_all_muted == FALSE ? "Mute All" : "Unmute")); |
376 | + //dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_MENUITEM_PROP_ENABLED, b_all_muted); |
377 | } |
378 | |
379 | static void set_global_mute_from_ui() |
380 | @@ -104,13 +105,7 @@ |
381 | b_all_muted = !b_all_muted; |
382 | toggle_global_mute(b_all_muted); |
383 | dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _(b_all_muted == FALSE ? "Mute All" : "Unmute")); |
384 | - |
385 | -/* GValue value = {0};*/ |
386 | -/* g_value_init(&value, G_TYPE_DOUBLE);*/ |
387 | -/* g_value_set_double(&value, 99.0);*/ |
388 | -/* // Testing*/ |
389 | -/* g_debug("BUGGY volume update");*/ |
390 | -/* dbusmenu_menuitem_property_set_value(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME, &value);*/ |
391 | + //dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_MENUITEM_PROP_ENABLED, b_all_muted); |
392 | } |
393 | |
394 | |
395 | @@ -137,7 +132,12 @@ |
396 | b_pulse_ready = pa_state; |
397 | volume_percent = percent; |
398 | g_debug("update pa state with state %i, availability of %i, mute value of %i and a volume percent is %f", pa_state, sink_available, sink_muted, volume_percent); |
399 | - rebuild_sound_menu(root_menuitem, dbus_interface); |
400 | + sound_service_dbus_update_sink_volume(dbus_interface, percent); |
401 | + sound_service_dbus_update_sink_mute(dbus_interface, sink_muted); |
402 | + |
403 | + // Only rebuild the menu on start up... |
404 | + if(volume_slider_menuitem == NULL) |
405 | + rebuild_sound_menu(root_menuitem, dbus_interface); |
406 | } |
407 | |
408 | |
409 | @@ -169,7 +169,7 @@ |
410 | dbusmenu_server_set_root(server, root_menuitem); |
411 | establish_pulse_activities(dbus_interface); |
412 | |
413 | -/* // THIS DOES NOT WORK FROM HERE*/ |
414 | +/* // THIS DOES NOT WORK FROM HERE - race condition ?!?*/ |
415 | /* GValue value = {0};*/ |
416 | /* g_value_init(&value, G_TYPE_DOUBLE);*/ |
417 | /* g_value_set_double(&value, volume_percent * 100);*/ |
This branch contains fixes to enable dynamic switching of the output devices and change to enable smooth sliding. I had to change some stuff around for this but it should be thoroughly tested .