aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-12-05 05:27:27 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2022-12-05 05:27:27 +0100
commite67d27e74d0a2b0281256402ea79adea8ae91373 (patch)
treed3e1af0d1ae3553d0d90a3520825df5b796bcbdd
parent90aeae98ca55fffcfbd598255d62fd258d287e1d (diff)
downloadmessenger-gtk-e67d27e74d0a2b0281256402ea79adea8ae91373.tar.gz
messenger-gtk-e67d27e74d0a2b0281256402ea79adea8ae91373.zip
Fix issues with video playback
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--resources/ui/play_media.ui35
-rw-r--r--src/ui/new_contact.c8
-rw-r--r--src/ui/picker.c6
-rw-r--r--src/ui/play_media.c374
-rw-r--r--src/ui/play_media.h19
5 files changed, 325 insertions, 117 deletions
diff --git a/resources/ui/play_media.ui b/resources/ui/play_media.ui
index ca1a1cf..cb2786b 100644
--- a/resources/ui/play_media.ui
+++ b/resources/ui/play_media.ui
@@ -23,6 +23,11 @@ Author: Tobias Frisch
23<interface> 23<interface>
24 <requires lib="gtk+" version="3.24"/> 24 <requires lib="gtk+" version="3.24"/>
25 <requires lib="libhandy" version="1.2"/> 25 <requires lib="libhandy" version="1.2"/>
26 <object class="GtkAdjustment" id="timeline_adjustment">
27 <property name="upper">100</property>
28 <property name="step-increment">1</property>
29 <property name="page-increment">10</property>
30 </object>
26 <object class="HdyWindow" id="play_media_window"> 31 <object class="HdyWindow" id="play_media_window">
27 <property name="width-request">250</property> 32 <property name="width-request">250</property>
28 <property name="height-request">250</property> 33 <property name="height-request">250</property>
@@ -234,15 +239,37 @@ audio-volume-medium-symbolic</property>
234 </packing> 239 </packing>
235 </child> 240 </child>
236 <child> 241 <child>
237 <object class="GtkLabel" id="timeline_label"> 242 <object class="HdyLeaflet">
238 <property name="visible">True</property> 243 <property name="visible">True</property>
239 <property name="can-focus">False</property> 244 <property name="can-focus">False</property>
240 <property name="label" translatable="yes">0:00 / 0:00</property> 245 <property name="visible-child">timeline_scale</property>
246 <property name="transition-type">slide</property>
247 <child>
248 <object class="GtkLabel" id="timeline_label">
249 <property name="width-request">80</property>
250 <property name="visible">True</property>
251 <property name="can-focus">False</property>
252 <property name="margin-end">4</property>
253 <property name="label" translatable="yes">0:00 / 0:00</property>
254 </object>
255 </child>
256 <child>
257 <object class="GtkScale" id="timeline_scale">
258 <property name="width-request">100</property>
259 <property name="visible">True</property>
260 <property name="sensitive">False</property>
261 <property name="can-focus">True</property>
262 <property name="margin-start">4</property>
263 <property name="hexpand">True</property>
264 <property name="adjustment">timeline_adjustment</property>
265 <property name="draw-value">False</property>
266 </object>
267 </child>
241 </object> 268 </object>
242 <packing> 269 <packing>
243 <property name="expand">False</property> 270 <property name="expand">True</property>
244 <property name="fill">True</property> 271 <property name="fill">True</property>
245 <property name="position">2</property> 272 <property name="position">3</property>
246 </packing> 273 </packing>
247 </child> 274 </child>
248 <child> 275 <child>
diff --git a/src/ui/new_contact.c b/src/ui/new_contact.c
index 90bb4b6..8393086 100644
--- a/src/ui/new_contact.c
+++ b/src/ui/new_contact.c
@@ -90,7 +90,7 @@ _disable_video_processing(UI_NEW_CONTACT_Handle *handle,
90static void 90static void
91msg_error_cb(UNUSED GstBus *bus, 91msg_error_cb(UNUSED GstBus *bus,
92 GstMessage *msg, 92 GstMessage *msg,
93 gpointer *data) 93 gpointer data)
94{ 94{
95 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data; 95 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
96 96
@@ -110,7 +110,7 @@ msg_error_cb(UNUSED GstBus *bus,
110static void 110static void
111msg_eos_cb(UNUSED GstBus *bus, 111msg_eos_cb(UNUSED GstBus *bus,
112 UNUSED GstMessage *msg, 112 UNUSED GstMessage *msg,
113 gpointer *data) 113 gpointer data)
114{ 114{
115 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data; 115 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
116 116
@@ -121,7 +121,7 @@ msg_eos_cb(UNUSED GstBus *bus,
121static void 121static void
122msg_state_changed_cb(UNUSED GstBus *bus, 122msg_state_changed_cb(UNUSED GstBus *bus,
123 GstMessage *msg, 123 GstMessage *msg,
124 gpointer *data) 124 gpointer data)
125{ 125{
126 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data; 126 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
127 127
@@ -144,7 +144,7 @@ msg_state_changed_cb(UNUSED GstBus *bus,
144static void 144static void
145msg_barcode_cb(UNUSED GstBus *bus, 145msg_barcode_cb(UNUSED GstBus *bus,
146 GstMessage *msg, 146 GstMessage *msg,
147 gpointer *data) 147 gpointer data)
148{ 148{
149 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data; 149 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
150 GstMessageType msg_type = GST_MESSAGE_TYPE(msg); 150 GstMessageType msg_type = GST_MESSAGE_TYPE(msg);
diff --git a/src/ui/picker.c b/src/ui/picker.c
index ca8423e..eb42a1d 100644
--- a/src/ui/picker.c
+++ b/src/ui/picker.c
@@ -101,6 +101,12 @@ handle_settings_button_click(UNUSED GtkButton *button,
101{ 101{
102 MESSENGER_Application *app = (MESSENGER_Application*) user_data; 102 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
103 ui_play_media_window_init(app, &(app->ui.play_media)); 103 ui_play_media_window_init(app, &(app->ui.play_media));
104
105 ui_play_media_window_update(
106 &(app->ui.play_media),
107 "TODO" // uri path to video file
108 );
109
104 gtk_widget_show(GTK_WIDGET(app->ui.play_media.window)); 110 gtk_widget_show(GTK_WIDGET(app->ui.play_media.window));
105} 111}
106 112
diff --git a/src/ui/play_media.c b/src/ui/play_media.c
index 5dbfdec..a7e9d88 100644
--- a/src/ui/play_media.c
+++ b/src/ui/play_media.c
@@ -27,8 +27,6 @@
27#include "../application.h" 27#include "../application.h"
28#include "../ui.h" 28#include "../ui.h"
29 29
30#include <gst/gst.h>
31
32static void 30static void
33handle_back_button_click(GtkButton *button, 31handle_back_button_click(GtkButton *button,
34 gpointer user_data) 32 gpointer user_data)
@@ -38,33 +36,69 @@ handle_back_button_click(GtkButton *button,
38} 36}
39 37
40static void 38static void
41_disable_video_processing(UI_PLAY_MEDIA_Handle *handle, 39_set_media_controls_sensivity(UI_PLAY_MEDIA_Handle *handle,
42 gboolean drop_pipeline) 40 gboolean sensitive)
43{ 41{
44 GNUNET_assert(handle); 42 if (handle->play_pause_button)
45 43 gtk_widget_set_sensitive(
46 if (handle->preview_stack) 44 GTK_WIDGET(handle->play_pause_button),
47 gtk_stack_set_visible_child(handle->preview_stack, handle->fail_box); 45 sensitive
46 );
48 47
49 if ((!(handle->pipeline)) || (!drop_pipeline)) 48 if (handle->volume_button)
50 return; 49 gtk_widget_set_sensitive(
50 GTK_WIDGET(handle->volume_button),
51 sensitive
52 );
51 53
52 gst_element_set_state(handle->pipeline, GST_STATE_NULL); 54 if (handle->timeline_scale)
55 gtk_widget_set_sensitive(
56 GTK_WIDGET(handle->timeline_scale),
57 sensitive
58 );
53} 59}
54 60
55static gboolean 61static void
56_adjust_playing_media_position(UI_PLAY_MEDIA_Handle *handle) 62handle_timeline_scale_value_changed(GtkRange *range,
63 gpointer user_data);
64
65static void
66_set_signal_connection_of_timeline(UI_PLAY_MEDIA_Handle *handle,
67 gboolean connected)
57{ 68{
58 gint64 pos, len; 69 if (!(handle->timeline_scale))
70 return;
59 71
60 if (!(handle->pipeline)) 72 if (connected == (handle->timeline_signal != 0))
61 return FALSE; 73 return;
62 74
63 if (!gst_element_query_position(handle->pipeline, GST_FORMAT_TIME, &pos)) 75 if (connected)
64 return FALSE; 76 handle->timeline_signal = g_signal_connect(
77 handle->timeline_scale,
78 "value-changed",
79 G_CALLBACK(handle_timeline_scale_value_changed),
80 handle
81 );
82 else
83 {
84 g_signal_handler_disconnect(
85 handle->timeline_scale,
86 handle->timeline_signal
87 );
65 88
66 if (!gst_element_query_duration(handle->pipeline, GST_FORMAT_TIME, &len)) 89 handle->timeline_signal = 0;
67 return FALSE; 90 }
91}
92
93static void
94_set_media_position(UI_PLAY_MEDIA_Handle *handle,
95 gint64 pos,
96 gint64 len,
97 gboolean include_scale)
98{
99 const gdouble position = (
100 len > 0? 1.0 * pos / len : 0.0
101 );
68 102
69 if (handle->timeline_label) 103 if (handle->timeline_label)
70 { 104 {
@@ -74,12 +108,12 @@ _adjust_playing_media_position(UI_PLAY_MEDIA_Handle *handle)
74 guint len_seconds = GST_TIME_AS_SECONDS(len); 108 guint len_seconds = GST_TIME_AS_SECONDS(len);
75 109
76 g_string_append_printf( 110 g_string_append_printf(
77 str, 111 str,
78 "%u:%02u / %u:%02u", 112 "%u:%02u / %u:%02u",
79 pos_seconds / 60, 113 pos_seconds / 60,
80 pos_seconds % 60, 114 pos_seconds % 60,
81 len_seconds / 60, 115 len_seconds / 60,
82 len_seconds % 60 116 len_seconds % 60
83 ); 117 );
84 118
85 ui_label_set_text(handle->timeline_label, str->str); 119 ui_label_set_text(handle->timeline_label, str->str);
@@ -88,52 +122,107 @@ _adjust_playing_media_position(UI_PLAY_MEDIA_Handle *handle)
88 122
89 if (handle->timeline_progress_bar) 123 if (handle->timeline_progress_bar)
90 gtk_progress_bar_set_fraction( 124 gtk_progress_bar_set_fraction(
91 handle->timeline_progress_bar, 125 handle->timeline_progress_bar,
92 1.0 * pos / len 126 1.0 * position
93 ); 127 );
94 128
95 return TRUE; 129 if ((!(handle->timeline_scale)) || (!include_scale))
130 return;
131
132 _set_signal_connection_of_timeline(handle, FALSE);
133
134 gtk_range_set_value(
135 GTK_RANGE(handle->timeline_scale),
136 100.0 * position
137 );
138
139 _set_signal_connection_of_timeline(handle, TRUE);
96} 140}
97 141
98static void 142static gboolean
99_adjust_playing_media_state(UI_PLAY_MEDIA_Handle *handle, 143_adjust_playing_media_position(UI_PLAY_MEDIA_Handle *handle)
100 gboolean playing)
101{ 144{
102 handle->playing = playing; 145 gint64 pos, len;
103 146
104 if (!(handle->play_symbol_stack)) 147 if (!(handle->pipeline))
105 return; 148 return FALSE;
106 149
107 gtk_stack_set_visible_child_name( 150 if (!gst_element_query_position(handle->pipeline, GST_FORMAT_TIME, &pos))
108 handle->play_symbol_stack, 151 return FALSE;
109 handle->playing? "pause_page" : "play_page" 152
110 ); 153 if (!gst_element_query_duration(handle->pipeline, GST_FORMAT_TIME, &len))
154 return FALSE;
155
156 _set_media_position(handle, pos, len, TRUE);
157 return TRUE;
158}
111 159
160static void
161_set_timeout_callback_of_timeline(UI_PLAY_MEDIA_Handle *handle,
162 gboolean connected)
163{
112 if (handle->timeline) 164 if (handle->timeline)
113 g_source_remove(handle->timeline); 165 g_source_remove(handle->timeline);
114 166
115 if (handle->playing) 167 if (connected)
116 handle->timeline = g_timeout_add( 168 handle->timeline = g_timeout_add(
117 1000, 169 1000,
118 G_SOURCE_FUNC(_adjust_playing_media_position), 170 G_SOURCE_FUNC(_adjust_playing_media_position),
119 handle 171 handle
120 ); 172 );
121 else 173 else
122 handle->timeline = 0; 174 handle->timeline = 0;
175}
123 176
124 gtk_widget_set_sensitive(GTK_WIDGET(handle->play_pause_button), TRUE); 177static void
178_set_media_state(UI_PLAY_MEDIA_Handle *handle,
179 gboolean playing)
180{
181 if (handle->play_symbol_stack)
182 gtk_stack_set_visible_child_name(
183 handle->play_symbol_stack,
184 playing? "pause_page" : "play_page"
185 );
125 186
126 gtk_stack_set_visible_child( 187 _set_timeout_callback_of_timeline(handle, playing);
127 handle->preview_stack, 188}
128 handle->video_box 189
129 ); 190static void
191_disable_video_processing(UI_PLAY_MEDIA_Handle *handle,
192 gboolean drop_pipeline)
193{
194 GNUNET_assert(handle);
195
196 if (handle->preview_stack)
197 gtk_stack_set_visible_child(handle->preview_stack, handle->fail_box);
198
199 _set_media_controls_sensivity(handle, FALSE);
200 _set_media_position(handle, 0, 0, TRUE);
201 _set_media_state(handle, FALSE);
202
203 if ((!(handle->pipeline)) || (!drop_pipeline))
204 return;
205
206 gst_element_set_state(handle->pipeline, GST_STATE_NULL);
207}
208
209static void
210_adjust_playing_media_state(UI_PLAY_MEDIA_Handle *handle, gboolean playing)
211{
212 _set_media_state(handle, playing);
213
214 if (handle->preview_stack)
215 gtk_stack_set_visible_child(
216 handle->preview_stack,
217 handle->video_box
218 );
130} 219}
131 220
132static void 221static void
133_pause_playing_media(UI_PLAY_MEDIA_Handle *handle) 222_pause_playing_media(UI_PLAY_MEDIA_Handle *handle)
134{ 223{
135 if (!(handle->pipeline)) 224 if (!(handle->pipeline))
136 _adjust_playing_media_state(handle, FALSE); 225 return;
137 226
138 GstStateChangeReturn ret = gst_element_set_state( 227 GstStateChangeReturn ret = gst_element_set_state(
139 handle->pipeline, 228 handle->pipeline,
@@ -151,7 +240,7 @@ static void
151_continue_playing_media(UI_PLAY_MEDIA_Handle *handle) 240_continue_playing_media(UI_PLAY_MEDIA_Handle *handle)
152{ 241{
153 if (!(handle->pipeline)) 242 if (!(handle->pipeline))
154 _adjust_playing_media_state(handle, TRUE); 243 return;
155 244
156 GstStateChangeReturn ret = gst_element_set_state( 245 GstStateChangeReturn ret = gst_element_set_state(
157 handle->pipeline, 246 handle->pipeline,
@@ -171,9 +260,14 @@ handle_play_pause_button_click(GtkButton *button,
171{ 260{
172 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) user_data; 261 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) user_data;
173 262
174 gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); 263 if (!(handle->play_symbol_stack))
264 return;
265
266 const gchar *page = gtk_stack_get_visible_child_name(
267 handle->play_symbol_stack
268 );
175 269
176 if (handle->playing) 270 if (0 == g_strcmp0(page, "pause_page"))
177 _pause_playing_media(handle); 271 _pause_playing_media(handle);
178 else 272 else
179 _continue_playing_media(handle); 273 _continue_playing_media(handle);
@@ -186,18 +280,18 @@ handle_volume_button_value_changed(GtkScaleButton *button,
186{ 280{
187 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) user_data; 281 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) user_data;
188 282
189 if (!(handle->vol)) 283 if (!(handle->pipeline))
190 return; 284 return;
191 285
192 g_object_set( 286 g_object_set(
193 G_OBJECT(handle->vol), 287 G_OBJECT(handle->pipeline),
194 "volume", 288 "volume",
195 value, 289 value,
196 NULL 290 NULL
197 ); 291 );
198 292
199 g_object_set( 293 g_object_set(
200 G_OBJECT(handle->vol), 294 G_OBJECT(handle->pipeline),
201 "mute", 295 "mute",
202 (value <= 0.0), 296 (value <= 0.0),
203 NULL 297 NULL
@@ -205,6 +299,28 @@ handle_volume_button_value_changed(GtkScaleButton *button,
205} 299}
206 300
207static void 301static void
302handle_timeline_scale_value_changed(GtkRange *range,
303 gpointer user_data)
304{
305 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) user_data;
306 gint64 pos, len;
307
308 if (!(handle->pipeline))
309 return;
310
311 if (!gst_element_query_duration(handle->pipeline, GST_FORMAT_TIME, &len))
312 return;
313
314 pos = (gint64) (gtk_range_get_value(range) * len / 100);
315
316 if (gst_element_seek_simple(handle->pipeline,
317 GST_FORMAT_TIME,
318 GST_SEEK_FLAG_FLUSH,
319 pos))
320 _set_media_position(handle, pos, len, FALSE);
321}
322
323static void
208handle_fullscreen_button_click(GtkButton *button, 324handle_fullscreen_button_click(GtkButton *button,
209 gpointer user_data) 325 gpointer user_data)
210{ 326{
@@ -240,9 +356,17 @@ handle_fullscreen_button_click(GtkButton *button,
240 ); 356 );
241 357
242 gtk_widget_show_all(GTK_WIDGET(handle->window)); 358 gtk_widget_show_all(GTK_WIDGET(handle->window));
359 hdy_flap_set_reveal_flap(handle->controls_flap, !(handle->fullscreen));
243 360
244 if (handle->fullscreen) 361 if (handle->fullscreen)
245 gtk_window_fullscreen(GTK_WINDOW(handle->window)); 362 gtk_window_fullscreen(GTK_WINDOW(handle->window));
363 else
364 {
365 if (handle->motion_lost)
366 g_source_remove(handle->motion_lost);
367
368 handle->motion_lost = 0;
369 }
246 370
247 gtk_stack_set_visible_child_name( 371 gtk_stack_set_visible_child_name(
248 handle->fullscreen_symbol_stack, 372 handle->fullscreen_symbol_stack,
@@ -277,6 +401,10 @@ handle_media_motion_notify(GtkWidget *widget,
277 g_source_remove(handle->motion_lost); 401 g_source_remove(handle->motion_lost);
278 402
279 hdy_flap_set_reveal_flap(handle->controls_flap, TRUE); 403 hdy_flap_set_reveal_flap(handle->controls_flap, TRUE);
404
405 if (!(handle->fullscreen))
406 return FALSE;
407
280 handle->motion_lost = g_timeout_add_seconds( 408 handle->motion_lost = g_timeout_add_seconds(
281 3, 409 3,
282 G_SOURCE_FUNC(handle_media_motion_lost), 410 G_SOURCE_FUNC(handle_media_motion_lost),
@@ -296,7 +424,7 @@ handle_window_destroy(UNUSED GtkWidget *window,
296static void 424static void
297msg_error_cb(UNUSED GstBus *bus, 425msg_error_cb(UNUSED GstBus *bus,
298 GstMessage *msg, 426 GstMessage *msg,
299 gpointer *data) 427 gpointer data)
300{ 428{
301 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) data; 429 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) data;
302 430
@@ -316,75 +444,86 @@ msg_error_cb(UNUSED GstBus *bus,
316static void 444static void
317msg_eos_cb(UNUSED GstBus *bus, 445msg_eos_cb(UNUSED GstBus *bus,
318 UNUSED GstMessage *msg, 446 UNUSED GstMessage *msg,
319 gpointer *data) 447 gpointer data)
320{ 448{
321 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) data; 449 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) data;
322 450
323 if (GST_MESSAGE_SRC(msg) == GST_OBJECT(handle->pipeline)) 451 if (GST_MESSAGE_SRC(msg) != GST_OBJECT(handle->pipeline))
324 _adjust_playing_media_state(handle, FALSE); 452 return;
453
454 if (handle->timeline_scale)
455 gtk_range_set_value(GTK_RANGE(handle->timeline_scale), 0.0);
456
457 _adjust_playing_media_state(handle, FALSE);
325} 458}
326 459
327static void 460static void
328msg_state_changed_cb(UNUSED GstBus *bus, 461msg_state_changed_cb(UNUSED GstBus *bus,
329 GstMessage *msg, 462 GstMessage *msg,
330 gpointer *data) 463 gpointer data)
331{ 464{
332 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) data; 465 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) data;
333 466
334 GstState old_state, new_state, pending_state; 467 GstState old_state, new_state, pending_state;
335 gst_message_parse_state_changed(msg, &old_state, &new_state, &pending_state); 468 gst_message_parse_state_changed(msg, &old_state, &new_state, &pending_state);
336 469
337 if ((GST_MESSAGE_SRC(msg) != GST_OBJECT(handle->pipeline)) || 470 if (GST_MESSAGE_SRC(msg) != GST_OBJECT(handle->pipeline))
338 (new_state == old_state) || (!(handle->preview_stack)))
339 return; 471 return;
340 472
341 if (!(handle->sink)) 473 if (!(handle->sink))
474 {
342 _disable_video_processing(handle, FALSE); 475 _disable_video_processing(handle, FALSE);
343 else if (GST_STATE_PLAYING == new_state) 476 return;
344 _adjust_playing_media_state(handle, TRUE); 477 }
345 else if (GST_STATE_PAUSED == new_state) 478
346 _adjust_playing_media_state(handle, FALSE); 479 if (GST_STATE_READY == new_state)
480 _set_media_controls_sensivity(handle, TRUE);
481
482 if ((GST_STATE_PLAYING != new_state) && (GST_STATE_PAUSED != new_state))
483 return;
484
485 _adjust_playing_media_state(handle, GST_STATE_PLAYING == new_state);
347} 486}
348 487
349static void 488static void
350_setup_gst_pipeline(UI_PLAY_MEDIA_Handle *handle) 489msg_buffering_cb(UNUSED GstBus *bus,
490 GstMessage *msg,
491 gpointer data)
351{ 492{
352 handle->pipeline = gst_parse_launch( 493 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) data;
353 "filesrc name=source" 494
354 " ! decodebin name=decode" 495 gint percent = 0;
355 " ! videoconvert ! video/x-raw,format=RGB" 496 gst_message_parse_buffering(msg, &percent);
356 " ! videoconvert ! gtksink name=vsink decode." 497
357 " ! audioconvert ! audioresample" 498 GstStateChangeReturn ret = gst_element_set_state(
358 " ! volume name=vol ! autoaudiosink", 499 handle->pipeline,
359 NULL 500 (percent < 100? GST_STATE_PAUSED : GST_STATE_PLAYING)
360 ); 501 );
361 502
503 if (ret == GST_STATE_CHANGE_FAILURE)
504 _disable_video_processing(handle, TRUE);
505}
506
507static void
508_setup_gst_pipeline(UI_PLAY_MEDIA_Handle *handle)
509{
510 handle->pipeline = gst_element_factory_make("playbin", NULL);
511
362 if (!(handle->pipeline)) 512 if (!(handle->pipeline))
363 return; 513 return;
364 514
365 handle->source = gst_bin_get_by_name( 515 handle->sink = gst_element_factory_make("gtksink", "vsink");
366 GST_BIN(handle->pipeline), "source" 516
367 ); 517 if (!(handle->sink))
518 return;
368 519
369 g_object_set( 520 g_object_set(
370 G_OBJECT(handle->source), 521 G_OBJECT(handle->pipeline),
371 "location", 522 "video-sink",
372 "", // absolute path to video file 523 handle->sink,
373 NULL 524 NULL
374 ); 525 );
375 526
376 handle->decode = gst_bin_get_by_name(
377 GST_BIN(handle->pipeline), "decode"
378 );
379
380 handle->sink = gst_bin_get_by_name(
381 GST_BIN(handle->pipeline), "vsink"
382 );
383
384 handle->vol = gst_bin_get_by_name(
385 GST_BIN(handle->pipeline), "vol"
386 );
387
388 GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(handle->pipeline)); 527 GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(handle->pipeline));
389 528
390 if (!bus) 529 if (!bus)
@@ -413,6 +552,13 @@ _setup_gst_pipeline(UI_PLAY_MEDIA_Handle *handle)
413 handle 552 handle
414 ); 553 );
415 554
555 g_signal_connect(
556 G_OBJECT(bus),
557 "message::buffering",
558 (GCallback) msg_buffering_cb,
559 handle
560 );
561
416 gst_object_unref(bus); 562 gst_object_unref(bus);
417} 563}
418 564
@@ -420,10 +566,7 @@ static void*
420_ui_play_media_video_thread(void *args) 566_ui_play_media_video_thread(void *args)
421{ 567{
422 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) args; 568 UI_PLAY_MEDIA_Handle *handle = (UI_PLAY_MEDIA_Handle*) args;
423 569 _continue_playing_media(handle);
424 if (!handle->playing)
425 _continue_playing_media(handle);
426
427 return NULL; 570 return NULL;
428} 571}
429 572
@@ -435,13 +578,6 @@ ui_play_media_window_init(MESSENGER_Application *app,
435 578
436 _setup_gst_pipeline(handle); 579 _setup_gst_pipeline(handle);
437 580
438 pthread_create(
439 &(handle->video_tid),
440 NULL,
441 _ui_play_media_video_thread,
442 handle
443 );
444
445 handle->parent = GTK_WINDOW(app->ui.messenger.main_window); 581 handle->parent = GTK_WINDOW(app->ui.messenger.main_window);
446 582
447 handle->builder = gtk_builder_new_from_resource( 583 handle->builder = gtk_builder_new_from_resource(
@@ -555,6 +691,12 @@ ui_play_media_window_init(MESSENGER_Application *app,
555 gtk_builder_get_object(handle->builder, "timeline_progress_bar") 691 gtk_builder_get_object(handle->builder, "timeline_progress_bar")
556 ); 692 );
557 693
694 handle->timeline_scale = GTK_SCALE(
695 gtk_builder_get_object(handle->builder, "timeline_scale")
696 );
697
698 _set_signal_connection_of_timeline(handle, handle->sink? TRUE : FALSE);
699
558 handle->settings_button = GTK_BUTTON( 700 handle->settings_button = GTK_BUTTON(
559 gtk_builder_get_object(handle->builder, "settings_button") 701 gtk_builder_get_object(handle->builder, "settings_button")
560 ); 702 );
@@ -603,11 +745,33 @@ ui_play_media_window_init(MESSENGER_Application *app,
603} 745}
604 746
605void 747void
748ui_play_media_window_update(UI_PLAY_MEDIA_Handle *handle,
749 const gchar *uri)
750{
751 if (handle->video_tid)
752 pthread_join(handle->video_tid, NULL);
753
754 if (!(handle->pipeline))
755 return;
756
757 _disable_video_processing(handle, TRUE);
758 g_object_set(G_OBJECT(handle->pipeline), "uri", uri, NULL);
759
760 pthread_create(
761 &(handle->video_tid),
762 NULL,
763 _ui_play_media_video_thread,
764 handle
765 );
766}
767
768void
606ui_play_media_window_cleanup(UI_PLAY_MEDIA_Handle *handle) 769ui_play_media_window_cleanup(UI_PLAY_MEDIA_Handle *handle)
607{ 770{
608 GNUNET_assert(handle); 771 GNUNET_assert(handle);
609 772
610 pthread_join(handle->video_tid, NULL); 773 if (handle->video_tid)
774 pthread_join(handle->video_tid, NULL);
611 775
612 g_object_unref(handle->builder); 776 g_object_unref(handle->builder);
613 777
diff --git a/src/ui/play_media.h b/src/ui/play_media.h
index 597bf7c..75132d6 100644
--- a/src/ui/play_media.h
+++ b/src/ui/play_media.h
@@ -27,19 +27,16 @@
27 27
28#include "messenger.h" 28#include "messenger.h"
29 29
30#include <glib-2.0/glib.h>
30#include <gstreamer-1.0/gst/gst.h> 31#include <gstreamer-1.0/gst/gst.h>
31#include <pthread.h> 32#include <pthread.h>
32 33
33typedef struct UI_PLAY_MEDIA_Handle 34typedef struct UI_PLAY_MEDIA_Handle
34{ 35{
35 gboolean playing;
36 gboolean fullscreen; 36 gboolean fullscreen;
37 37
38 GstElement *pipeline; 38 GstElement *pipeline;
39 GstElement *source;
40 GstElement *decode;
41 GstElement *sink; 39 GstElement *sink;
42 GstElement *vol;
43 40
44 GtkWindow *parent; 41 GtkWindow *parent;
45 42
@@ -62,6 +59,7 @@ typedef struct UI_PLAY_MEDIA_Handle
62 GtkVolumeButton *volume_button; 59 GtkVolumeButton *volume_button;
63 GtkLabel *timeline_label; 60 GtkLabel *timeline_label;
64 GtkProgressBar *timeline_progress_bar; 61 GtkProgressBar *timeline_progress_bar;
62 GtkScale* timeline_scale;
65 63
66 GtkButton *settings_button; 64 GtkButton *settings_button;
67 65
@@ -71,6 +69,8 @@ typedef struct UI_PLAY_MEDIA_Handle
71 guint timeline; 69 guint timeline;
72 guint motion_lost; 70 guint motion_lost;
73 71
72 guint timeline_signal;
73
74 pthread_t video_tid; 74 pthread_t video_tid;
75} UI_PLAY_MEDIA_Handle; 75} UI_PLAY_MEDIA_Handle;
76 76
@@ -86,6 +86,17 @@ ui_play_media_window_init(MESSENGER_Application *app,
86 UI_PLAY_MEDIA_Handle *handle); 86 UI_PLAY_MEDIA_Handle *handle);
87 87
88/** 88/**
89 * Updates a handle for the play media window with
90 * a specific uri to play a media file from.
91 *
92 * @param handle Play media window handle
93 * @param uri URI of media file
94 */
95void
96ui_play_media_window_update(UI_PLAY_MEDIA_Handle *handle,
97 const gchar *uri);
98
99/**
89 * Cleans up the allocated resources and resets the 100 * Cleans up the allocated resources and resets the
90 * state of a given play media window handle. 101 * state of a given play media window handle.
91 * 102 *