1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * gmtk_media_player.c
4 * Copyright (C) Kevin DeKorte 2009 <kdekorte@gmail.com>
5 *
6 * gmtk_media_player.c is free software.
7 *
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * gmtk_media_tracker.c is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with playlist.c. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
23 */
24
25 #include "gmtk_media_player.h"
26 #include "gmlib.h"
27 #include "gmtk_common.h"
28
29 G_DEFINE_TYPE(GmtkMediaPlayer, gmtk_media_player, GTK_TYPE_EVENT_BOX);
30 static GObjectClass *parent_class = NULL;
31
32 static void gmtk_media_player_dispose(GObject * object);
33 static gboolean gmtk_media_player_draw_event(GtkWidget * widget, cairo_t * cr);
34 static gboolean gmtk_media_player_expose_event(GtkWidget * widget, GdkEventExpose * event);
35 static void gmtk_media_player_size_allocate(GtkWidget * widget, GtkAllocation * allocation);
36 static gboolean player_key_press_event_callback(GtkWidget * widget, GdkEventKey * event, gpointer data);
37 static gboolean player_button_press_event_callback(GtkWidget * widget, GdkEventButton * event, gpointer data);
38 static gboolean player_motion_notify_event_callback(GtkWidget * widget, GdkEventMotion * event, gpointer data);
39 static void gmtk_media_player_restart_complete_callback(GmtkMediaPlayer * player, gpointer data);
40 static void gmtk_media_player_restart_shutdown_complete_callback(GmtkMediaPlayer * player, gpointer data);
41
42 // monitoring functions
43 gpointer launch_mplayer(gpointer data);
44 gboolean thread_reader_error(GIOChannel * source, GIOCondition condition, gpointer data);
45 gboolean thread_reader(GIOChannel * source, GIOCondition condition, gpointer data);
46 gboolean thread_query(gpointer data);
47 gboolean thread_complete(GIOChannel * source, GIOCondition condition, gpointer data);
48
49 gboolean write_to_mplayer(GmtkMediaPlayer * player, const gchar * cmd);
50 gboolean detect_mplayer_features(GmtkMediaPlayer * player);
51
player_realized(GtkWidget * widget,gpointer data)52 static void player_realized(GtkWidget * widget, gpointer data)
53 {
54 GtkStyle *style;
55
56 style = gtk_widget_get_style(widget);
57 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &(style->black));
58 gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, &(style->black));
59 gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, &(style->black));
60 gtk_widget_modify_bg(widget, GTK_STATE_PRELIGHT, &(style->black));
61 gtk_widget_modify_bg(widget, GTK_STATE_INSENSITIVE, &(style->black));
62
63 }
64
alignment_realized(GtkWidget * widget,gpointer data)65 static void alignment_realized(GtkWidget * widget, gpointer data)
66 {
67 GtkStyle *style;
68
69 style = gtk_widget_get_style(widget);
70 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &(style->black));
71 gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, &(style->black));
72 gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, &(style->black));
73 gtk_widget_modify_bg(widget, GTK_STATE_PRELIGHT, &(style->black));
74 gtk_widget_modify_bg(widget, GTK_STATE_INSENSITIVE, &(style->black));
75
76 }
77
vodesc_looks_like_vo(gchar const * const desc,gchar const * const vo)78 static gboolean vodesc_looks_like_vo(gchar const *const desc, gchar const *const vo)
79 {
80 if (g_strcmp0(desc, vo) == 0) {
81 return TRUE;
82 }
83 if (!g_str_has_prefix(desc, vo)) {
84 return FALSE;
85 }
86 /* we know that they are not equal but desc starts with vo, i.e. desc is longer than vo */
87 /* now to check that desc looks like vo: */
88 const size_t vol = strlen(vo);
89 if (desc[vol] == ':') {
90 return TRUE;
91 }
92 return FALSE;
93 }
94
socket_realized(GtkWidget * widget,gpointer data)95 static void socket_realized(GtkWidget * widget, gpointer data)
96 {
97 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(data);
98 GtkStyle *style;
99
100 player->socket_id = GPOINTER_TO_INT(gtk_socket_get_id(GTK_SOCKET(widget)));
101 style = gtk_widget_get_style(widget);
102 if (player->vo != NULL) {
103 if (!vodesc_looks_like_vo(player->vo, "vdpau")) {
104 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &(style->black));
105 gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, &(style->black));
106 gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, &(style->black));
107 gtk_widget_modify_bg(widget, GTK_STATE_PRELIGHT, &(style->black));
108 gtk_widget_modify_bg(widget, GTK_STATE_INSENSITIVE, &(style->black));
109 } else {
110 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, NULL);
111 gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, NULL);
112 gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, NULL);
113 gtk_widget_modify_bg(widget, GTK_STATE_PRELIGHT, NULL);
114 gtk_widget_modify_bg(widget, GTK_STATE_INSENSITIVE, NULL);
115 }
116 } else {
117 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &(style->black));
118 gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, &(style->black));
119 gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, &(style->black));
120 gtk_widget_modify_bg(widget, GTK_STATE_PRELIGHT, &(style->black));
121 gtk_widget_modify_bg(widget, GTK_STATE_INSENSITIVE, &(style->black));
122 }
123
124 }
125
126
127 // use g_idle_add to emit the signals outside of the thread, makes them be emitted in the main loop
128 // this is done so that thread_enter/thread_leave is not needed
signal_event(gpointer data)129 gboolean signal_event(gpointer data)
130 {
131 GmtkMediaPlayerEvent *event = (GmtkMediaPlayerEvent *) data;
132
133 if (event && event->event_name != NULL
134 && (event->player->restart == FALSE || event->event_data_int == ATTRIBUTE_AF_EXPORT_FILENAME)) {
135
136 switch (event->type) {
137 case EVENT_TYPE_INT:
138 g_signal_emit_by_name(event->player, event->event_name, event->event_data_int);
139 break;
140
141 case EVENT_TYPE_DOUBLE:
142 g_signal_emit_by_name(event->player, event->event_name, event->event_data_double);
143 break;
144
145 case EVENT_TYPE_BOOLEAN:
146 g_signal_emit_by_name(event->player, event->event_name, event->event_data_boolean);
147 break;
148
149 case EVENT_TYPE_ALLOCATION:
150 if (gtk_widget_get_visible(GTK_WIDGET(event->player))) {
151 if (!(event->event_allocation->width >= 65535 || event->event_allocation->height >= 65535))
152 g_signal_emit_by_name(event->player, event->event_name, event->event_allocation);
153 }
154 g_free(event->event_allocation);
155 event->event_allocation = NULL;
156 break;
157
158 case EVENT_TYPE_STRING:
159 g_signal_emit_by_name(event->player, event->event_name, event->event_data_string);
160 g_free(event->event_data_string);
161 event->event_data_string = NULL;
162 break;
163
164 default:
165 gm_log(event->player->debug, G_LOG_LEVEL_MESSAGE, "undefined event %s", event->event_name);
166 }
167 g_free(event->event_name);
168 event->event_name = NULL;
169 }
170 if (event)
171 g_free(event);
172
173 return FALSE;
174 }
175
176 // build the events we are going to signal
create_event_int(GmtkMediaPlayer * player,const gchar * name,gint value)177 void create_event_int(GmtkMediaPlayer * player, const gchar * name, gint value)
178 {
179 GmtkMediaPlayerEvent *event;
180
181 event = g_new0(GmtkMediaPlayerEvent, 1);
182 event->player = player;
183 event->type = EVENT_TYPE_INT;
184 event->event_name = g_strdup(name);
185 event->event_data_int = value;
186 g_idle_add(signal_event, event);
187 }
188
create_event_double(GmtkMediaPlayer * player,const gchar * name,gdouble value)189 void create_event_double(GmtkMediaPlayer * player, const gchar * name, gdouble value)
190 {
191 GmtkMediaPlayerEvent *event;
192
193 event = g_new0(GmtkMediaPlayerEvent, 1);
194 event->player = player;
195 event->type = EVENT_TYPE_DOUBLE;
196 event->event_name = g_strdup(name);
197 event->event_data_double = value;
198 g_idle_add(signal_event, event);
199 }
200
create_event_boolean(GmtkMediaPlayer * player,const gchar * name,gboolean value)201 void create_event_boolean(GmtkMediaPlayer * player, const gchar * name, gboolean value)
202 {
203 GmtkMediaPlayerEvent *event;
204
205 event = g_new0(GmtkMediaPlayerEvent, 1);
206 event->player = player;
207 event->type = EVENT_TYPE_BOOLEAN;
208 event->event_name = g_strdup(name);
209 event->event_data_boolean = value;
210 g_idle_add(signal_event, event);
211 }
212
create_event_allocation(GmtkMediaPlayer * player,const gchar * name,GtkAllocation * allocation)213 void create_event_allocation(GmtkMediaPlayer * player, const gchar * name, GtkAllocation * allocation)
214 {
215 GmtkMediaPlayerEvent *event;
216
217 event = g_new0(GmtkMediaPlayerEvent, 1);
218 event->player = player;
219 event->type = EVENT_TYPE_ALLOCATION;
220 event->event_name = g_strdup(name);
221 event->event_allocation = g_new0(GtkAllocation, 1);
222 memcpy(event->event_allocation, allocation, sizeof(GtkAllocation));
223 g_idle_add(signal_event, event);
224
225 }
226
create_event_string(GmtkMediaPlayer * player,const gchar * name,gchar * string)227 void create_event_string(GmtkMediaPlayer * player, const gchar * name, gchar * string)
228 {
229 GmtkMediaPlayerEvent *event;
230
231 event = g_new0(GmtkMediaPlayerEvent, 1);
232 event->player = player;
233 event->type = EVENT_TYPE_STRING;
234 event->event_name = g_strdup(name);
235 event->event_data_string = g_strdup(string);
236 g_idle_add(signal_event, event);
237
238 }
239
240 // helper function to assist retry/fallback
gmtk_media_player_switch_protocol(const gchar * uri,gchar * new_protocol)241 gchar *gmtk_media_player_switch_protocol(const gchar * uri, gchar * new_protocol)
242 {
243 gchar *p;
244
245 p = g_strrstr(uri, "://");
246
247 if (p != NULL)
248 return g_strdup_printf("%s%s", new_protocol, p);
249 else
250 return NULL;
251 }
252
gmtk_media_state_to_string(const GmtkMediaPlayerMediaState media_state)253 const gchar *gmtk_media_state_to_string(const GmtkMediaPlayerMediaState media_state)
254 {
255 switch (media_state) {
256 case MEDIA_STATE_UNKNOWN:
257 return "unknown";
258 case MEDIA_STATE_PLAY:
259 return "play";
260 case MEDIA_STATE_PAUSE:
261 return "pause";
262 case MEDIA_STATE_STOP:
263 return "stop";
264 case MEDIA_STATE_QUIT:
265 return "quit";
266 case MEDIA_STATE_BUFFERING:
267 return "buffering";
268 default:
269 return "???";
270 }
271 }
272
gmtk_media_player_log_state(GmtkMediaPlayer * player,char const * const context)273 static void gmtk_media_player_log_state(GmtkMediaPlayer * player, char const *const context)
274 {
275 // Gmtk_Media_Player_Log_State
276 #define GMPLS_LEN 1024
277 gchar msg[GMPLS_LEN] = "";
278 gchar *tmp;
279
280 if (context != NULL && (*context) != '\0') {
281 g_strlcat(msg, context, GMPLS_LEN);
282 g_strlcat(msg, ": ", GMPLS_LEN);
283 }
284 tmp = g_strdup_printf("position=%.3f length=%.3f start_time=%.3f run_time=%.3f volume=%.2f", player->position,
285 player->length, player->start_time, player->run_time, player->volume);
286 g_strlcat(msg, tmp, GMPLS_LEN);
287 g_free(tmp);
288
289 if (player->muted) {
290 g_strlcat(msg, " muted", GMPLS_LEN);
291 }
292
293 g_strlcat(msg, " player=", GMPLS_LEN);
294 switch (player->player_state) {
295 case PLAYER_STATE_DEAD:
296 g_strlcat(msg, "dead", GMPLS_LEN);
297 break;
298 case PLAYER_STATE_RUNNING:
299 g_strlcat(msg, "running", GMPLS_LEN);
300 break;
301 default:
302 g_strlcat(msg, "???", GMPLS_LEN);
303 }
304
305 g_strlcat(msg, " media=", GMPLS_LEN);
306 g_strlcat(msg, gmtk_media_state_to_string(player->media_state), GMPLS_LEN);
307 g_strlcat(msg, " uri=", GMPLS_LEN);
308 if (player->uri != NULL) {
309 g_strlcat(msg, player->uri, GMPLS_LEN);
310 }
311 gm_log(player->debug, G_LOG_LEVEL_INFO, "%s", msg);
312 }
313
gmtk_media_player_class_init(GmtkMediaPlayerClass * class)314 static void gmtk_media_player_class_init(GmtkMediaPlayerClass * class)
315 {
316 GtkWidgetClass *widget_class;
317 GObjectClass *object_class;
318
319 object_class = G_OBJECT_CLASS(class);
320 widget_class = GTK_WIDGET_CLASS(class);
321
322 parent_class = g_type_class_peek_parent(class);
323 G_OBJECT_CLASS(class)->dispose = gmtk_media_player_dispose;
324 #ifdef GTK3_ENABLED
325 widget_class->draw = gmtk_media_player_draw_event;
326 #else
327 widget_class->expose_event = gmtk_media_player_expose_event;
328 #endif
329 widget_class->size_allocate = gmtk_media_player_size_allocate;
330
331 g_signal_new("position-changed",
332 G_OBJECT_CLASS_TYPE(object_class),
333 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
334 G_STRUCT_OFFSET(GmtkMediaPlayerClass, position_changed),
335 NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE);
336
337 g_signal_new("cache-percent-changed",
338 G_OBJECT_CLASS_TYPE(object_class),
339 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
340 G_STRUCT_OFFSET(GmtkMediaPlayerClass, cache_percent_changed),
341 NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE);
342
343 g_signal_new("attribute-changed",
344 G_OBJECT_CLASS_TYPE(object_class),
345 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
346 G_STRUCT_OFFSET(GmtkMediaPlayerClass, attribute_changed),
347 NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
348
349 g_signal_new("player-state-changed",
350 G_OBJECT_CLASS_TYPE(object_class),
351 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
352 G_STRUCT_OFFSET(GmtkMediaPlayerClass, player_state_changed),
353 NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
354
355 g_signal_new("media-state-changed",
356 G_OBJECT_CLASS_TYPE(object_class),
357 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
358 G_STRUCT_OFFSET(GmtkMediaPlayerClass, media_state_changed),
359 NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
360
361 g_signal_new("subtitles-changed",
362 G_OBJECT_CLASS_TYPE(object_class),
363 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
364 G_STRUCT_OFFSET(GmtkMediaPlayerClass, subtitles_changed),
365 NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
366
367 g_signal_new("audio-tracks-changed",
368 G_OBJECT_CLASS_TYPE(object_class),
369 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
370 G_STRUCT_OFFSET(GmtkMediaPlayerClass, audio_tracks_changed),
371 NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
372
373 g_signal_new("restart-shutdown-complete",
374 G_OBJECT_CLASS_TYPE(object_class),
375 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
376 G_STRUCT_OFFSET(GmtkMediaPlayerClass, restart_shutdown_complete),
377 NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
378
379 g_signal_new("restart-complete",
380 G_OBJECT_CLASS_TYPE(object_class),
381 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
382 G_STRUCT_OFFSET(GmtkMediaPlayerClass, restart_complete),
383 NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
384
385 g_signal_new("error-message",
386 G_OBJECT_CLASS_TYPE(object_class),
387 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
388 G_STRUCT_OFFSET(GmtkMediaPlayerClass, error_message),
389 NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
390
391 }
392
gmtk_media_player_init(GmtkMediaPlayer * player)393 static void gmtk_media_player_init(GmtkMediaPlayer * player)
394 {
395 GtkStyle *style;
396
397 // player is an GtkEventBox that holds a GtkAlignment that holds a GtkSocket
398 // mplayer uses the xwindow id from the socket to display media
399
400 gtk_widget_add_events(GTK_WIDGET(player),
401 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
402 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
403 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK | GDK_SCROLL_MASK);
404 #ifdef GTK3_ENABLED
405 gtk_widget_set_app_paintable(GTK_WIDGET(player), TRUE);
406 #endif
407
408 g_signal_connect(player, "key_press_event", G_CALLBACK(player_key_press_event_callback), NULL);
409 g_signal_connect(player, "motion_notify_event", G_CALLBACK(player_motion_notify_event_callback), NULL);
410 g_signal_connect(player, "button_press_event", G_CALLBACK(player_button_press_event_callback), NULL);
411 gtk_widget_push_composite_child();
412
413 player->alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
414 player->socket = gtk_socket_new();
415 g_signal_connect(G_OBJECT(player), "realize", G_CALLBACK(player_realized), NULL);
416 g_signal_connect(G_OBJECT(player->alignment), "realize", G_CALLBACK(alignment_realized), NULL);
417 g_signal_connect(G_OBJECT(player->socket), "realize", G_CALLBACK(socket_realized), player);
418 gtk_container_add(GTK_CONTAINER(player), player->alignment);
419 gtk_container_add(GTK_CONTAINER(player->alignment), player->socket);
420 #ifdef GTK2_18_ENABLED
421 gtk_widget_set_has_window(GTK_WIDGET(player->socket), TRUE);
422 gtk_widget_set_can_focus(GTK_WIDGET(player->socket), TRUE);
423 gtk_widget_set_can_default(GTK_WIDGET(player->socket), TRUE);
424 #else
425 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(player->socket), GTK_CAN_FOCUS);
426 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(player->socket), GTK_CAN_DEFAULT);
427 #endif
428 gtk_widget_activate(GTK_WIDGET(player->socket));
429
430 g_signal_connect(player->socket, "key_press_event", G_CALLBACK(player_key_press_event_callback), player);
431
432 g_signal_connect(player, "restart-shutdown-complete",
433 G_CALLBACK(gmtk_media_player_restart_shutdown_complete_callback), NULL);
434 g_signal_connect(player, "restart-complete", G_CALLBACK(gmtk_media_player_restart_complete_callback), NULL);
435 gtk_widget_pop_composite_child();
436
437 gtk_widget_show_all(GTK_WIDGET(player));
438 style = gtk_widget_get_style(GTK_WIDGET(player));
439 player->default_background = gdk_color_copy(&(style->bg[GTK_STATE_NORMAL]));
440 player->player_state = PLAYER_STATE_DEAD;
441 player->media_state = MEDIA_STATE_UNKNOWN;
442 player->uri = NULL;
443 player->message = NULL;
444 player->mplayer_thread = NULL;
445 player->aspect_ratio = ASPECT_DEFAULT;
446 player->mplayer_complete_cond = g_cond_new();
447 player->thread_running = g_mutex_new();
448 player->video_width = 0;
449 player->video_height = 0;
450 player->video_present = FALSE;
451 player->media_device = NULL;
452 player->type = TYPE_FILE;
453 player->title_is_menu = FALSE;
454 player->start_time = 0.0;
455 player->run_time = 0.0;
456 player->vo = NULL;
457 player->ao = NULL;
458 player->cache_size = 0;
459 player->subtitles = NULL;
460 player->audio_tracks = NULL;
461 player->af_export_filename = gm_tempname(NULL, "mplayer-af_exportXXXXXX");
462 player->brightness = 0;
463 player->contrast = 0;
464 player->gamma = 0;
465 player->hue = 0;
466 player->osdlevel = 0;
467 player->saturation = 0;
468 player->restart = FALSE;
469 player->video_format = NULL;
470 player->video_codec = NULL;
471 player->audio_format = NULL;
472 player->audio_codec = NULL;
473 player->disable_upscaling = FALSE;
474 player->mplayer_binary = NULL;
475 player->extra_opts = NULL;
476 player->use_mplayer2 = FALSE;
477 player->features_detected = FALSE;
478 player->zoom = 1.0;
479 player->speed_multiplier = 1.0;
480 player->subtitle_scale = 1.0;
481 player->subtitle_delay = 0.0;
482 player->subtitle_position = 0;
483 player->subtitle_fuzziness = 0;
484 player->audio_delay = 0.0;
485 player->restart = FALSE;
486 player->debug = 1;
487 player->channel_in = NULL;
488 player->channel_out = NULL;
489 player->channel_err = NULL;
490 player->retry_on_full_cache = FALSE;
491 player->profile = NULL;
492 player->alang = NULL;
493 player->slang = NULL;
494 player->artist = NULL;
495 player->title = NULL;
496 player->album = NULL;
497 player->disposed = FALSE;
498 player->player_lock = g_mutex_new();
499 player->name_regex = g_regex_new(".*name\\s*:\\s*(.*)\n", G_REGEX_CASELESS, 0, NULL);
500 player->genre_regex = g_regex_new(".*genre\\s*:\\s*(.*)\n", G_REGEX_CASELESS, 0, NULL);
501 player->title_regex = g_regex_new(".*title\\s*:\\s*(.*)\n", G_REGEX_CASELESS, 0, NULL);
502 player->artist_regex = g_regex_new(".*artist\\s*:\\s*(.*)\n", G_REGEX_CASELESS, 0, NULL);
503 player->album_regex = g_regex_new(".*album\\s*:\\s*(.*)\n", G_REGEX_CASELESS, 0, NULL);
504 player->deintN_regex = g_regex_new("(.*)(:deint=[0-9]+)\\b(.*)", G_REGEX_CASELESS, 0, NULL);
505
506 gmtk_media_player_log_state(player, "after init");
507 }
508
gmtk_media_player_dispose(GObject * object)509 static void gmtk_media_player_dispose(GObject * object)
510 {
511
512 GmtkMediaPlayer *player;
513
514 if (object == NULL) {
515 return;
516 }
517
518 player = GMTK_MEDIA_PLAYER(object);
519
520 if (player->disposed) {
521 return;
522 }
523 player->disposed = TRUE;
524
525 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "gmtk_media_player_dispose");
526
527 // cleanup the memory used
528
529 if (player->uri != NULL) {
530 g_free(player->uri);
531 player->uri = NULL;
532 }
533 if (player->media_device != NULL) {
534 g_free(player->media_device);
535 player->media_device = NULL;
536 }
537 if (player->vo != NULL) {
538 g_free(player->vo);
539 player->vo = NULL;
540 }
541 if (player->ao != NULL) {
542 g_free(player->ao);
543 player->ao = NULL;
544 }
545
546 if (player->artist != NULL) {
547 g_free(player->artist);
548 player->artist = NULL;
549 }
550
551 if (player->title != NULL) {
552 g_free(player->title);
553 player->title = NULL;
554 }
555
556 if (player->message != NULL) {
557 g_free(player->message);
558 player->message = NULL;
559 }
560
561 if (player->extra_opts != NULL) {
562 g_free(player->extra_opts);
563 player->extra_opts = NULL;
564 }
565
566 if (player->video_format != NULL) {
567 g_free(player->video_format);
568 player->video_format = NULL;
569 }
570
571 if (player->video_codec != NULL) {
572 g_free(player->video_codec);
573 player->video_codec = NULL;
574 }
575
576 if (player->audio_format != NULL) {
577 g_free(player->audio_format);
578 player->audio_format = NULL;
579 }
580
581 if (player->audio_codec != NULL) {
582 g_free(player->audio_codec);
583 player->audio_codec = NULL;
584 }
585
586 if (player->af_export_filename != NULL) {
587 g_free(player->af_export_filename);
588 player->af_export_filename = NULL;
589 }
590
591 if (player->subtitle_font != NULL) {
592 g_free(player->subtitle_font);
593 player->subtitle_font = NULL;
594 }
595
596 if (player->subtitle_color != NULL) {
597 g_free(player->subtitle_color);
598 player->subtitle_color = NULL;
599 }
600
601 if (player->profile != NULL) {
602 g_free(player->profile);
603 player->profile = NULL;
604 }
605
606 if (player->slang != NULL) {
607 g_free(player->slang);
608 player->slang = NULL;
609 }
610
611 if (player->alang != NULL) {
612 g_free(player->alang);
613 player->alang = NULL;
614 }
615
616 gdk_color_free(player->default_background);
617
618 G_OBJECT_CLASS(parent_class)->dispose(object);
619 }
620
gmtk_media_player_draw_event(GtkWidget * widget,cairo_t * cr)621 static gboolean gmtk_media_player_draw_event(GtkWidget * widget, cairo_t * cr)
622 {
623 GtkStyle *style;
624 GtkAllocation allocation;
625
626 style = gtk_widget_get_style(widget);
627 gmtk_get_allocation(widget, &allocation);
628
629 cairo_set_source_rgb(cr, style->black.red / 65535.0, style->black.green / 65535.0, style->black.blue / 65535.0);
630 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
631 cairo_fill(cr);
632 cairo_stroke(cr);
633
634 return FALSE;
635 }
636
gmtk_media_player_expose_event(GtkWidget * widget,GdkEventExpose * event)637 static gboolean gmtk_media_player_expose_event(GtkWidget * widget, GdkEventExpose * event)
638 {
639 return FALSE;
640 }
641
gmtk_media_player_send_key_press_event(GmtkMediaPlayer * widget,GdkEventKey * event,gpointer data)642 gboolean gmtk_media_player_send_key_press_event(GmtkMediaPlayer * widget, GdkEventKey * event, gpointer data)
643 {
644 return player_key_press_event_callback(GTK_WIDGET(widget), event, data);
645 }
646
647 /*
648 sub_select [value]
649 Display subtitle with index [value]. Turn subtitle display off if
650 [value] is -1 or greater than the highest available subtitle index.
651 Cycle through the available subtitles if [value] is omitted or less
652 than -1 (forward or backward respectively).
653 Supported subtitle sources are -sub options on the command
654 line, VOBsubs, DVD subtitles, and Ogg and Matroska text streams.
655 This command is mainly for cycling all subtitles, if you want to set
656 a specific subtitle, use sub_file, sub_vob, or sub_demux.
657
658 GmtkMediaPlayerSubtitle
659
660 count: (gdouble) g_list_length(player->subtitles)
661
662 iter = player->subtitles;
663 while (iter) {
664 subtitle = (GmtkMediaPlayerSubtitle *) iter->data;
665 if (subtitle->id == player->subtitle_id && subtitle->is_file == player->subtitle_is_file)
666 value = subtitle->label;
667 iter = iter->next;
668 }
669
670 sub_visibility [0|1]
671
672 properties: sub
673 get_property <property>
674 set_property <property> <value>
675
676 */
gmtk_media_player_cycle_subtitles(GmtkMediaPlayer * player)677 static void gmtk_media_player_cycle_subtitles(GmtkMediaPlayer * player)
678 {
679 write_to_mplayer(player, "sub_select\n");
680 }
681
player_key_press_event_callback(GtkWidget * widget,GdkEventKey * event,gpointer data)682 static gboolean player_key_press_event_callback(GtkWidget * widget, GdkEventKey * event, gpointer data)
683 {
684 GmtkMediaPlayer *player;
685 GtkAllocation alloc;
686 gchar *cmd;
687
688 if (data != NULL) {
689 player = GMTK_MEDIA_PLAYER(data);
690 } else {
691 player = GMTK_MEDIA_PLAYER(widget);
692 }
693
694 if (event->is_modifier)
695 return TRUE;
696
697 if ((event->state & GDK_CONTROL_MASK) == 0 && (event->state & GDK_MOD1_MASK) == 0) {
698 switch (event->keyval) {
699 case GDK_Right:
700 if (player->title_is_menu) {
701 write_to_mplayer(player, "dvdnav 4\n");
702 }
703 break;
704 case GDK_Left:
705 if (player->title_is_menu) {
706 write_to_mplayer(player, "dvdnav 3\n");
707 }
708 break;
709 case GDK_Up:
710 if (player->title_is_menu) {
711 write_to_mplayer(player, "dvdnav 1\n");
712 }
713 break;
714 case GDK_Down:
715 if (player->title_is_menu) {
716 write_to_mplayer(player, "dvdnav 2\n");
717 }
718 break;
719 case GDK_Return:
720 if (player->title_is_menu) {
721 write_to_mplayer(player, "dvdnav 6\n");
722 }
723 return TRUE;
724 break;
725 case GDK_Home:
726 if (!player->title_is_menu) {
727 write_to_mplayer(player, "dvdnav menu\n");
728 }
729 return TRUE;
730 break;
731 case GDK_space:
732 case GDK_p:
733 switch (player->media_state) {
734 case MEDIA_STATE_PAUSE:
735 gmtk_media_player_set_state(player, MEDIA_STATE_PLAY);
736 break;
737 case MEDIA_STATE_PLAY:
738 gmtk_media_player_set_state(player, MEDIA_STATE_PAUSE);
739 break;
740 default:
741 break;
742 }
743 break;
744 case GDK_1:
745 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_CONTRAST, -5);
746 break;
747 case GDK_2:
748 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_CONTRAST, 5);
749 break;
750 case GDK_3:
751 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_BRIGHTNESS, -5);
752 break;
753 case GDK_4:
754 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_BRIGHTNESS, 5);
755 break;
756 case GDK_5:
757 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_HUE, -5);
758 break;
759 case GDK_6:
760 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_HUE, 5);
761 break;
762 case GDK_7:
763 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_SATURATION, -5);
764 break;
765 case GDK_8:
766 gmtk_media_player_set_attribute_integer_delta(player, ATTRIBUTE_SATURATION, 5);
767 break;
768 case GDK_plus:
769 write_to_mplayer(player, "audio_delay 0.1 0\n");
770 break;
771 case GDK_minus:
772 write_to_mplayer(player, "audio_delay -0.1 0\n");
773 break;
774 case GDK_numbersign:
775 write_to_mplayer(player, "switch_audio -1\n");
776 return TRUE;
777 break;
778 case GDK_period:
779 if (player->media_state == MEDIA_STATE_PAUSE)
780 write_to_mplayer(player, "frame_step\n");
781 break;
782 case GDK_KP_Add:
783 player->zoom += 0.10;
784 player->zoom = CLAMP(player->zoom, 0.1, 10.0);
785 gmtk_get_allocation(GTK_WIDGET(player), &alloc);
786 gmtk_media_player_size_allocate(GTK_WIDGET(player), &alloc);
787 break;
788 case GDK_KP_Subtract:
789 player->zoom -= 0.10;
790 player->zoom = CLAMP(player->zoom, 0.1, 10.0);
791 gmtk_get_allocation(GTK_WIDGET(player), &alloc);
792 gmtk_media_player_size_allocate(GTK_WIDGET(player), &alloc);
793 break;
794 case GDK_KP_Enter:
795 player->zoom = 1.0;
796 gmtk_get_allocation(GTK_WIDGET(player), &alloc);
797 gmtk_media_player_size_allocate(GTK_WIDGET(player), &alloc);
798 break;
799 case GDK_j:
800 gmtk_media_player_cycle_subtitles(player);
801 break;
802 case GDK_d:
803 write_to_mplayer(player, "frame_drop\n");
804 cmd =
805 g_strdup_printf("osd_show_property_text \"%s: ${framedropping}\" 1000 1\n",
806 g_dgettext(GETTEXT_PACKAGE, "Frame Dropping"));
807 write_to_mplayer(player, cmd);
808 g_free(cmd);
809 break;
810 case GDK_b:
811 write_to_mplayer(player, "sub_pos -1 0\n");
812 break;
813 case GDK_B:
814 write_to_mplayer(player, "sub_pos 1 0\n");
815 break;
816 case GDK_D:
817 write_to_mplayer(player, "step_property deinterlace\n");
818 cmd =
819 g_strdup_printf("osd_show_property_text \"%s: ${deinterlace}\" 1000 1\n",
820 g_dgettext(GETTEXT_PACKAGE, "Deinterlace"));
821 write_to_mplayer(player, cmd);
822 g_free(cmd);
823 break;
824 case GDK_s:
825 case GDK_S:
826 write_to_mplayer(player, "screenshot 0\n");
827 break;
828 case GDK_x:
829 write_to_mplayer(player, "sub_delay 0.1\n");
830 break;
831 case GDK_z:
832 write_to_mplayer(player, "sub_delay -0.1\n");
833 break;
834 case GDK_o:
835 write_to_mplayer(player, "osd\n");
836 break;
837 case GDK_h:
838 write_to_mplayer(player, "tv_step_channel -1\n");
839 break;
840 case GDK_k:
841 write_to_mplayer(player, "tv_step_channel 1\n");
842 break;
843 default:
844 gm_log(player->debug, G_LOG_LEVEL_INFO, "ignoring key %s%s%s%s",
845 (event->state & GDK_CONTROL_MASK) ? "Control-" : "", (event->state & GDK_MOD1_MASK) ? "Alt-" : "",
846 (event->state & GDK_SHIFT_MASK) ? "Shift-" : "", gdk_keyval_name(event->keyval));
847 }
848
849 }
850 return FALSE;
851 }
852
player_button_press_event_callback(GtkWidget * widget,GdkEventButton * event,gpointer data)853 static gboolean player_button_press_event_callback(GtkWidget * widget, GdkEventButton * event, gpointer data)
854 {
855 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(widget);
856 gchar *cmd;
857
858 if (event->button == 1) {
859 if (player->title_is_menu) {
860 cmd = g_strdup_printf("dvdnav mouse\n");
861 write_to_mplayer(player, cmd);
862 g_free(cmd);
863 }
864 }
865
866
867 return FALSE;
868 }
869
player_motion_notify_event_callback(GtkWidget * widget,GdkEventMotion * event,gpointer data)870 static gboolean player_motion_notify_event_callback(GtkWidget * widget, GdkEventMotion * event, gpointer data)
871 {
872 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(widget);
873 gchar *cmd;
874 gint x, y;
875 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4
876 GdkDeviceManager *device_manager;
877 GdkDevice *pointer;
878 #endif
879
880 if (player->title_is_menu) {
881 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4
882 device_manager = gdk_display_get_device_manager(gtk_widget_get_display(widget));
883 pointer = gdk_device_manager_get_client_pointer(device_manager);
884 gdk_window_get_device_position(gtk_widget_get_window(widget), pointer, &x, &y, NULL);
885 #else
886 gtk_widget_get_pointer(player->socket, &x, &y);
887 #endif
888 cmd = g_strdup_printf("set_mouse_pos %i %i\n", x, y);
889 write_to_mplayer(player, cmd);
890 g_free(cmd);
891 }
892
893 return FALSE;
894
895 }
896
gmtk_media_player_size_allocate(GtkWidget * widget,GtkAllocation * allocation)897 static void gmtk_media_player_size_allocate(GtkWidget * widget, GtkAllocation * allocation)
898 {
899 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(widget);
900 gdouble video_aspect;
901 gdouble widget_aspect;
902 gfloat xscale, yscale;
903
904 if (allocation->width <= 0 || allocation->height <= 0) {
905 gmtk_get_allocation(widget, allocation);
906 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "widget allocation %i x %i", allocation->width, allocation->height);
907 }
908 // protect against possible divide by zero
909 if (allocation->width == 0 || allocation->height == 0) {
910 return;
911 }
912
913 if (player->video_width == 0 || player->video_height == 0 || !gmtk_widget_get_realized(widget)) {
914 gtk_alignment_set(GTK_ALIGNMENT(player->alignment), 0.0, 0.0, 1.0, 1.0);
915 } else {
916 switch (player->aspect_ratio) {
917 case ASPECT_4X3:
918 video_aspect = 4.0 / 3.0;
919 break;
920 case ASPECT_16X9:
921 video_aspect = 16.0 / 9.0;
922 break;
923 case ASPECT_16X10:
924 video_aspect = 16.0 / 10.0;
925 break;
926 case ASPECT_WINDOW:
927 video_aspect = (gdouble) allocation->width / (gdouble) allocation->height;
928 break;
929 case ASPECT_ANAMORPHIC:
930 video_aspect = 2.39;
931 break;
932 case ASPECT_DEFAULT:
933 default:
934 video_aspect = (gdouble) player->video_width / (gdouble) player->video_height;
935 break;
936 }
937
938 widget_aspect = (gdouble) allocation->width / (gdouble) allocation->height;
939
940 if (player->disable_upscaling && allocation->width > player->video_width
941 && allocation->height > player->video_height) {
942
943 gtk_alignment_set(GTK_ALIGNMENT(player->alignment), 0.5, 0.5,
944 CLAMP((gdouble) player->video_width / (gdouble) allocation->width, 0.1, 1.0),
945 CLAMP((gdouble) player->video_height / (gdouble) allocation->height, 0.1, 1.0));
946
947 } else {
948 if (video_aspect > widget_aspect) {
949 yscale = ((gdouble) allocation->width / video_aspect) / (gdouble) allocation->height;
950
951 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "yscale = %lf", yscale);
952 if (yscale > 0.0) {
953 gtk_alignment_set(GTK_ALIGNMENT(player->alignment), 0.0, 0.5, 1.0, CLAMP(yscale, 0.1, 1.0));
954 } else {
955 gtk_alignment_set(GTK_ALIGNMENT(player->alignment), 0.0, 0.5, 1.0, 1.0);
956 }
957 } else {
958 xscale = ((gdouble) allocation->height * video_aspect) / (gdouble) allocation->width;
959
960 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "xscale = %lf", xscale);
961 if (xscale > 0.0) {
962 gtk_alignment_set(GTK_ALIGNMENT(player->alignment), 0.5, 0.0, CLAMP(xscale, 0.1, 1.0), 1.0);
963 } else {
964 gtk_alignment_set(GTK_ALIGNMENT(player->alignment), 0.5, 0.0, 1.0, 1.0);
965 }
966 }
967 }
968 }
969
970
971 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "gmtk allocation video:%s %ix%i", gm_bool_to_string(player->video_present),
972 allocation->width, allocation->height);
973 GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation);
974
975 }
976
gmtk_media_player_new()977 GtkWidget *gmtk_media_player_new()
978 {
979 GtkWidget *player = g_object_new(GMTK_TYPE_MEDIA_PLAYER, NULL);
980
981 return player;
982 }
983
gmtk_media_player_restart_complete_callback(GmtkMediaPlayer * player,gpointer data)984 static void gmtk_media_player_restart_complete_callback(GmtkMediaPlayer * player, gpointer data)
985 {
986 gmtk_media_player_seek(player, player->restart_position, SEEK_ABSOLUTE);
987 player->restart = FALSE;
988 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "restart state = %s, current state = %s",
989 gmtk_media_state_to_string(player->restart_state),
990 gmtk_media_state_to_string(gmtk_media_player_get_media_state(player)));
991 if (player->restart_state != gmtk_media_player_get_media_state(player))
992 gmtk_media_player_set_state(GMTK_MEDIA_PLAYER(player), player->restart_state);
993 gm_log(player->debug, G_LOG_LEVEL_INFO, "restart complete");
994 }
995
gmtk_media_player_restart_shutdown_complete_callback(GmtkMediaPlayer * player,gpointer data)996 static void gmtk_media_player_restart_shutdown_complete_callback(GmtkMediaPlayer * player, gpointer data)
997 {
998 if (player->restart) {
999 if (player->restart_state != MEDIA_STATE_STOP) {
1000 gmtk_media_player_set_state(GMTK_MEDIA_PLAYER(player), MEDIA_STATE_PLAY);
1001 } else {
1002 player->restart = FALSE;
1003 }
1004 }
1005 }
1006
gmtk_media_player_restart(GmtkMediaPlayer * player)1007 void gmtk_media_player_restart(GmtkMediaPlayer * player)
1008 {
1009 if (player->player_state == PLAYER_STATE_RUNNING) {
1010 player->restart = TRUE;
1011 player->restart_state = gmtk_media_player_get_media_state(player);
1012 gmtk_media_player_set_state(player, MEDIA_STATE_PAUSE);
1013 player->restart_position = player->position;
1014 gmtk_media_player_set_state(GMTK_MEDIA_PLAYER(player), MEDIA_STATE_QUIT);
1015 }
1016 }
1017
1018 // this will take a new URI, but better to shut it down and start a new instance
gmtk_media_player_set_uri(GmtkMediaPlayer * player,const gchar * uri)1019 void gmtk_media_player_set_uri(GmtkMediaPlayer * player, const gchar * uri)
1020 {
1021 gchar *cmd;
1022 gchar *filename = NULL;
1023
1024 player->uri = g_strdup(uri);
1025 player->video_width = 0;
1026 player->video_height = 0;
1027 player->length = 0;
1028
1029 if (player->player_state == PLAYER_STATE_RUNNING) {
1030 if (player->uri != NULL) {
1031 filename = g_filename_from_uri(player->uri, NULL, NULL);
1032 }
1033 cmd = g_strdup_printf("loadfile \"%s\" 0\n", filename);
1034 write_to_mplayer(player, cmd);
1035 g_free(cmd);
1036 if (filename != NULL) {
1037 g_free(filename);
1038 filename = NULL;
1039 }
1040 if (player->media_state == MEDIA_STATE_STOP) {
1041 gmtk_media_player_set_state(player, MEDIA_STATE_PLAY);
1042 }
1043 }
1044
1045 }
1046
gmtk_media_player_get_uri(GmtkMediaPlayer * player)1047 const gchar *gmtk_media_player_get_uri(GmtkMediaPlayer * player)
1048 {
1049 return player->uri;
1050 }
1051
gmtk_media_player_set_state(GmtkMediaPlayer * player,const GmtkMediaPlayerMediaState new_media_state)1052 void gmtk_media_player_set_state(GmtkMediaPlayer * player, const GmtkMediaPlayerMediaState new_media_state)
1053 {
1054 gmtk_media_player_log_state(player, "old");
1055 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "setting media state to %s", gmtk_media_state_to_string(new_media_state));
1056
1057 if (player->player_state == PLAYER_STATE_DEAD) {
1058
1059 if (new_media_state == MEDIA_STATE_QUIT) {
1060 player->media_state = MEDIA_STATE_UNKNOWN;
1061 }
1062
1063 if (new_media_state == MEDIA_STATE_STOP) {
1064 player->media_state = MEDIA_STATE_UNKNOWN;
1065 }
1066
1067 if (new_media_state == MEDIA_STATE_PAUSE) {
1068 player->media_state = MEDIA_STATE_UNKNOWN;
1069 }
1070
1071 if (new_media_state == MEDIA_STATE_PLAY) {
1072 // launch player
1073 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "launching launch_mplayer thread");
1074 player->mplayer_thread = g_thread_create(launch_mplayer, player, TRUE, NULL);
1075 if (player->mplayer_thread != NULL) {
1076 if (player->message != NULL) {
1077 g_free(player->message);
1078 player->message = NULL;
1079 }
1080 player->message = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Loading..."));
1081 if (!player->restart)
1082 g_signal_emit_by_name(player, "attribute-changed", ATTRIBUTE_MESSAGE);
1083 player->player_state = PLAYER_STATE_RUNNING;
1084 if (!player->restart)
1085 g_signal_emit_by_name(player, "player-state-changed", player->player_state);
1086 gmtk_media_player_log_state(player, "new");
1087 return;
1088 }
1089 }
1090
1091 }
1092
1093 if (player->player_state == PLAYER_STATE_RUNNING) {
1094 if (new_media_state == MEDIA_STATE_STOP) {
1095 if (player->type == TYPE_NETWORK) {
1096 write_to_mplayer(player, "quit\n");
1097 } else {
1098 write_to_mplayer(player, "seek 0 2\n");
1099 if (player->media_state == MEDIA_STATE_PLAY) {
1100 write_to_mplayer(player, "pause\n");
1101 }
1102 player->media_state = MEDIA_STATE_STOP;
1103 g_signal_emit_by_name(player, "position-changed", 0.0);
1104 if (!player->restart)
1105 g_signal_emit_by_name(player, "media-state-changed", player->media_state);
1106 }
1107 }
1108
1109 if (new_media_state == MEDIA_STATE_PLAY) {
1110 gtk_widget_show(GTK_WIDGET(player->socket));
1111
1112 if (player->media_state == MEDIA_STATE_PAUSE || player->media_state == MEDIA_STATE_STOP) {
1113 write_to_mplayer(player, "pause\n");
1114 player->media_state = MEDIA_STATE_PLAY;
1115 if (!player->restart)
1116 g_signal_emit_by_name(player, "media-state-changed", player->media_state);
1117 }
1118 if (player->media_state == MEDIA_STATE_UNKNOWN) {
1119 player->media_state = MEDIA_STATE_PLAY;
1120 if (!player->restart)
1121 g_signal_emit_by_name(player, "media-state-changed", player->media_state);
1122 }
1123 }
1124
1125 if (new_media_state == MEDIA_STATE_PAUSE) {
1126 if (player->media_state == MEDIA_STATE_PLAY) {
1127 write_to_mplayer(player, "pause\n");
1128 player->media_state = MEDIA_STATE_PAUSE;
1129 if (!player->restart)
1130 g_signal_emit_by_name(player, "media-state-changed", player->media_state);
1131 }
1132 }
1133
1134 if (new_media_state == MEDIA_STATE_QUIT) {
1135 write_to_mplayer(player, "quit\n");
1136 }
1137 }
1138
1139 gmtk_media_player_log_state(player, "new");
1140 }
1141
gmtk_media_player_get_media_state(GmtkMediaPlayer * player)1142 GmtkMediaPlayerMediaState gmtk_media_player_get_media_state(GmtkMediaPlayer * player)
1143 {
1144 return player->media_state;
1145 }
1146
gmtk_media_player_send_command(GmtkMediaPlayer * player,GmtkMediaPlayerCommand command)1147 void gmtk_media_player_send_command(GmtkMediaPlayer * player, GmtkMediaPlayerCommand command)
1148 {
1149 gchar *cmd = NULL;
1150
1151 if (player->player_state == PLAYER_STATE_RUNNING) {
1152 switch (command) {
1153 case COMMAND_SHOW_DVD_MENU:
1154 write_to_mplayer(player, "dvdnav 5\n");
1155 break;
1156
1157 case COMMAND_TAKE_SCREENSHOT:
1158 write_to_mplayer(player, "screenshot 0\n");
1159 break;
1160
1161 case COMMAND_SWITCH_ANGLE:
1162 write_to_mplayer(player, "switch_angle\n");
1163 break;
1164
1165 case COMMAND_SWITCH_AUDIO:
1166 write_to_mplayer(player, "switch_audio\n");
1167 break;
1168
1169 case COMMAND_FRAME_STEP:
1170 if (player->media_state == MEDIA_STATE_PAUSE)
1171 write_to_mplayer(player, "frame_step\n");
1172 break;
1173
1174 case COMMAND_SUBTITLE_SELECT:
1175 gmtk_media_player_cycle_subtitles(player);
1176 break;
1177
1178 case COMMAND_SUBTITLE_STEP_FORWARD:
1179 write_to_mplayer(player, "sub_step 1\n");
1180 break;
1181
1182 case COMMAND_SUBTITLE_STEP_BACKWARD:
1183 write_to_mplayer(player, "sub_step -1\n");
1184 break;
1185
1186 case COMMAND_SWITCH_FRAME_DROP:
1187 write_to_mplayer(player, "frame_drop\n");
1188 cmd =
1189 g_strdup_printf("osd_show_property_text \"%s ${framedropping}\" 1000 1\n",
1190 g_dgettext(GETTEXT_PACKAGE, "Frame Dropping"));
1191 write_to_mplayer(player, cmd);
1192 g_free(cmd);
1193 cmd = NULL;
1194 break;
1195
1196 default:
1197 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unknown command");
1198 }
1199 }
1200 }
1201
gmtk_media_player_set_attribute_boolean(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute,gboolean value)1202 void gmtk_media_player_set_attribute_boolean(GmtkMediaPlayer * player,
1203 GmtkMediaPlayerMediaAttributes attribute, gboolean value)
1204 {
1205 gchar *cmd = NULL;
1206
1207 switch (attribute) {
1208 case ATTRIBUTE_SUB_VISIBLE:
1209 player->sub_visible = value;
1210 if (player->player_state == PLAYER_STATE_RUNNING) {
1211 cmd = g_strdup_printf("set_property sub_visibility %i\n", value);
1212 write_to_mplayer(player, cmd);
1213 g_free(cmd);
1214 cmd = NULL;
1215 if (value) {
1216 cmd =
1217 g_strdup_printf("osd_show_property_text \"%s\" 1000 1\n",
1218 g_dgettext(GETTEXT_PACKAGE, "Subtitles Visible"));
1219 } else {
1220 cmd =
1221 g_strdup_printf("osd_show_property_text \"%s\" 1000 1\n",
1222 g_dgettext(GETTEXT_PACKAGE, "Subtitles Hidden"));
1223 }
1224 write_to_mplayer(player, cmd);
1225 g_free(cmd);
1226 cmd = NULL;
1227 }
1228 break;
1229
1230 case ATTRIBUTE_ENABLE_FRAME_DROP:
1231 player->frame_drop = value;
1232 if (player->player_state == PLAYER_STATE_RUNNING) {
1233 cmd = g_strdup_printf("frame_drop %i\n", value);
1234 write_to_mplayer(player, cmd);
1235 g_free(cmd);
1236 cmd = NULL;
1237 }
1238 break;
1239
1240 case ATTRIBUTE_PLAYLIST:
1241 player->playlist = value;
1242 break;
1243
1244 case ATTRIBUTE_DISABLE_UPSCALING:
1245 player->disable_upscaling = value;
1246 break;
1247
1248 case ATTRIBUTE_SOFTVOL:
1249 player->softvol = value;
1250 break;
1251
1252 case ATTRIBUTE_MUTED:
1253 player->muted = value;
1254 if (player->player_state == PLAYER_STATE_RUNNING) {
1255 cmd = g_strdup_printf("mute %i\n", value);
1256 write_to_mplayer(player, cmd);
1257 g_free(cmd);
1258 cmd = NULL;
1259 }
1260 break;
1261
1262 case ATTRIBUTE_ENABLE_ADVANCED_SUBTITLES:
1263 player->enable_advanced_subtitles = value;
1264 break;
1265
1266 case ATTRIBUTE_ENABLE_EMBEDDED_FONTS:
1267 player->enable_embedded_fonts = value;
1268 break;
1269
1270 case ATTRIBUTE_SUBTITLE_OUTLINE:
1271 player->subtitle_outline = value;
1272 break;
1273
1274 case ATTRIBUTE_SUBTITLE_SHADOW:
1275 player->subtitle_shadow = value;
1276 break;
1277
1278 case ATTRIBUTE_DEINTERLACE:
1279 player->deinterlace = value;
1280 break;
1281
1282 case ATTRIBUTE_ENABLE_DEBUG:
1283 player->debug = value;
1284 break;
1285
1286 case ATTRIBUTE_HARDWARE_AC3:
1287 player->hardware_ac3 = value;
1288 break;
1289
1290 case ATTRIBUTE_ENABLE_HARDWARE_CODECS:
1291 player->enable_hardware_codecs = value;
1292 break;
1293
1294 case ATTRIBUTE_ENABLE_CRYSTALHD_CODECS:
1295 player->enable_crystalhd_codecs = value;
1296 break;
1297
1298 case ATTRIBUTE_FORCE_CACHE:
1299 player->force_cache = value;
1300 break;
1301
1302 default:
1303 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unsupported Attribute");
1304 }
1305
1306 return;
1307 }
1308
gmtk_media_player_get_attribute_boolean(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute)1309 gboolean gmtk_media_player_get_attribute_boolean(GmtkMediaPlayer * player, GmtkMediaPlayerMediaAttributes attribute)
1310 {
1311 gboolean ret = FALSE;
1312
1313 switch (attribute) {
1314 case ATTRIBUTE_SUB_VISIBLE:
1315 ret = player->sub_visible;
1316 break;
1317
1318 case ATTRIBUTE_ENABLE_FRAME_DROP:
1319 ret = player->frame_drop;
1320 break;
1321
1322 case ATTRIBUTE_SUBS_EXIST:
1323 ret = g_list_length(player->subtitles);
1324 break;
1325
1326 case ATTRIBUTE_SOFTVOL:
1327 ret = player->softvol;
1328 break;
1329
1330 case ATTRIBUTE_PLAYLIST:
1331 ret = player->playlist;
1332 break;
1333
1334 case ATTRIBUTE_SEEKABLE:
1335 ret = player->seekable;
1336 break;
1337
1338 case ATTRIBUTE_HAS_CHAPTERS:
1339 ret = player->has_chapters;
1340 break;
1341
1342 case ATTRIBUTE_TITLE_IS_MENU:
1343 ret = player->title_is_menu;
1344 break;
1345
1346 case ATTRIBUTE_DISABLE_UPSCALING:
1347 ret = player->disable_upscaling;
1348 break;
1349
1350 case ATTRIBUTE_VIDEO_PRESENT:
1351 ret = player->video_present;
1352 break;
1353
1354 case ATTRIBUTE_MUTED:
1355 ret = player->muted;
1356 break;
1357
1358 case ATTRIBUTE_ENABLE_ADVANCED_SUBTITLES:
1359 ret = player->enable_advanced_subtitles;
1360 break;
1361
1362 case ATTRIBUTE_ENABLE_EMBEDDED_FONTS:
1363 ret = player->enable_embedded_fonts;
1364 break;
1365
1366 case ATTRIBUTE_SUBTITLE_OUTLINE:
1367 ret = player->subtitle_outline;
1368 break;
1369
1370 case ATTRIBUTE_SUBTITLE_SHADOW:
1371 ret = player->subtitle_shadow;
1372 break;
1373
1374 case ATTRIBUTE_DEINTERLACE:
1375 ret = player->deinterlace;
1376 break;
1377
1378 case ATTRIBUTE_ENABLE_DEBUG:
1379 ret = player->debug;
1380 break;
1381
1382 case ATTRIBUTE_HARDWARE_AC3:
1383 ret = player->hardware_ac3;
1384 break;
1385
1386 case ATTRIBUTE_RETRY_ON_FULL_CACHE:
1387 ret = player->retry_on_full_cache;
1388 break;
1389
1390 case ATTRIBUTE_ENABLE_HARDWARE_CODECS:
1391 ret = player->enable_hardware_codecs;
1392 break;
1393
1394 case ATTRIBUTE_ENABLE_CRYSTALHD_CODECS:
1395 ret = player->enable_crystalhd_codecs;
1396 break;
1397
1398 case ATTRIBUTE_FORCE_CACHE:
1399 ret = player->force_cache;
1400 break;
1401
1402 default:
1403 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unsupported Attribute");
1404 }
1405 return ret;
1406 }
1407
gmtk_media_player_set_attribute_double(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute,gdouble value)1408 void gmtk_media_player_set_attribute_double(GmtkMediaPlayer * player,
1409 GmtkMediaPlayerMediaAttributes attribute, gdouble value)
1410 {
1411 gchar *cmd;
1412 gchar *tmp;
1413
1414 switch (attribute) {
1415 case ATTRIBUTE_CACHE_SIZE:
1416 player->cache_size = value;
1417 break;
1418
1419 case ATTRIBUTE_START_TIME:
1420 player->start_time = value;
1421 break;
1422
1423 case ATTRIBUTE_RUN_TIME:
1424 player->run_time = value;
1425 break;
1426
1427 case ATTRIBUTE_ZOOM:
1428 player->zoom = CLAMP(value, 0.1, 10.0);
1429 break;
1430
1431 case ATTRIBUTE_VOLUME_GAIN:
1432 player->volume_gain = CLAMP(value, -200.0, 60.0);
1433 break;
1434
1435 case ATTRIBUTE_SPEED_MULTIPLIER:
1436 player->speed_multiplier = CLAMP(value, 0.1, 10.0);
1437 if (player->player_state == PLAYER_STATE_RUNNING) {
1438 if (player->speed_multiplier == 1.0) {
1439 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
1440 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->speed_multiplier);
1441 cmd = g_strdup_printf("speed_set %s\n", tmp);
1442 g_free(tmp);
1443
1444 } else {
1445 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
1446 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->speed_multiplier);
1447 cmd = g_strdup_printf("speed_mult %s\n", tmp);
1448 g_free(tmp);
1449 }
1450 write_to_mplayer(player, cmd);
1451 g_free(cmd);
1452 cmd = NULL;
1453 write_to_mplayer(player, "get_property speed\n");
1454 }
1455 break;
1456
1457 case ATTRIBUTE_SPEED_SET:
1458 player->speed = CLAMP(value, 0.1, 10.0);
1459 if (player->player_state == PLAYER_STATE_RUNNING) {
1460 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
1461 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->speed);
1462 cmd = g_strdup_printf("speed_set %s\n", tmp);
1463 g_free(tmp);
1464 write_to_mplayer(player, cmd);
1465 g_free(cmd);
1466 cmd = NULL;
1467 write_to_mplayer(player, "get_property speed\n");
1468 }
1469 break;
1470
1471 case ATTRIBUTE_SUBTITLE_SCALE:
1472 player->subtitle_scale = CLAMP(value, 0.2, 100.0);
1473 if (player->player_state == PLAYER_STATE_RUNNING) {
1474 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
1475 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->subtitle_scale);
1476 cmd = g_strdup_printf("sub_scale %s\n", tmp);
1477 g_free(tmp);
1478
1479 write_to_mplayer(player, cmd);
1480 g_free(cmd);
1481 cmd = NULL;
1482 }
1483 break;
1484
1485 case ATTRIBUTE_SUBTITLE_DELAY:
1486 player->subtitle_delay = value;
1487 if (player->player_state == PLAYER_STATE_RUNNING) {
1488 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
1489 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->subtitle_delay);
1490 cmd = g_strdup_printf("set_property sub_delay %s\n", tmp);
1491 g_free(tmp);
1492 write_to_mplayer(player, cmd);
1493 g_free(cmd);
1494 cmd = NULL;
1495 }
1496 break;
1497
1498 case ATTRIBUTE_AUDIO_DELAY:
1499 player->audio_delay = CLAMP(value, -100.0, 100.0);
1500 if (player->player_state == PLAYER_STATE_RUNNING) {
1501 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
1502 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->audio_delay);
1503 cmd = g_strdup_printf("set_property audio_delay %s\n", tmp);
1504 g_free(tmp);
1505 write_to_mplayer(player, cmd);
1506 g_free(cmd);
1507 cmd = NULL;
1508 }
1509 break;
1510
1511 default:
1512 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unsupported Attribute");
1513 }
1514
1515 return;
1516 }
1517
gmtk_media_player_get_attribute_double(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute)1518 gdouble gmtk_media_player_get_attribute_double(GmtkMediaPlayer * player, GmtkMediaPlayerMediaAttributes attribute)
1519 {
1520 gdouble ret = 0.0;
1521
1522 switch (attribute) {
1523 case ATTRIBUTE_LENGTH:
1524 ret = player->length;
1525 break;
1526
1527 case ATTRIBUTE_POSITION:
1528 ret = player->position;
1529 break;
1530
1531 case ATTRIBUTE_POSITION_PERCENT:
1532 if (player->length != 0) {
1533 ret = (player->position - player->start_time) / player->length;
1534 } else {
1535 ret = 0.0;
1536 }
1537 break;
1538
1539 case ATTRIBUTE_START_TIME:
1540 ret = player->start_time;
1541 break;
1542
1543 case ATTRIBUTE_WIDTH:
1544 ret = (gdouble) player->video_width;
1545 break;
1546
1547 case ATTRIBUTE_HEIGHT:
1548 ret = (gdouble) player->video_height;
1549 break;
1550
1551 case ATTRIBUTE_SUB_COUNT:
1552 ret = (gdouble) g_list_length(player->subtitles);
1553 break;
1554
1555 case ATTRIBUTE_AUDIO_TRACK_COUNT:
1556 ret = (gdouble) g_list_length(player->audio_tracks);
1557 break;
1558
1559 case ATTRIBUTE_ZOOM:
1560 ret = player->zoom;
1561 break;
1562
1563 case ATTRIBUTE_SPEED_MULTIPLIER:
1564 ret = player->speed_multiplier;
1565 break;
1566
1567 case ATTRIBUTE_SPEED_SET:
1568 ret = player->speed;
1569 break;
1570
1571 case ATTRIBUTE_SUBTITLE_SCALE:
1572 ret = player->subtitle_scale;
1573 break;
1574
1575 case ATTRIBUTE_SUBTITLE_DELAY:
1576 ret = player->subtitle_delay;
1577 break;
1578
1579 case ATTRIBUTE_AUDIO_DELAY:
1580 ret = player->audio_delay;
1581 break;
1582
1583 case ATTRIBUTE_VIDEO_FPS:
1584 ret = player->video_fps;
1585 break;
1586
1587 case ATTRIBUTE_VOLUME_GAIN:
1588 ret = player->volume_gain;
1589 break;
1590
1591 case ATTRIBUTE_CACHE_PERCENT:
1592 ret = player->cache_percent;
1593 break;
1594
1595 default:
1596 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unsupported Attribute");
1597 }
1598 return ret;
1599 }
1600
gmtk_media_player_set_attribute_string(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute,const gchar * value)1601 void gmtk_media_player_set_attribute_string(GmtkMediaPlayer * player,
1602 GmtkMediaPlayerMediaAttributes attribute, const gchar * value)
1603 {
1604 gchar *cmd;
1605
1606 switch (attribute) {
1607 case ATTRIBUTE_VO:
1608 if (player->vo != NULL) {
1609 g_free(player->vo);
1610 player->vo = NULL;
1611 }
1612 if (value == NULL || strlen(value) == 0) {
1613 player->vo = NULL;
1614 } else {
1615 player->vo = g_strdup(value);
1616 }
1617 break;
1618
1619 case ATTRIBUTE_AO:
1620 if (player->ao != NULL) {
1621 g_free(player->ao);
1622 player->ao = NULL;
1623 }
1624 if (value == NULL || strlen(value) == 0) {
1625 player->ao = NULL;
1626 } else {
1627 player->ao = g_strdup(value);
1628 }
1629 break;
1630
1631 case ATTRIBUTE_MEDIA_DEVICE:
1632 if (player->media_device != NULL) {
1633 g_free(player->media_device);
1634 player->media_device = NULL;
1635 }
1636 if (value == NULL || strlen(value) == 0) {
1637 player->media_device = NULL;
1638 } else {
1639 player->media_device = g_strdup(value);
1640 }
1641 break;
1642
1643 case ATTRIBUTE_EXTRA_OPTS:
1644 if (player->extra_opts != NULL) {
1645 g_free(player->extra_opts);
1646 player->extra_opts = NULL;
1647 }
1648 if (value == NULL || strlen(value) == 0) {
1649 player->extra_opts = NULL;
1650 } else {
1651 player->extra_opts = g_strdup(value);
1652 }
1653 break;
1654
1655 case ATTRIBUTE_MPLAYER_BINARY:
1656 if (player->mplayer_binary != NULL) {
1657 g_free(player->mplayer_binary);
1658 player->mplayer_binary = NULL;
1659 }
1660 if (value == NULL || strlen(value) == 0) {
1661 player->mplayer_binary = NULL;
1662 } else {
1663 player->mplayer_binary = g_strdup(value);
1664 }
1665 player->features_detected = FALSE;
1666 break;
1667
1668 case ATTRIBUTE_AUDIO_TRACK_FILE:
1669 if (player->audio_track_file != NULL) {
1670 g_free(player->audio_track_file);
1671 player->audio_track_file = NULL;
1672 }
1673 if (value == NULL || strlen(value) == 0) {
1674 player->audio_track_file = NULL;
1675 } else {
1676 player->audio_track_file = g_strdup(value);
1677 }
1678 break;
1679
1680 case ATTRIBUTE_SUBTITLE_FILE:
1681 if (player->subtitle_file != NULL) {
1682 g_free(player->subtitle_file);
1683 }
1684 if (value == NULL || strlen(value) == 0) {
1685 player->subtitle_file = NULL;
1686 } else {
1687 player->subtitle_file = g_strdup(value);
1688 if (player->player_state == PLAYER_STATE_RUNNING) {
1689 write_to_mplayer(player, "sub_remove\n");
1690 cmd = g_strdup_printf("sub_load \"%s\" 1\n", player->subtitle_file);
1691 write_to_mplayer(player, cmd);
1692 g_free(cmd);
1693 cmd = g_strdup_printf("sub_file 0\n");
1694 write_to_mplayer(player, cmd);
1695 g_free(cmd);
1696 }
1697 }
1698 break;
1699
1700 case ATTRIBUTE_SUBTITLE_COLOR:
1701 if (player->subtitle_color != NULL) {
1702 g_free(player->subtitle_color);
1703 }
1704 if (value == NULL || strlen(value) == 0) {
1705 player->subtitle_color = NULL;
1706 } else {
1707 player->subtitle_color = g_strdup(value);
1708 }
1709 break;
1710
1711 case ATTRIBUTE_SUBTITLE_CODEPAGE:
1712 if (player->subtitle_codepage != NULL) {
1713 g_free(player->subtitle_codepage);
1714 }
1715 if (value == NULL || strlen(value) == 0) {
1716 player->subtitle_codepage = NULL;
1717 } else {
1718 player->subtitle_codepage = g_strdup(value);
1719 }
1720 break;
1721
1722 case ATTRIBUTE_SUBTITLE_FONT:
1723 if (player->subtitle_font != NULL) {
1724 g_free(player->subtitle_font);
1725 }
1726 if (value == NULL || strlen(value) == 0) {
1727 player->subtitle_font = NULL;
1728 } else {
1729 player->subtitle_font = g_strdup(value);
1730 }
1731 break;
1732
1733 case ATTRIBUTE_PROFILE:
1734 if (player->profile != NULL) {
1735 g_free(player->profile);
1736 }
1737 if (value == NULL || strlen(value) == 0) {
1738 player->profile = NULL;
1739 } else {
1740 player->profile = g_strdup(value);
1741 }
1742 break;
1743
1744 case ATTRIBUTE_PREFERRED_AUDIO_LANGUAGE:
1745 if (player->alang != NULL) {
1746 g_free(player->alang);
1747 }
1748 if (value == NULL || strlen(value) == 0) {
1749 player->alang = NULL;
1750 } else {
1751 player->alang = g_strdup(value);
1752 }
1753 break;
1754
1755 case ATTRIBUTE_PREFERRED_SUBTITLE_LANGUAGE:
1756 if (player->slang != NULL) {
1757 g_free(player->slang);
1758 }
1759 if (value == NULL || strlen(value) == 0) {
1760 player->slang = NULL;
1761 } else {
1762 player->slang = g_strdup(value);
1763 }
1764 break;
1765
1766 default:
1767 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unsupported Attribute");
1768 }
1769 }
1770
gmtk_media_player_get_attribute_string(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute)1771 const gchar *gmtk_media_player_get_attribute_string(GmtkMediaPlayer * player, GmtkMediaPlayerMediaAttributes attribute)
1772 {
1773 gchar *value = NULL;
1774 GList *iter;
1775 GmtkMediaPlayerAudioTrack *track;
1776 GmtkMediaPlayerSubtitle *subtitle;
1777
1778 switch (attribute) {
1779 case ATTRIBUTE_AF_EXPORT_FILENAME:
1780 value = player->af_export_filename;
1781 break;
1782
1783 case ATTRIBUTE_MEDIA_DEVICE:
1784 value = player->media_device;
1785 break;
1786
1787 case ATTRIBUTE_EXTRA_OPTS:
1788 value = player->extra_opts;
1789 break;
1790
1791 case ATTRIBUTE_MESSAGE:
1792 value = player->message;
1793 break;
1794
1795 case ATTRIBUTE_AUDIO_TRACK:
1796 iter = player->audio_tracks;
1797 while (iter) {
1798 track = (GmtkMediaPlayerAudioTrack *) iter->data;
1799 if (track->id == player->audio_track_id)
1800 value = track->label;
1801 iter = iter->next;
1802 }
1803 break;
1804
1805 case ATTRIBUTE_SUBTITLE:
1806 iter = player->subtitles;
1807 while (iter) {
1808 subtitle = (GmtkMediaPlayerSubtitle *) iter->data;
1809 if (subtitle->id == player->subtitle_id && subtitle->is_file == player->subtitle_is_file)
1810 value = subtitle->label;
1811 iter = iter->next;
1812 }
1813 break;
1814
1815 case ATTRIBUTE_SUBTITLE_COLOR:
1816 value = player->subtitle_color;
1817 break;
1818
1819 case ATTRIBUTE_SUBTITLE_CODEPAGE:
1820 value = player->subtitle_codepage;
1821 break;
1822
1823 case ATTRIBUTE_SUBTITLE_FONT:
1824 value = player->subtitle_font;
1825 break;
1826
1827 case ATTRIBUTE_VIDEO_FORMAT:
1828 value = player->video_format;
1829 break;
1830
1831 case ATTRIBUTE_VIDEO_CODEC:
1832 value = player->video_codec;
1833 break;
1834
1835 case ATTRIBUTE_AUDIO_FORMAT:
1836 value = player->audio_format;
1837 break;
1838
1839 case ATTRIBUTE_AUDIO_CODEC:
1840 value = player->audio_codec;
1841 break;
1842
1843 case ATTRIBUTE_ARTIST:
1844 if (player->artist == NULL || strlen(player->artist) == 0) {
1845 value = NULL;
1846 } else {
1847 value = player->artist;
1848 }
1849 break;
1850
1851 case ATTRIBUTE_TITLE:
1852 if (player->title == NULL || strlen(player->title) == 0) {
1853 value = NULL;
1854 } else {
1855 value = player->title;
1856 }
1857 break;
1858
1859 case ATTRIBUTE_ALBUM:
1860 if (player->album == NULL || strlen(player->album) == 0) {
1861 value = NULL;
1862 } else {
1863 value = player->album;
1864 }
1865 break;
1866
1867 case ATTRIBUTE_GENRE:
1868 if (player->genre == NULL || strlen(player->genre) == 0) {
1869 value = NULL;
1870 } else {
1871 value = player->genre;
1872 }
1873 break;
1874
1875 case ATTRIBUTE_PROFILE:
1876 value = player->profile;
1877 break;
1878
1879 default:
1880 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unsupported Attribute");
1881 }
1882
1883 return value;
1884 }
1885
gmtk_media_player_set_attribute_integer(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute,gint value)1886 void gmtk_media_player_set_attribute_integer(GmtkMediaPlayer * player, GmtkMediaPlayerMediaAttributes attribute,
1887 gint value)
1888 {
1889 gchar *cmd = NULL;
1890
1891 switch (attribute) {
1892 case ATTRIBUTE_BRIGHTNESS:
1893 player->brightness = CLAMP(value, -100.0, 100.0);
1894 if (player->player_state == PLAYER_STATE_RUNNING) {
1895 cmd = g_strdup_printf("set_property brightness %i\n", value);
1896 write_to_mplayer(player, cmd);
1897 g_free(cmd);
1898 }
1899 break;
1900
1901 case ATTRIBUTE_CONTRAST:
1902 player->contrast = CLAMP(value, -100.0, 100.0);
1903 if (player->player_state == PLAYER_STATE_RUNNING) {
1904 cmd = g_strdup_printf("set_property contrast %i\n", value);
1905 write_to_mplayer(player, cmd);
1906 g_free(cmd);
1907 }
1908 break;
1909
1910 case ATTRIBUTE_GAMMA:
1911 player->gamma = CLAMP(value, -100.0, 100.0);
1912 if (player->player_state == PLAYER_STATE_RUNNING) {
1913 cmd = g_strdup_printf("set_property gamma %i\n", value);
1914 write_to_mplayer(player, cmd);
1915 g_free(cmd);
1916 }
1917 break;
1918
1919 case ATTRIBUTE_HUE:
1920 player->hue = CLAMP(value, -100.0, 100.0);
1921 if (player->player_state == PLAYER_STATE_RUNNING) {
1922 cmd = g_strdup_printf("set_property hue %i\n", value);
1923 write_to_mplayer(player, cmd);
1924 g_free(cmd);
1925 }
1926 break;
1927
1928 case ATTRIBUTE_SATURATION:
1929 player->saturation = CLAMP(value, -100.0, 100.0);
1930 if (player->player_state == PLAYER_STATE_RUNNING) {
1931 cmd = g_strdup_printf("set_property saturation %i\n", value);
1932 write_to_mplayer(player, cmd);
1933 g_free(cmd);
1934 }
1935 break;
1936
1937 case ATTRIBUTE_SUBTITLE_MARGIN:
1938 player->subtitle_margin = CLAMP(value, 0.0, 200.0);
1939 break;
1940
1941 case ATTRIBUTE_SUBTITLE_POSITION:
1942 player->subtitle_position = CLAMP(value, 0, 100);
1943 if (player->player_state == PLAYER_STATE_RUNNING) {
1944 cmd = g_strdup_printf("set_property sub_pos %i\n", player->subtitle_position);
1945 write_to_mplayer(player, cmd);
1946 g_free(cmd);
1947 }
1948 break;
1949
1950 case ATTRIBUTE_OSDLEVEL:
1951 player->osdlevel = CLAMP(value, 0, 3);
1952 if (player->player_state == PLAYER_STATE_RUNNING) {
1953 cmd = g_strdup_printf("set_property osdlevel %i\n", player->osdlevel);
1954 write_to_mplayer(player, cmd);
1955 g_free(cmd);
1956 }
1957 break;
1958
1959 case ATTRIBUTE_POST_PROCESSING_LEVEL:
1960 player->post_processing_level = value;
1961 break;
1962
1963 case ATTRIBUTE_SUBTITLE_FUZZINESS:
1964 player->subtitle_fuzziness = CLAMP(value, 0, 2);
1965 break;
1966
1967 case ATTRIBUTE_AUDIO_CHANNELS:
1968 player->audio_channels = CLAMP(value, 0, 3);
1969 break;
1970
1971 default:
1972 gm_log(player->debug, G_LOG_LEVEL_INFO, "Unsupported Attribute");
1973 }
1974
1975 return;
1976
1977 }
1978
gmtk_media_player_set_attribute_integer_delta(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute,gint delta)1979 void gmtk_media_player_set_attribute_integer_delta(GmtkMediaPlayer * player, GmtkMediaPlayerMediaAttributes attribute,
1980 gint delta)
1981 {
1982 gint value;
1983
1984 switch (attribute) {
1985 case ATTRIBUTE_BRIGHTNESS:
1986 value = player->brightness + delta;
1987 break;
1988
1989 case ATTRIBUTE_CONTRAST:
1990 value = player->contrast + delta;
1991 break;
1992
1993 case ATTRIBUTE_GAMMA:
1994 value = player->gamma + delta;
1995 break;
1996
1997 case ATTRIBUTE_HUE:
1998 value = player->hue + delta;
1999 break;
2000
2001 case ATTRIBUTE_SATURATION:
2002 value = player->saturation + delta;
2003 break;
2004
2005 default:
2006 return;
2007 }
2008
2009 gmtk_media_player_set_attribute_integer(player, attribute, value);
2010
2011 }
2012
gmtk_media_player_get_attribute_integer(GmtkMediaPlayer * player,GmtkMediaPlayerMediaAttributes attribute)2013 gint gmtk_media_player_get_attribute_integer(GmtkMediaPlayer * player, GmtkMediaPlayerMediaAttributes attribute)
2014 {
2015 gint ret;
2016
2017 switch (attribute) {
2018 case ATTRIBUTE_BRIGHTNESS:
2019 ret = player->brightness;
2020 break;
2021
2022 case ATTRIBUTE_CONTRAST:
2023 ret = player->contrast;
2024 break;
2025
2026 case ATTRIBUTE_GAMMA:
2027 ret = player->gamma;
2028 break;
2029
2030 case ATTRIBUTE_HUE:
2031 ret = player->hue;
2032 break;
2033
2034 case ATTRIBUTE_SATURATION:
2035 ret = player->saturation;
2036 break;
2037
2038 case ATTRIBUTE_WIDTH:
2039 ret = player->video_width;
2040 break;
2041
2042 case ATTRIBUTE_HEIGHT:
2043 ret = player->video_height;
2044 break;
2045
2046 case ATTRIBUTE_SUBTITLE_MARGIN:
2047 ret = player->subtitle_margin;
2048 break;
2049
2050 case ATTRIBUTE_SUBTITLE_POSITION:
2051 ret = player->subtitle_position;
2052 break;
2053
2054 case ATTRIBUTE_CHAPTERS:
2055 ret = player->chapters;
2056 break;
2057
2058 case ATTRIBUTE_VIDEO_BITRATE:
2059 ret = player->video_bitrate;
2060 break;
2061
2062 case ATTRIBUTE_AUDIO_BITRATE:
2063 ret = player->audio_bitrate;
2064 break;
2065
2066 case ATTRIBUTE_AUDIO_RATE:
2067 ret = player->audio_rate;
2068 break;
2069
2070 case ATTRIBUTE_AUDIO_NCH:
2071 ret = player->audio_nch;
2072 break;
2073
2074 case ATTRIBUTE_OSDLEVEL:
2075 ret = player->osdlevel;
2076 break;
2077
2078 case ATTRIBUTE_POST_PROCESSING_LEVEL:
2079 ret = player->post_processing_level;
2080 break;
2081
2082 case ATTRIBUTE_SUBTITLE_FUZZINESS:
2083 ret = player->subtitle_fuzziness;
2084 break;
2085
2086 default:
2087 return 0;
2088 }
2089
2090 return ret;
2091 }
2092
2093
gmtk_media_player_seek(GmtkMediaPlayer * player,gdouble value,GmtkMediaPlayerSeekType seek_type)2094 void gmtk_media_player_seek(GmtkMediaPlayer * player, gdouble value, GmtkMediaPlayerSeekType seek_type)
2095 {
2096 gchar *cmd;
2097
2098 cmd = g_strdup_printf("seek %lf %i\n", value, seek_type);
2099 write_to_mplayer(player, cmd);
2100 g_free(cmd);
2101 }
2102
gmtk_media_player_seek_chapter(GmtkMediaPlayer * player,gint value,GmtkMediaPlayerSeekType seek_type)2103 void gmtk_media_player_seek_chapter(GmtkMediaPlayer * player, gint value, GmtkMediaPlayerSeekType seek_type)
2104 {
2105 gchar *cmd;
2106 if (seek_type != SEEK_RELATIVE)
2107 seek_type = 1;
2108
2109 cmd = g_strdup_printf("seek_chapter %i %i\n", value, seek_type);
2110 write_to_mplayer(player, cmd);
2111 g_free(cmd);
2112 }
2113
gmtk_media_player_set_volume(GmtkMediaPlayer * player,gdouble value)2114 void gmtk_media_player_set_volume(GmtkMediaPlayer * player, gdouble value)
2115 {
2116 gchar *cmd;
2117
2118 player->volume = value;
2119 if (player->player_state == PLAYER_STATE_RUNNING) {
2120 cmd = g_strdup_printf("volume %i 1\n", (gint) (player->volume * 100.0));
2121 write_to_mplayer(player, cmd);
2122 g_free(cmd);
2123 }
2124 }
2125
gmtk_media_player_get_volume(GmtkMediaPlayer * player)2126 gdouble gmtk_media_player_get_volume(GmtkMediaPlayer * player)
2127 {
2128 return player->volume;
2129 }
2130
gmtk_media_player_set_media_device(GmtkMediaPlayer * player,gchar * media_device)2131 void gmtk_media_player_set_media_device(GmtkMediaPlayer * player, gchar * media_device)
2132 {
2133 if (player->media_device != NULL) {
2134 g_free(player->media_device);
2135 }
2136 if (media_device == NULL) {
2137 player->media_device = NULL;
2138 } else {
2139 player->media_device = g_strdup(media_device);
2140 }
2141 }
2142
gmtk_media_player_set_aspect(GmtkMediaPlayer * player,GmtkMediaPlayerAspectRatio aspect)2143 void gmtk_media_player_set_aspect(GmtkMediaPlayer * player, GmtkMediaPlayerAspectRatio aspect)
2144 {
2145 GtkAllocation alloc;
2146
2147 player->aspect_ratio = aspect;
2148 gmtk_get_allocation(GTK_WIDGET(player), &alloc);
2149 gmtk_media_player_size_allocate(GTK_WIDGET(player), &alloc);
2150 }
2151
gmtk_media_player_get_aspect(GmtkMediaPlayer * player)2152 GmtkMediaPlayerAspectRatio gmtk_media_player_get_aspect(GmtkMediaPlayer * player)
2153 {
2154 return player->aspect_ratio;
2155 }
2156
gmtk_media_player_set_media_type(GmtkMediaPlayer * player,GmtkMediaPlayerMediaType type)2157 void gmtk_media_player_set_media_type(GmtkMediaPlayer * player, GmtkMediaPlayerMediaType type)
2158 {
2159 player->type = type;
2160 }
2161
gmtk_media_player_get_media_type(GmtkMediaPlayer * player)2162 GmtkMediaPlayerMediaType gmtk_media_player_get_media_type(GmtkMediaPlayer * player)
2163 {
2164 return player->type;
2165 }
2166
gmtk_media_player_select_subtitle(GmtkMediaPlayer * player,const gchar * label)2167 void gmtk_media_player_select_subtitle(GmtkMediaPlayer * player, const gchar * label)
2168 {
2169 GList *list;
2170 GmtkMediaPlayerSubtitle *subtitle;
2171 gchar *cmd;
2172
2173 list = player->subtitles;
2174 subtitle = NULL;
2175
2176 while (list != NULL) {
2177 subtitle = (GmtkMediaPlayerSubtitle *) list->data;
2178 if (g_ascii_strcasecmp(subtitle->label, label) == 0) {
2179 break;
2180 }
2181 list = list->next;
2182 }
2183
2184 if (list != NULL && subtitle != NULL && player->player_state == PLAYER_STATE_RUNNING) {
2185 if (subtitle->is_file) {
2186 cmd = g_strdup_printf("sub_file %i \n", subtitle->id);
2187 } else {
2188 cmd = g_strdup_printf("sub_demux %i \n", subtitle->id);
2189 }
2190 player->subtitle_id = subtitle->id;
2191 player->subtitle_is_file = subtitle->is_file;
2192 write_to_mplayer(player, cmd);
2193 g_free(cmd);
2194 }
2195 }
2196
gmtk_media_player_select_audio_track(GmtkMediaPlayer * player,const gchar * label)2197 void gmtk_media_player_select_audio_track(GmtkMediaPlayer * player, const gchar * label)
2198 {
2199 GList *list;
2200 GmtkMediaPlayerAudioTrack *track;
2201 gchar *cmd;
2202
2203 list = player->audio_tracks;
2204 track = NULL;
2205
2206 while (list != NULL) {
2207 track = (GmtkMediaPlayerAudioTrack *) list->data;
2208 if (g_ascii_strcasecmp(track->label, label) == 0) {
2209 break;
2210 }
2211 list = list->next;
2212 }
2213
2214 if (list != NULL && track != NULL && player->player_state == PLAYER_STATE_RUNNING) {
2215 cmd = g_strdup_printf("switch_audio %i \n", track->id);
2216 player->audio_track_id = track->id;
2217 write_to_mplayer(player, cmd);
2218 g_free(cmd);
2219 }
2220 }
2221
gmtk_media_player_select_subtitle_by_id(GmtkMediaPlayer * player,gint id)2222 void gmtk_media_player_select_subtitle_by_id(GmtkMediaPlayer * player, gint id)
2223 {
2224 GList *list;
2225 GmtkMediaPlayerSubtitle *subtitle;
2226 gchar *cmd;
2227
2228 list = player->subtitles;
2229 subtitle = NULL;
2230
2231 while (list != NULL) {
2232 subtitle = (GmtkMediaPlayerSubtitle *) list->data;
2233 if (subtitle->id == id) {
2234 break;
2235 }
2236 list = list->next;
2237 }
2238
2239 if (list != NULL && subtitle != NULL && player->player_state == PLAYER_STATE_RUNNING) {
2240 if (subtitle->is_file) {
2241 cmd = g_strdup_printf("sub_file %i \n", subtitle->id);
2242 } else {
2243 cmd = g_strdup_printf("sub_demux %i \n", subtitle->id);
2244 }
2245 player->subtitle_id = subtitle->id;
2246 player->subtitle_is_file = subtitle->is_file;
2247 write_to_mplayer(player, cmd);
2248 g_free(cmd);
2249 }
2250 }
2251
gmtk_media_player_select_audio_track_by_id(GmtkMediaPlayer * player,gint id)2252 void gmtk_media_player_select_audio_track_by_id(GmtkMediaPlayer * player, gint id)
2253 {
2254 GList *list;
2255 GmtkMediaPlayerAudioTrack *track;
2256 gchar *cmd;
2257
2258 list = player->audio_tracks;
2259 track = NULL;
2260
2261 while (list != NULL) {
2262 track = (GmtkMediaPlayerAudioTrack *) list->data;
2263 if (track->id == id) {
2264 break;
2265 }
2266 list = list->next;
2267 }
2268
2269 if (list != NULL && track != NULL && player->player_state == PLAYER_STATE_RUNNING) {
2270 cmd = g_strdup_printf("switch_audio %i \n", track->id);
2271 player->audio_track_id = track->id;
2272 write_to_mplayer(player, cmd);
2273 g_free(cmd);
2274 }
2275 }
2276
playback_error_to_string(const GmtkMediaPlayerPlaybackError playback_error)2277 static const gchar *playback_error_to_string(const GmtkMediaPlayerPlaybackError playback_error)
2278 {
2279 switch (playback_error) {
2280 case NO_ERROR:
2281 return "NO_ERROR";
2282 case ERROR_RETRY_WITH_PLAYLIST:
2283 return "RETRY_WITH_PLAYLIST";
2284 case ERROR_RETRY_WITH_HTTP:
2285 return "RETRY_WITH_HTTP";
2286 case ERROR_RETRY_WITH_HTTP_AND_PLAYLIST:
2287 return "RETRY_WITH_HTTP_AND_PLAYLIST";
2288 case ERROR_RETRY_WITH_MMSHTTP:
2289 return "RETRY_WITH_MMSHTTP";
2290 case ERROR_RETRY_WITHOUT_DIVX_VDPAU:
2291 return "RETRY_WITHOUT_DIVX_VDPAU";
2292 case ERROR_RETRY_WITHOUT_XVMC:
2293 return "RETRY_WITHOUT_XVMC";
2294 case ERROR_RETRY_ALSA_BUSY:
2295 return "RETRY_ALSA_BUSY";
2296 case ERROR_RETRY_VDPAU:
2297 return "RETRY_VDPAU";
2298 case ERROR_RETRY_WITHOUT_HARDWARE_CODECS:
2299 return "RETRY_WITHOUT_HARDWARE_CODECS";
2300 case ERROR_RETRY:
2301 return "RETRY";
2302 default:
2303 return "???";
2304 }
2305
2306 }
2307
2308 /* if it contains a deint=N leave as is, otherwise add deint=2
2309 returns newly-allocated string, passing ownership to caller */
vdpau_compute_vo_with_deint(GmtkMediaPlayer * player,gchar const * const vodesc)2310 static gchar *vdpau_compute_vo_with_deint(GmtkMediaPlayer * player, gchar const *const vodesc)
2311 {
2312 gchar *ret;
2313 if (g_regex_match(player->deintN_regex, vodesc, 0, NULL)) {
2314 ret = g_strdup(vodesc);
2315 } else {
2316 ret = g_strdup_printf("%s:deint=2", vodesc);
2317 }
2318 return ret;
2319 }
2320
2321 /* if it contains a deint=N remove that, otherwise leave as is
2322 returns newly-allocated string, passing ownership to caller */
vdpau_compute_vo_without_deint(GmtkMediaPlayer * player,gchar const * const vodesc)2323 static gchar *vdpau_compute_vo_without_deint(GmtkMediaPlayer * player, gchar const *const vodesc)
2324 {
2325 GMatchInfo *match_info = NULL;
2326 gchar *ret;
2327 if (g_regex_match(player->deintN_regex, vodesc, 0, &match_info)) {
2328 gchar *before = g_match_info_fetch(match_info, 1);
2329 gchar *after = g_match_info_fetch(match_info, 3);
2330 ret = g_strdup_printf("%s%s", before, after);
2331 g_free(before);
2332 g_free(after);
2333 } else {
2334 ret = g_strdup(vodesc);
2335 }
2336 g_match_info_free(match_info);
2337 return ret;
2338 }
2339
2340 /* replace the vo part with "gl_nosw"
2341 returns newly-allocated string, passing ownership to caller */
vodesc_replace_gl_with_gl_nosw(GmtkMediaPlayer * player,gchar const * const vodesc)2342 static gchar *vodesc_replace_gl_with_gl_nosw(GmtkMediaPlayer * player, gchar const *const vodesc)
2343 {
2344 /* find the first colon : and replace the part before that with gl_nosw */
2345 char *colonptr = strchr(vodesc, ':');
2346 gchar *ret;
2347 if (colonptr == NULL) {
2348 ret = g_strdup("gl_nosw");
2349 } else {
2350 ret = g_strdup_printf("gl_nosw%s", colonptr);
2351 }
2352 return ret;
2353 }
2354
launch_mplayer(gpointer data)2355 gpointer launch_mplayer(gpointer data)
2356 {
2357 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(data);
2358 gchar *argv[255];
2359 gchar *filename = NULL;
2360 gint argn;
2361 GPid pid;
2362 GError *error;
2363 gint i;
2364 gboolean spawn;
2365 gchar *fontname;
2366 gchar *size;
2367 gchar *tmp;
2368 GList *list;
2369 GmtkMediaPlayerSubtitle *subtitle;
2370 GmtkMediaPlayerAudioTrack *track;
2371 gchar *codecs_vdpau = NULL;
2372 gchar *codecs_crystalhd = NULL;
2373 gchar *codecs = NULL;
2374 GmtkMediaPlayerPlaybackError last_error = NO_ERROR;
2375 #ifdef GIO_ENABLED
2376 GFile *file;
2377 #endif
2378
2379 gm_log_name_this_thread("lm");
2380 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "within launch_mplayer()");
2381
2382 player->seekable = FALSE;
2383 player->has_chapters = FALSE;
2384 //player->video_present = FALSE;
2385 player->position = 0.0;
2386 player->cache_percent = -1.0;
2387 player->title_is_menu = FALSE;
2388 player->enable_divx = TRUE;
2389 player->disable_xvmc = FALSE;
2390 player->retry_on_full_cache = FALSE;
2391 player->speed = 1.0;
2392 player->hardware_ac3 = FALSE;
2393
2394 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "locking thread_running");
2395 g_mutex_lock(player->thread_running);
2396
2397 do {
2398 gm_log(player->debug, G_LOG_LEVEL_INFO, "setting up mplayer");
2399
2400 list = player->subtitles;
2401 while (list) {
2402 subtitle = (GmtkMediaPlayerSubtitle *) list->data;
2403 g_free(subtitle->lang);
2404 g_free(subtitle->name);
2405 g_free(subtitle->label);
2406 list = g_list_remove(list, subtitle);
2407 }
2408 player->subtitles = NULL;
2409
2410 list = player->audio_tracks;
2411 while (list) {
2412 track = (GmtkMediaPlayerAudioTrack *) list->data;
2413 g_free(track->lang);
2414 g_free(track->name);
2415 g_free(track->label);
2416 list = g_list_remove(list, track);
2417 }
2418 player->audio_tracks = NULL;
2419 player->has_metadata = FALSE;
2420 if (player->artist) {
2421 g_free(player->artist);
2422 player->artist = NULL;
2423 }
2424 if (player->title) {
2425 g_free(player->title);
2426 player->title = NULL;
2427 }
2428 if (player->album) {
2429 g_free(player->album);
2430 player->album = NULL;
2431 }
2432
2433 argn = 0;
2434 player->playback_error = NO_ERROR;
2435 if (player->uri != NULL) {
2436 #ifdef GIO_ENABLED
2437 file = g_file_new_for_uri(player->uri);
2438 if (file != NULL) {
2439 filename = g_file_get_path(file);
2440 g_object_unref(file);
2441 }
2442 #else
2443 filename = g_filename_from_uri(player->uri, NULL, NULL);
2444 #endif
2445 if (filename != NULL)
2446 player->type = TYPE_FILE;
2447 }
2448
2449 player->minimum_mplayer = detect_mplayer_features(player);
2450
2451 if (player->mplayer_binary == NULL || !g_file_test(player->mplayer_binary, G_FILE_TEST_EXISTS)) {
2452 argv[argn++] = g_strdup_printf("mplayer");
2453 } else {
2454 argv[argn++] = g_strdup_printf("%s", player->mplayer_binary);
2455 }
2456
2457 // use the profile to set up some default values
2458 if (player->profile != NULL) {
2459 argv[argn++] = g_strdup_printf("-profile");
2460 argv[argn++] = g_strdup(player->profile);
2461 }
2462
2463 if (player->vo != NULL) {
2464 argv[argn++] = g_strdup_printf("-vo");
2465
2466 if (vodesc_looks_like_vo(player->vo, "vdpau")) {
2467
2468 if (player->deinterlace) {
2469 /* if it contains a deint=N leave as is, otherwise add deint=2 */
2470 gchar *vo_with_deint = vdpau_compute_vo_with_deint(player, player->vo);
2471 argv[argn++] = g_strdup_printf("%s,gl,x11,", player->vo);
2472 g_free(vo_with_deint);
2473 } else {
2474 /* if it contains a deint=N remove that, otherwise leave as is */
2475 gchar *vo_without_deint = vdpau_compute_vo_without_deint(player, player->vo);
2476 argv[argn++] = g_strdup_printf("%s,gl,x11,", player->vo);
2477 g_free(vo_without_deint);
2478 }
2479
2480 // told by uau that vdpau without hardware decoding is often what you want
2481 if (player->enable_hardware_codecs) {
2482 if (player->enable_divx) {
2483 codecs_vdpau =
2484 g_strdup_printf("ffmpeg12vdpau,ffh264vdpau,ffwmv3vdpau,ffvc1vdpau,ffodivxvdpau,");
2485 } else {
2486 codecs_vdpau = g_strdup_printf("ffmpeg12vdpau,ffh264vdpau,ffwmv3vdpau,ffvc1vdpau,");
2487 }
2488 }
2489
2490 } else if (vodesc_looks_like_vo(player->vo, "vaapi")) {
2491 argv[argn++] = g_strdup_printf("%s,", player->vo);
2492 argv[argn++] = g_strdup_printf("-va");
2493 argv[argn++] = g_strdup_printf("vaapi");
2494
2495 } else if (vodesc_looks_like_vo(player->vo, "xvmc")) {
2496
2497 if (player->disable_xvmc) {
2498 argv[argn++] = g_strdup_printf("xv,");
2499 } else {
2500 argv[argn++] = g_strdup_printf("%s,xv,", player->vo);
2501 }
2502
2503 } else {
2504
2505 if (vodesc_looks_like_vo(player->vo, "gl") && player->enable_hardware_codecs) {
2506 gchar *vodesc = vodesc_replace_gl_with_gl_nosw(player, player->vo);
2507 argv[argn++] = vodesc;
2508 } else if (vodesc_looks_like_vo(player->vo, "gl2") && player->enable_hardware_codecs) {
2509 gchar *vodesc = vodesc_replace_gl_with_gl_nosw(player, player->vo);
2510 argv[argn++] = vodesc;
2511 } else {
2512 argv[argn++] = g_strdup_printf("%s", player->vo);
2513 if (vodesc_looks_like_vo(player->vo, "x11")) {
2514 argv[argn++] = g_strdup_printf("-zoom");
2515 }
2516 }
2517
2518 if (player->deinterlace) {
2519 argv[argn++] = g_strdup_printf("-vf-pre");
2520 argv[argn++] = g_strdup_printf("yadif,softskip,scale");
2521 }
2522
2523 if (player->post_processing_level > 0) {
2524 argv[argn++] = g_strdup_printf("-vf-add");
2525 argv[argn++] = g_strdup_printf("pp=ac/tn:a");
2526 argv[argn++] = g_strdup_printf("-autoq");
2527 argv[argn++] = g_strdup_printf("%d", player->post_processing_level);
2528 }
2529
2530 argv[argn++] = g_strdup_printf("-vf-add");
2531 argv[argn++] = g_strdup_printf("screenshot");
2532
2533 }
2534 }
2535
2536 if (player->enable_crystalhd_codecs) {
2537 codecs_crystalhd = g_strdup_printf
2538 ("ffmpeg2crystalhd,ffdivxcrystalhd,ffwmv3crystalhd,ffvc1crystalhd,ffh264crystalhd,ffodivxcrystalhd,");
2539 }
2540
2541 if (codecs_vdpau && codecs_crystalhd) {
2542 codecs = g_strconcat(codecs_vdpau, codecs_crystalhd, NULL);
2543 g_free(codecs_vdpau);
2544 g_free(codecs_crystalhd);
2545 codecs_vdpau = NULL;
2546 codecs_crystalhd = NULL;
2547 } else if (codecs_vdpau) {
2548 codecs = g_strdup(codecs_vdpau);
2549 g_free(codecs_vdpau);
2550 codecs_vdpau = NULL;
2551 } else if (codecs_crystalhd) {
2552 codecs = g_strdup(codecs_crystalhd);
2553 g_free(codecs_crystalhd);
2554 codecs_crystalhd = NULL;
2555 }
2556
2557 if (codecs != NULL) {
2558 argv[argn++] = g_strdup_printf("-vc");
2559 argv[argn++] = g_strdup_printf("%s", codecs);
2560 g_free(codecs);
2561 codecs = NULL;
2562 }
2563
2564 if (player->ao != NULL) {
2565
2566 argv[argn++] = g_strdup_printf("-ao");
2567 argv[argn++] = g_strdup_printf("%s", player->ao);
2568
2569 if (player->alsa_mixer != NULL) {
2570 argv[argn++] = g_strdup_printf("-mixer-channel");
2571 argv[argn++] = g_strdup_printf("%s", player->alsa_mixer);
2572 }
2573 }
2574
2575 argv[argn++] = g_strdup_printf("-channels");
2576 switch (player->audio_channels) {
2577 case 1:
2578 argv[argn++] = g_strdup_printf("4");
2579 break;
2580 case 2:
2581 argv[argn++] = g_strdup_printf("6");
2582 break;
2583 case 3:
2584 argv[argn++] = g_strdup_printf("8");
2585 break;
2586 default:
2587 argv[argn++] = g_strdup_printf("2");
2588 break;
2589 }
2590
2591 if (player->hardware_ac3) {
2592 argv[argn++] = g_strdup_printf("-afm");
2593 argv[argn++] = g_strdup_printf("hwac3,");
2594 } else {
2595 argv[argn++] = g_strdup_printf("-af-add");
2596 argv[argn++] = g_strdup_printf("export=%s:512", player->af_export_filename);
2597 }
2598
2599 argv[argn++] = g_strdup_printf("-quiet");
2600 argv[argn++] = g_strdup_printf("-slave");
2601 argv[argn++] = g_strdup_printf("-noidle");
2602 argv[argn++] = g_strdup_printf("-noconsolecontrols");
2603 argv[argn++] = g_strdup_printf("-nostop-xscreensaver");
2604 argv[argn++] = g_strdup_printf("-identify");
2605 if (player->softvol) {
2606 if ((gint) (player->volume * 100) != 0) {
2607 argv[argn++] = g_strdup_printf("-volume");
2608 argv[argn++] = g_strdup_printf("%i", (gint) (player->volume * 100));
2609 }
2610
2611 if ((gint) (player->volume_gain) != 0) {
2612 argv[argn++] = g_strdup_printf("-af-add");
2613 argv[argn++] = g_strdup_printf("volume=%lf:0", player->volume_gain);
2614 }
2615
2616 argv[argn++] = g_strdup_printf("-softvol");
2617 }
2618
2619 if ((gint) (player->start_time) > 0) {
2620 argv[argn++] = g_strdup_printf("-ss");
2621 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
2622 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->start_time);
2623 argv[argn++] = g_strdup(tmp);
2624 g_free(tmp);
2625 }
2626
2627 if ((gint) (player->run_time) > 0) {
2628 argv[argn++] = g_strdup_printf("-endpos");
2629 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
2630 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->run_time);
2631 argv[argn++] = g_strdup(tmp);
2632 g_free(tmp);
2633 }
2634
2635 if (player->frame_drop)
2636 argv[argn++] = g_strdup_printf("-framedrop");
2637
2638 argv[argn++] = g_strdup_printf("-msglevel");
2639 argv[argn++] = g_strdup_printf("all=5");
2640
2641 argv[argn++] = g_strdup_printf("-osdlevel");
2642 argv[argn++] = g_strdup_printf("%i", player->osdlevel);
2643
2644 argv[argn++] = g_strdup_printf("-delay");
2645 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
2646 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->audio_delay);
2647 argv[argn++] = g_strdup(tmp);
2648 g_free(tmp);
2649
2650 argv[argn++] = g_strdup_printf("-subdelay");
2651 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
2652 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->subtitle_delay);
2653 argv[argn++] = g_strdup(tmp);
2654 g_free(tmp);
2655
2656 argv[argn++] = g_strdup_printf("-subpos");
2657 argv[argn++] = g_strdup_printf("%i", player->subtitle_position);
2658
2659 argv[argn++] = g_strdup_printf("-sub-fuzziness");
2660 argv[argn++] = g_strdup_printf("%i", player->subtitle_fuzziness);
2661
2662 // wait upto 1 second for the socket_id to be valid, but in plugin mode it may not so timeout
2663 i = 0;
2664 while (player->socket_id == 0 && (i++ < 100)) {
2665 g_usleep(1000);
2666 }
2667
2668 argv[argn++] = g_strdup_printf("-wid");
2669 argv[argn++] = g_strdup_printf("0x%x", player->socket_id);
2670
2671 argv[argn++] = g_strdup_printf("-brightness");
2672 argv[argn++] = g_strdup_printf("%i", player->brightness);
2673 argv[argn++] = g_strdup_printf("-contrast");
2674 argv[argn++] = g_strdup_printf("%i", player->contrast);
2675 //argv[argn++] = g_strdup_printf("-gamma");
2676 //argv[argn++] = g_strdup_printf("%i", player->gamma);
2677 argv[argn++] = g_strdup_printf("-hue");
2678 argv[argn++] = g_strdup_printf("%i", player->hue);
2679 argv[argn++] = g_strdup_printf("-saturation");
2680 argv[argn++] = g_strdup_printf("%i", player->saturation);
2681
2682 if (player->alang) {
2683 argv[argn++] = g_strdup_printf("-alang");
2684 argv[argn++] = g_strdup_printf("%s", player->alang);
2685 }
2686
2687 if (player->slang) {
2688 argv[argn++] = g_strdup_printf("-slang");
2689 argv[argn++] = g_strdup_printf("%s", player->slang);
2690 }
2691
2692 /* disable msg stuff to make sure extra console characters don't mess around */
2693 argv[argn++] = g_strdup_printf("-nomsgcolor");
2694 argv[argn++] = g_strdup_printf("-nomsgmodule");
2695
2696 // mplayer says that nokeepaspect isn't supported by all vo's but it seems to work
2697 //if (player->use_mplayer2)
2698 argv[argn++] = g_strdup_printf("-nokeepaspect");
2699
2700 if (player->audio_track_file != NULL && strlen(player->audio_track_file) > 0) {
2701 argv[argn++] = g_strdup_printf("-audiofile");
2702 argv[argn++] = g_strdup_printf("%s", player->audio_track_file);
2703 }
2704
2705 if (player->subtitle_file != NULL && strlen(player->subtitle_file) > 0) {
2706 argv[argn++] = g_strdup_printf("-sub");
2707 argv[argn++] = g_strdup_printf("%s", player->subtitle_file);
2708 }
2709 // subtitle stuff
2710 if (player->enable_advanced_subtitles) {
2711 argv[argn++] = g_strdup_printf("-ass");
2712
2713 if (player->subtitle_margin > 0) {
2714 argv[argn++] = g_strdup_printf("-ass-bottom-margin");
2715 argv[argn++] = g_strdup_printf("%i", player->subtitle_margin);
2716 argv[argn++] = g_strdup_printf("-ass-use-margins");
2717 }
2718
2719 if (player->enable_embedded_fonts) {
2720 argv[argn++] = g_strdup_printf("-embeddedfonts");
2721 } else {
2722 argv[argn++] = g_strdup_printf("-noembeddedfonts");
2723
2724 if (player->subtitle_font != NULL && strlen(player->subtitle_font) > 0) {
2725 fontname = g_strdup(player->subtitle_font);
2726 size = g_strrstr(fontname, " ");
2727 if (size)
2728 size[0] = '\0';
2729 size = g_strrstr(fontname, " Bold");
2730 if (size)
2731 size[0] = '\0';
2732 size = g_strrstr(fontname, " Italic");
2733 if (size)
2734 size[0] = '\0';
2735 argv[argn++] = g_strdup_printf("-ass-force-style");
2736 argv[argn++] = g_strconcat("FontName=", fontname,
2737 ((g_strrstr(player->subtitle_font, "Italic") !=
2738 NULL) ? ",Italic=1" : ",Italic=0"),
2739 ((g_strrstr(player->subtitle_font, "Bold") !=
2740 NULL) ? ",Bold=1" : ",Bold=0"),
2741 (player->subtitle_outline ? ",Outline=1" : ",Outline=0"),
2742 (player->subtitle_shadow ? ",Shadow=2" : ",Shadow=0"), NULL);
2743 g_free(fontname);
2744 }
2745 }
2746
2747 argv[argn++] = g_strdup_printf("-ass-font-scale");
2748 tmp = g_new0(char, G_ASCII_DTOSTR_BUF_SIZE);
2749 tmp = g_ascii_dtostr(tmp, G_ASCII_DTOSTR_BUF_SIZE, player->subtitle_scale);
2750 argv[argn++] = g_strdup(tmp);
2751 g_free(tmp);
2752
2753 if (player->subtitle_color != NULL && strlen(player->subtitle_color) > 0) {
2754 argv[argn++] = g_strdup_printf("-ass-color");
2755 argv[argn++] = g_strdup_printf("%s", player->subtitle_color);
2756 }
2757
2758 } else {
2759 if (player->subtitle_scale != 0) {
2760 argv[argn++] = g_strdup_printf("-subfont-text-scale");
2761 argv[argn++] = g_strdup_printf("%d", (int) (player->subtitle_scale * 5)); // 5 is the default
2762 }
2763
2764 if (player->subtitle_font != NULL && strlen(player->subtitle_font) > 0) {
2765 fontname = g_strdup(player->subtitle_font);
2766 size = g_strrstr(fontname, " ");
2767 if (size)
2768 size[0] = '\0';
2769 argv[argn++] = g_strdup_printf("-subfont");
2770 argv[argn++] = g_strdup_printf("%s", fontname);
2771 g_free(fontname);
2772 }
2773 }
2774
2775 if (player->subtitle_codepage != NULL && strlen(player->subtitle_codepage) > 0) {
2776 argv[argn++] = g_strdup_printf("-subcp");
2777 argv[argn++] = g_strdup_printf("%s", player->subtitle_codepage);
2778 }
2779
2780 if (player->extra_opts != NULL) {
2781 char **opts = g_strsplit(player->extra_opts, " ", -1);
2782 int i;
2783 for (i = 0; opts[i] != NULL; i++)
2784 argv[argn++] = g_strdup(opts[i]);
2785 g_strfreev(opts);
2786 }
2787
2788 switch (player->type) {
2789 case TYPE_FILE:
2790 if (filename != NULL) {
2791 if (player->force_cache && player->cache_size >= 32) {
2792 argv[argn++] = g_strdup_printf("-cache");
2793 argv[argn++] = g_strdup_printf("%i", (gint) player->cache_size);
2794 }
2795 if (player->playlist) {
2796 argv[argn++] = g_strdup_printf("-playlist");
2797 }
2798 argv[argn++] = g_strdup_printf("%s", filename);
2799 break;
2800 }
2801 case TYPE_CD:
2802 argv[argn++] = g_strdup_printf("-cache");
2803 argv[argn++] = g_strdup_printf("%i", (gint) player->cache_size);
2804 argv[argn++] = g_strdup_printf("%s", player->uri);
2805 if (player->media_device != NULL) {
2806 argv[argn++] = g_strdup_printf("-dvd-device");
2807 argv[argn++] = g_strdup_printf("%s", player->media_device);
2808 }
2809 break;
2810
2811 case TYPE_DVD:
2812 argv[argn++] = g_strdup_printf("-mouse-movements");
2813 argv[argn++] = g_strdup_printf("-nocache");
2814 argv[argn++] = g_strdup_printf("dvdnav://");
2815 if (player->media_device != NULL) {
2816 argv[argn++] = g_strdup_printf("-dvd-device");
2817 argv[argn++] = g_strdup_printf("%s", player->media_device);
2818 }
2819 break;
2820
2821 case TYPE_VCD:
2822 argv[argn++] = g_strdup_printf("-nocache");
2823 argv[argn++] = g_strdup_printf("%s", player->uri);
2824 if (player->media_device != NULL) {
2825 argv[argn++] = g_strdup_printf("-dvd-device");
2826 argv[argn++] = g_strdup_printf("%s", player->media_device);
2827 }
2828 break;
2829
2830 case TYPE_NETWORK:
2831 if (g_strrstr(player->uri, "apple.com")) {
2832 argv[argn++] = g_strdup_printf("-user-agent");
2833 argv[argn++] = g_strdup_printf("QuickTime/7.6.9");
2834 }
2835 if (player->cache_size >= 32) {
2836 argv[argn++] = g_strdup_printf("-cache");
2837 argv[argn++] = g_strdup_printf("%i", (gint) player->cache_size);
2838 }
2839 if (player->playlist) {
2840 argv[argn++] = g_strdup_printf("-playlist");
2841 }
2842 argv[argn++] = g_strdup_printf("%s", player->uri);
2843 break;
2844
2845 case TYPE_DVB:
2846 case TYPE_TV:
2847 if (player->tv_device != NULL) {
2848 argv[argn++] = g_strdup_printf("-tv:device");
2849 argv[argn++] = g_strdup_printf("%s", player->tv_device);
2850 }
2851 if (player->tv_driver != NULL) {
2852 argv[argn++] = g_strdup_printf("-tv:driver");
2853 argv[argn++] = g_strdup_printf("%s", player->tv_driver);
2854 }
2855 if (player->tv_input != NULL) {
2856 argv[argn++] = g_strdup_printf("-tv:input");
2857 argv[argn++] = g_strdup_printf("%s", player->tv_input);
2858 }
2859 if (player->tv_width > 0) {
2860 argv[argn++] = g_strdup_printf("-tv:width");
2861 argv[argn++] = g_strdup_printf("%i", player->tv_width);
2862 }
2863 if (player->tv_height > 0) {
2864 argv[argn++] = g_strdup_printf("-tv:height");
2865 argv[argn++] = g_strdup_printf("%i", player->tv_height);
2866 }
2867 if (player->tv_fps > 0) {
2868 argv[argn++] = g_strdup_printf("-tv:fps");
2869 argv[argn++] = g_strdup_printf("%i", player->tv_fps);
2870 }
2871 argv[argn++] = g_strdup_printf("-nocache");
2872 argv[argn++] = g_strdup_printf("%s", player->uri);
2873
2874
2875 default:
2876 break;
2877 }
2878 argv[argn] = NULL;
2879
2880 gchar *allargs = g_strjoinv(" ", argv);
2881 gm_log(player->debug, G_LOG_LEVEL_INFO, "%s", allargs);
2882 g_free(allargs);
2883
2884 error = NULL;
2885 player->std_in = -1;
2886 player->std_out = -1;
2887 player->std_err = -1;
2888 spawn =
2889 g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &pid,
2890 &(player->std_in), &(player->std_out), &(player->std_err), &error);
2891
2892 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "spawn = %s files in %i out %i err %i", gm_bool_to_string(spawn),
2893 player->std_in, player->std_out, player->std_err);
2894
2895 if (error != NULL) {
2896 gm_log(player->debug, G_LOG_LEVEL_INFO, "error code = %i - %s", error->code, error->message);
2897 g_error_free(error);
2898 error = NULL;
2899 }
2900
2901 argn = 0;
2902 while (argv[argn] != NULL) {
2903 g_free(argv[argn]);
2904 argv[argn] = NULL;
2905 argn++;
2906 }
2907
2908 if (spawn) {
2909 gmtk_media_player_log_state(player, "launched");
2910 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "spawn succeeded, setup up channels");
2911
2912 player->player_state = PLAYER_STATE_RUNNING;
2913 player->media_state = MEDIA_STATE_BUFFERING;
2914 if (player->channel_in != NULL) {
2915 g_io_channel_unref(player->channel_in);
2916 player->channel_in = NULL;
2917 }
2918
2919 if (player->channel_out != NULL) {
2920 g_io_channel_unref(player->channel_out);
2921 player->channel_out = NULL;
2922 }
2923
2924 if (player->channel_err != NULL) {
2925 g_io_channel_unref(player->channel_err);
2926 player->channel_err = NULL;
2927 }
2928
2929 player->channel_in = g_io_channel_unix_new(player->std_in);
2930 g_io_channel_set_encoding(player->channel_in, NULL, NULL);
2931 player->channel_out = g_io_channel_unix_new(player->std_out);
2932 g_io_channel_set_encoding(player->channel_out, NULL, NULL);
2933 player->channel_err = g_io_channel_unix_new(player->std_err);
2934 g_io_channel_set_encoding(player->channel_err, NULL, NULL);
2935
2936 g_io_channel_set_close_on_unref(player->channel_in, TRUE);
2937 g_io_channel_set_close_on_unref(player->channel_out, TRUE);
2938 g_io_channel_set_close_on_unref(player->channel_err, TRUE);
2939
2940 player->watch_in_id =
2941 g_io_add_watch_full(player->channel_out, G_PRIORITY_LOW, G_IO_IN, thread_reader, player, NULL);
2942 player->watch_err_id =
2943 g_io_add_watch_full(player->channel_err, G_PRIORITY_LOW, G_IO_IN, thread_reader_error, player, NULL);
2944 player->watch_in_hup_id =
2945 g_io_add_watch_full(player->channel_out, G_PRIORITY_LOW, G_IO_HUP, thread_complete, player, NULL);
2946
2947 #ifdef GLIB2_14_ENABLED
2948 g_timeout_add_seconds(1, thread_query, player);
2949 #else
2950 g_timeout_add(1000, thread_query, player);
2951 #endif
2952
2953 // /////////////////////////////////////////////////////////////////////
2954 // Now this thread waits till somebody signals player->mplayer_complete_cond
2955
2956 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "waiting for mplayer_complete_cond");
2957 g_cond_wait(player->mplayer_complete_cond, player->thread_running);
2958 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "mplayer_complete_cond was signalled");
2959
2960 g_source_remove(player->watch_in_id);
2961 g_source_remove(player->watch_err_id);
2962 g_source_remove(player->watch_in_hup_id);
2963 if (player->channel_in != NULL) {
2964 g_io_channel_shutdown(player->channel_in, FALSE, NULL);
2965 g_io_channel_unref(player->channel_in);
2966 player->channel_in = NULL;
2967 }
2968
2969 if (player->channel_out != NULL) {
2970 g_io_channel_shutdown(player->channel_out, FALSE, NULL);
2971 g_io_channel_unref(player->channel_out);
2972 player->channel_out = NULL;
2973 }
2974
2975 if (player->channel_err != NULL) {
2976 g_io_channel_shutdown(player->channel_err, FALSE, NULL);
2977 g_io_channel_unref(player->channel_err);
2978 player->channel_err = NULL;
2979 }
2980 close(player->std_in);
2981 player->std_in = -1;
2982 g_spawn_close_pid(pid);
2983
2984 }
2985
2986 if (player->cache_percent < 0.0 && g_str_has_prefix(player->uri, "mms"))
2987 player->playback_error = ERROR_RETRY_WITH_MMSHTTP;
2988
2989 if (player->cache_percent < 0.0 && g_str_has_prefix(player->uri, "mmshttp"))
2990 player->playback_error = ERROR_RETRY_WITH_HTTP;
2991
2992 switch (player->playback_error) {
2993 case ERROR_RETRY_WITH_PLAYLIST:
2994 player->playlist = TRUE;
2995 break;
2996
2997 case ERROR_RETRY_WITH_HTTP:
2998 tmp = gmtk_media_player_switch_protocol(player->uri, "http");
2999 g_free(player->uri);
3000 player->uri = tmp;
3001 break;
3002
3003 case ERROR_RETRY_WITH_HTTP_AND_PLAYLIST:
3004 tmp = gmtk_media_player_switch_protocol(player->uri, "http");
3005 g_free(player->uri);
3006 player->uri = tmp;
3007 player->playlist = TRUE;
3008 break;
3009
3010 case ERROR_RETRY_WITH_MMSHTTP:
3011 tmp = gmtk_media_player_switch_protocol(player->uri, "mmsh");
3012 g_free(player->uri);
3013 player->uri = tmp;
3014 break;
3015
3016 case ERROR_RETRY_WITHOUT_DIVX_VDPAU:
3017 player->enable_divx = FALSE;
3018 break;
3019
3020 case ERROR_RETRY_WITHOUT_XVMC:
3021 player->disable_xvmc = TRUE;
3022 break;
3023
3024 case ERROR_RETRY_ALSA_BUSY:
3025 case ERROR_RETRY_VDPAU:
3026 break;
3027 case ERROR_RETRY:
3028 if (last_error == NO_ERROR) {
3029 last_error = ERROR_RETRY;
3030 } else {
3031 last_error = NO_ERROR;
3032 player->playback_error = NO_ERROR;
3033 }
3034 break;
3035
3036 case ERROR_RETRY_WITHOUT_HARDWARE_CODECS:
3037 player->enable_hardware_codecs = FALSE;
3038 break;
3039
3040 case ERROR_RETRY_WITHOUT_AF_EXPORT:
3041 player->hardware_ac3 = TRUE;
3042 break;
3043
3044 default:
3045 break;
3046 }
3047
3048 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "playback error code is %s",
3049 playback_error_to_string(player->playback_error));
3050
3051 } while (player->playback_error != NO_ERROR);
3052
3053 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "marking playback complete");
3054 player->player_state = PLAYER_STATE_DEAD;
3055 player->media_state = MEDIA_STATE_UNKNOWN;
3056 player->mplayer_thread = NULL;
3057 player->start_time = 0.0;
3058 player->run_time = 0.0;
3059 if (player->artist) {
3060 g_free(player->artist);
3061 player->artist = NULL;
3062 }
3063 if (player->title) {
3064 g_free(player->title);
3065 player->title = NULL;
3066 }
3067 if (player->album) {
3068 g_free(player->album);
3069 player->album = NULL;
3070 }
3071
3072 gmtk_media_player_log_state(player, "finished");
3073
3074 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "unlocking thread_running");
3075 g_mutex_unlock(player->thread_running);
3076
3077 if (player->restart) {
3078 g_signal_emit_by_name(player, "restart-shutdown-complete", NULL);
3079 } else {
3080 create_event_double(player, "position-changed", 0.0);
3081 create_event_int(player, "player-state-changed", player->player_state);
3082 create_event_int(player, "media-state-changed", player->media_state);
3083 }
3084
3085 return NULL;
3086 }
3087
finalize_mplayer(GmtkMediaPlayer * player)3088 static void finalize_mplayer(GmtkMediaPlayer * player)
3089 {
3090 g_source_remove(player->watch_in_id);
3091 g_source_remove(player->watch_in_hup_id);
3092 g_source_remove(player->watch_err_id);
3093 g_unlink(player->af_export_filename);
3094 gmtk_media_player_log_state(player, "completed");
3095 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "signaling mplayer_complete_cond");
3096 g_cond_signal(player->mplayer_complete_cond);
3097 }
3098
3099 // this executes in the main thread
thread_complete(GIOChannel * source,GIOCondition condition,gpointer data)3100 gboolean thread_complete(GIOChannel * source, GIOCondition condition, gpointer data)
3101 {
3102 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(data);
3103
3104 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "thread_complete()");
3105 player->player_state = PLAYER_STATE_DEAD;
3106 player->media_state = MEDIA_STATE_UNKNOWN;
3107 finalize_mplayer(player);
3108
3109 return FALSE;
3110 }
3111
3112 // this executes in the main thread
thread_reader_error(GIOChannel * source,GIOCondition condition,gpointer data)3113 gboolean thread_reader_error(GIOChannel * source, GIOCondition condition, gpointer data)
3114 {
3115 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(data);
3116 GString *mplayer_output;
3117 GIOStatus status;
3118 gchar *error_msg = NULL;
3119 //GtkWidget *dialog;
3120 gchar *buf;
3121
3122 if (player == NULL) {
3123 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "player is NULL");
3124 finalize_mplayer(player);
3125 return FALSE;
3126 }
3127
3128 if (source == NULL) {
3129 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "source is null");
3130 finalize_mplayer(player);
3131 return FALSE;
3132 }
3133
3134 if (player->player_state == PLAYER_STATE_DEAD) {
3135 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "player is dead");
3136 finalize_mplayer(player);
3137 return FALSE;
3138 }
3139
3140 mplayer_output = g_string_new("");
3141 status = g_io_channel_read_line_string(source, mplayer_output, NULL, NULL);
3142 if (status == G_IO_STATUS_ERROR) {
3143 gm_logsp(player->debug, G_LOG_LEVEL_INFO, "GIO IO Error:", mplayer_output->str);
3144 return TRUE;
3145 } else {
3146 if (g_strrstr(mplayer_output->str, "ANS") == NULL) {
3147 gm_logsp(player->debug, G_LOG_LEVEL_INFO, "< ERROR:", mplayer_output->str);
3148 }
3149
3150 if (strstr(mplayer_output->str, "Couldn't open DVD device") != 0) {
3151 error_msg = g_strdup(mplayer_output->str);
3152 }
3153
3154 if (strstr(mplayer_output->str, "X11 error") != 0) {
3155 create_event_int(player, "attribute-changed", ATTRIBUTE_SIZE);
3156 }
3157
3158 if (strstr(mplayer_output->str, "signal") != NULL) {
3159 if (strstr(mplayer_output->str, "decode") != NULL) {
3160 create_event_int(player, "attribute-changed", ATTRIBUTE_SIZE);
3161 if (player->position == 0) {
3162 player->playback_error = ERROR_RETRY;
3163 }
3164 } else if (strstr(mplayer_output->str, "filter video") != NULL) {
3165 player->playback_error = ERROR_RETRY;
3166 } else {
3167 error_msg = g_strdup(mplayer_output->str);
3168 }
3169 }
3170 if (strstr(mplayer_output->str, "Error when calling vdp_output_surface_create") != NULL) {
3171 create_event_int(player, "attribute-changed", ATTRIBUTE_SIZE);
3172 if (player->position == 0) {
3173 player->playback_error = ERROR_RETRY;
3174 }
3175 }
3176
3177 if (strstr(mplayer_output->str, "Failed creating VDPAU decoder") != NULL) {
3178 if (player->enable_divx && vodesc_looks_like_vo(player->vo, "vdpau"))
3179 player->playback_error = ERROR_RETRY_WITHOUT_DIVX_VDPAU;
3180 }
3181
3182 if (strstr(mplayer_output->str, "decoding to PIX_FMT_NONE is not supported") != NULL) {
3183 if (player->enable_divx)
3184 player->playback_error = ERROR_RETRY_WITHOUT_HARDWARE_CODECS;
3185 }
3186
3187 if (strstr(mplayer_output->str, "The selected video_out device is incompatible with this codec") != NULL) {
3188 if (!player->disable_xvmc && vodesc_looks_like_vo(player->vo, "xvmc"))
3189 player->playback_error = ERROR_RETRY_WITHOUT_XVMC;
3190 }
3191
3192 if (strstr(mplayer_output->str, "[AO_ALSA] Playback open error: Device or resource busy") != NULL) {
3193 player->playback_error = ERROR_RETRY_ALSA_BUSY;
3194 }
3195
3196 if (strstr(mplayer_output->str, "Sample format big-endian AC3 not yet supported") != NULL) {
3197 player->playback_error = ERROR_RETRY_WITHOUT_AF_EXPORT;
3198 }
3199
3200 /*
3201 if (strstr(mplayer_output->str, "Error when calling vdp_output_surface_create") != NULL) {
3202 create_event_int(player, "attribute-changed", ATTRIBUTE_SIZE);
3203 player->playback_error = ERROR_RETRY_VDPAU;
3204 write_to_mplayer(player, "quit\n");
3205 }
3206 */
3207
3208 if (strstr(mplayer_output->str, "Failed to open") != NULL) {
3209 if (strstr(mplayer_output->str, "LIRC") == NULL &&
3210 strstr(mplayer_output->str, "input.conf") == NULL &&
3211 strstr(mplayer_output->str, "/dev/rtc") == NULL &&
3212 strstr(mplayer_output->str, "VDPAU") == NULL && strstr(mplayer_output->str, "registry file") == NULL) {
3213 if (strstr(mplayer_output->str, "<") == NULL && strstr(mplayer_output->str, ">") == NULL
3214 && player->type == TYPE_FILE) {
3215 error_msg =
3216 g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Failed to open %s"),
3217 mplayer_output->str + strlen("Failed to open "));
3218 }
3219
3220 if (strstr(mplayer_output->str, "mms://") != NULL && player->type == TYPE_NETWORK) {
3221 player->playback_error = ERROR_RETRY_WITH_MMSHTTP;
3222 }
3223 }
3224 }
3225
3226 if (strstr(mplayer_output->str, "MPlayer interrupted by signal 13 in module: open_stream") != NULL
3227 && g_strrstr(player->uri, "mms://") != NULL) {
3228 player->playback_error = ERROR_RETRY_WITH_MMSHTTP;
3229 }
3230
3231 if (strstr(mplayer_output->str, "No stream found to handle url mmshttp://") != NULL) {
3232 player->playback_error = ERROR_RETRY_WITH_HTTP;
3233 }
3234
3235 if (strstr(mplayer_output->str, "Server returned 404:File Not Found") != NULL
3236 && g_strrstr(player->uri, "mmshttp://") != NULL) {
3237 player->playback_error = ERROR_RETRY_WITH_HTTP;
3238 }
3239
3240 if (strstr(mplayer_output->str, "unknown ASF streaming type") != NULL
3241 && g_strrstr(player->uri, "mmshttp://") != NULL) {
3242 player->playback_error = ERROR_RETRY_WITH_HTTP;
3243 }
3244
3245 if (strstr(mplayer_output->str, "Error while parsing chunk header") != NULL) {
3246 player->playback_error = ERROR_RETRY_WITH_HTTP_AND_PLAYLIST;
3247 }
3248
3249 if (strstr(mplayer_output->str, "Failed to initiate \"video/X-ASF-PF\" RTP subsession") != NULL) {
3250 player->playback_error = ERROR_RETRY_WITH_PLAYLIST;
3251 }
3252
3253 if (strstr(mplayer_output->str, "playlist support will not be used") != NULL) {
3254 player->playback_error = ERROR_RETRY_WITH_PLAYLIST;
3255 }
3256
3257 if (strstr(mplayer_output->str, "Compressed SWF format not supported") != NULL) {
3258 error_msg = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Compressed SWF format not supported"));
3259 }
3260
3261 if (strstr(mplayer_output->str, "moov atom not found") != NULL) {
3262 player->retry_on_full_cache = TRUE;
3263 create_event_boolean(player, "attribute-changed", ATTRIBUTE_RETRY_ON_FULL_CACHE);
3264 }
3265
3266 if (strstr(mplayer_output->str, "MOV: missing header (moov/cmov) chunk") != NULL) {
3267 player->retry_on_full_cache = TRUE;
3268 create_event_boolean(player, "attribute-changed", ATTRIBUTE_RETRY_ON_FULL_CACHE);
3269 }
3270
3271 if (strstr(mplayer_output->str, "Seek failed") != NULL) {
3272 write_to_mplayer(player, "quit\n");
3273 player->retry_on_full_cache = TRUE;
3274 create_event_boolean(player, "attribute-changed", ATTRIBUTE_RETRY_ON_FULL_CACHE);
3275 }
3276
3277 if (strstr(mplayer_output->str, "Title: ") != 0) {
3278 buf = strstr(mplayer_output->str, "Title:");
3279 buf = strstr(mplayer_output->str, "Title: ") + strlen("Title: ");
3280 buf = g_strchomp(buf);
3281 if (player->title != NULL) {
3282 g_free(player->title);
3283 player->title = NULL;
3284 }
3285
3286 player->title = g_locale_to_utf8(buf, -1, NULL, NULL, NULL);
3287 if (player->title == NULL) {
3288 player->title = g_strdup(buf);
3289 gm_str_strip_unicode(player->title, strlen(player->title));
3290 }
3291 create_event_int(player, "attribute-changed", ATTRIBUTE_TITLE);
3292 }
3293
3294 if (error_msg != NULL && player->playback_error == NO_ERROR) {
3295 create_event_string(player, "error-message", error_msg);
3296 /*
3297 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
3298 GTK_BUTTONS_CLOSE, "%s", error_msg);
3299 gtk_window_set_title(GTK_WINDOW(dialog), g_dgettext(GETTEXT_PACKAGE, "GNOME MPlayer Error"));
3300 gtk_dialog_run(GTK_DIALOG(dialog));
3301 gtk_widget_destroy(dialog);
3302 */
3303 g_free(error_msg);
3304 error_msg = NULL;
3305 }
3306
3307 }
3308 g_string_free(mplayer_output, TRUE);
3309
3310 return TRUE;
3311 }
3312
3313 // this executes in the main thread
thread_reader(GIOChannel * source,GIOCondition condition,gpointer data)3314 gboolean thread_reader(GIOChannel * source, GIOCondition condition, gpointer data)
3315 {
3316 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(data);
3317 GString *mplayer_output;
3318 GIOStatus status;
3319 GError *error = NULL;
3320 gchar *buf, *title, *message = NULL, *icy = NULL;
3321 gint w, h, i;
3322 gfloat percent, oldposition;
3323 gchar vm[10];
3324 gint id;
3325 GtkAllocation allocation = { 0 };
3326 GmtkMediaPlayerSubtitle *subtitle = NULL;
3327 GmtkMediaPlayerAudioTrack *audio_track = NULL;
3328 GList *iter;
3329 GtkWidget *dialog;
3330 gchar **split;
3331 gint index;
3332
3333 if (player == NULL) {
3334 gm_log(player->debug, G_LOG_LEVEL_MESSAGE, "player is NULL");
3335 finalize_mplayer(player);
3336 return FALSE;
3337 }
3338
3339 if (source == NULL) {
3340 gm_log(player->debug, G_LOG_LEVEL_INFO, "source is null");
3341 finalize_mplayer(player);
3342 return FALSE;
3343 }
3344
3345 if (player->player_state == PLAYER_STATE_DEAD) {
3346 gm_log(player->debug, G_LOG_LEVEL_INFO, "player is dead");
3347 finalize_mplayer(player);
3348 return FALSE;
3349 }
3350
3351 mplayer_output = g_string_new("");
3352
3353 status = g_io_channel_read_line_string(source, mplayer_output, NULL, &error);
3354 if (status == G_IO_STATUS_ERROR) {
3355 gm_logsp(player->debug, G_LOG_LEVEL_INFO, "GIO IO Error:", mplayer_output->str);
3356 return TRUE;
3357 } else {
3358 if (g_strrstr(mplayer_output->str, "ANS") == NULL) {
3359 gm_logsp(player->debug, G_LOG_LEVEL_INFO, "<", mplayer_output->str);
3360 } else {
3361 gm_logsp(player->debug, G_LOG_LEVEL_DEBUG, "<", mplayer_output->str);
3362 }
3363
3364 if (strstr(mplayer_output->str, "Cache fill") != 0) {
3365 buf = strstr(mplayer_output->str, "Cache fill");
3366 sscanf(buf, "Cache fill: %f%%", &percent);
3367 buf = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Cache fill: %2.2f%%"), percent);
3368 player->cache_percent = percent / 100.0;
3369 create_event_double(player, "cache-percent-changed", player->cache_percent);
3370 }
3371
3372 if (strstr(mplayer_output->str, "AO:") != NULL) {
3373 write_to_mplayer(player, "get_property switch_audio\n");
3374 }
3375
3376 if (strstr(mplayer_output->str, "VO:") != NULL) {
3377 buf = strstr(mplayer_output->str, "VO:");
3378 sscanf(buf, "VO: [%[^]]] %ix%i => %ix%i", vm, &w, &h, &(player->video_width), &(player->video_height));
3379 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "%ix%i => %ix%i", w, h, player->video_width, player->video_height);
3380 gmtk_get_allocation(GTK_WIDGET(player), &allocation);
3381 player->media_state = MEDIA_STATE_PLAY;
3382 if (player->restart) {
3383 g_signal_emit_by_name(player, "restart-complete", NULL);
3384 } else {
3385 create_event_int(player, "media-state-changed", player->media_state);
3386 allocation.width = player->video_width;
3387 allocation.height = player->video_height;
3388 if (player->video_present == FALSE) {
3389 create_event_allocation(player, "size_allocate", &allocation);
3390 }
3391 player->video_present = TRUE;
3392 buf = g_strdup_printf("set_property sub_visibility %i\n", player->sub_visible);
3393 write_to_mplayer(player, buf);
3394 g_free(buf);
3395 write_to_mplayer(player, "get_property sub_source\n");
3396 write_to_mplayer(player, "get_property sub_visibility\n");
3397 create_event_int(player, "attribute-changed", ATTRIBUTE_SIZE);
3398 create_event_int(player, "attribute-changed", ATTRIBUTE_VIDEO_PRESENT);
3399 create_event_int(player, "subtitles-changed", g_list_length(player->subtitles));
3400 create_event_int(player, "audio-tracks-changed", g_list_length(player->audio_tracks));
3401 create_event_double(player, "cache-percent-changed", 0.0);
3402 }
3403 create_event_int(player, "attribute-changed", ATTRIBUTE_AF_EXPORT_FILENAME);
3404 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_TRACK);
3405 create_event_int(player, "attribute-changed", ATTRIBUTE_SUBTITLE);
3406 gmtk_media_player_log_state(player, "media_loaded");
3407 }
3408
3409 if (strstr(mplayer_output->str, "Video: no video") != NULL) {
3410 gm_log(player->debug, G_LOG_LEVEL_MESSAGE, "Running in audio only mode");
3411 player->video_width = 0;
3412 player->video_height = 0;
3413 gmtk_get_allocation(GTK_WIDGET(player), &allocation);
3414 player->media_state = MEDIA_STATE_PLAY;
3415 if (player->restart) {
3416 g_signal_emit_by_name(player, "restart-complete", NULL);
3417 } else {
3418 create_event_int(player, "media-state-changed", player->media_state);
3419 player->video_present = FALSE;
3420 create_event_int(player, "attribute-changed", ATTRIBUTE_SIZE);
3421 create_event_int(player, "attribute-changed", ATTRIBUTE_VIDEO_PRESENT);
3422 create_event_int(player, "subtitles-changed", g_list_length(player->subtitles));
3423 create_event_int(player, "audio-tracks-changed", g_list_length(player->audio_tracks));
3424 create_event_double(player, "cache-percent-changed", 0.0);
3425 }
3426 create_event_int(player, "attribute-changed", ATTRIBUTE_AF_EXPORT_FILENAME);
3427 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_TRACK);
3428 create_event_int(player, "attribute-changed", ATTRIBUTE_SUBTITLE);
3429 gmtk_media_player_log_state(player, "media_loaded");
3430 }
3431
3432 if (strstr(mplayer_output->str, "ANS_TIME_POSITION") != 0) {
3433 buf = strstr(mplayer_output->str, "ANS_TIME_POSITION");
3434 oldposition = player->position;
3435 sscanf(buf, "ANS_TIME_POSITION=%lf", &player->position);
3436 if (oldposition != player->position)
3437 create_event_double(player, "position-changed", player->position);
3438 if (player->position > player->length)
3439 write_to_mplayer(player, "get_time_length\n");
3440 }
3441
3442 if (strstr(mplayer_output->str, "ID_START_TIME") != 0) {
3443 buf = strstr(mplayer_output->str, "ID_START_TIME");
3444 sscanf(buf, "ID_START_TIME=%lf", &player->start_time);
3445 create_event_int(player, "attribute-changed", ATTRIBUTE_START_TIME);
3446 }
3447
3448 if (strstr(mplayer_output->str, "ID_LENGTH") != 0) {
3449 buf = strstr(mplayer_output->str, "ID_LENGTH");
3450 sscanf(buf, "ID_LENGTH=%lf", &player->length);
3451 create_event_int(player, "attribute-changed", ATTRIBUTE_LENGTH);
3452 }
3453
3454 if (strstr(mplayer_output->str, "ANS_LENGTH") != 0) {
3455 buf = strstr(mplayer_output->str, "ANS_LENGTH");
3456 sscanf(buf, "ANS_LENGTH=%lf", &player->length);
3457 create_event_int(player, "attribute-changed", ATTRIBUTE_LENGTH);
3458 }
3459
3460 if (strstr(mplayer_output->str, "ID_AUDIO_TRACK") != 0) {
3461 buf = strstr(mplayer_output->str, "ID_AUDIO_TRACK");
3462 id = player->audio_track_id;
3463 sscanf(buf, "ID_AUDIO_TRACK=%i", &player->audio_track_id);
3464 if (id != player->audio_track_id)
3465 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_TRACK);
3466 }
3467
3468 if (strstr(mplayer_output->str, "ANS_switch_audio") != 0) {
3469 buf = strstr(mplayer_output->str, "ANS_switch_audio");
3470 id = player->audio_track_id;
3471 sscanf(buf, "ANS_switch_audio=%i", &player->audio_track_id);
3472 if (id != player->audio_track_id)
3473 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_TRACK);
3474 }
3475
3476 if (strstr(mplayer_output->str, "ANS_sub_source") != 0) {
3477 buf = strstr(mplayer_output->str, "ANS_sub_source");
3478 sscanf(buf, "ANS_sub_source=%i", &player->subtitle_source);
3479 switch (player->subtitle_source) {
3480 case 0:
3481 player->subtitle_is_file = TRUE;
3482 write_to_mplayer(player, "get_property sub_file\n");
3483 break;
3484 case 1:
3485 player->subtitle_is_file = FALSE;
3486 write_to_mplayer(player, "get_property sub_vob\n");
3487 break;
3488 case 2:
3489 player->subtitle_is_file = FALSE;
3490 write_to_mplayer(player, "get_property sub_demux\n");
3491 break;
3492 }
3493 }
3494
3495 if (strstr(mplayer_output->str, "ANS_sub_file") != 0) {
3496 buf = strstr(mplayer_output->str, "ANS_sub_file");
3497 sscanf(buf, "ANS_sub_file=%i", &player->subtitle_id);
3498 create_event_int(player, "attribute-changed", ATTRIBUTE_SUBTITLE);
3499 }
3500
3501 if (strstr(mplayer_output->str, "ANS_sub_demux") != 0) {
3502 buf = strstr(mplayer_output->str, "ANS_sub_demux");
3503 sscanf(buf, "ANS_sub_demux=%i", &player->subtitle_id);
3504 create_event_int(player, "attribute-changed", ATTRIBUTE_SUBTITLE);
3505 }
3506
3507 if (strstr(mplayer_output->str, "ANS_sub_visibility") != 0) {
3508 if (strstr(mplayer_output->str, "ANS_sub_visibility=yes") != 0) {
3509 player->sub_visible = TRUE;
3510 } else {
3511 player->sub_visible = FALSE;
3512 }
3513 create_event_int(player, "attribute-changed", ATTRIBUTE_SUB_VISIBLE);
3514 }
3515
3516 if (strstr(mplayer_output->str, "ANS_speed") != 0) {
3517 buf = strstr(mplayer_output->str, "ANS_speed");
3518 sscanf(buf, "ANS_speed=%lf", &player->speed);
3519 gm_log(player->debug, G_LOG_LEVEL_MESSAGE, "new speed is %lf", player->speed);
3520 create_event_int(player, "attribute-changed", ATTRIBUTE_SPEED_SET);
3521 }
3522
3523 if (strstr(mplayer_output->str, "DVDNAV_TITLE_IS_MENU") != 0) {
3524 player->title_is_menu = TRUE;
3525 write_to_mplayer(player, "get_time_length\n");
3526 }
3527
3528 if (strstr(mplayer_output->str, "DVDNAV_TITLE_IS_MOVIE") != 0) {
3529 player->title_is_menu = FALSE;
3530 write_to_mplayer(player, "get_time_length\n");
3531 }
3532
3533 if (strstr(mplayer_output->str, "ID_SUBTITLE_ID=") != 0) {
3534 buf = strstr(mplayer_output->str, "ID_SUBTITLE_ID");
3535 sscanf(buf, "ID_SUBTITLE_ID=%i", &id);
3536 subtitle = g_new0(GmtkMediaPlayerSubtitle, 1);
3537 subtitle->id = id;
3538 subtitle->lang = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Unknown"));
3539 subtitle->name = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Unknown"));
3540 subtitle->label = g_strdup_printf("%s (%s) - %i", subtitle->name, subtitle->lang, subtitle->id);
3541 player->subtitles = g_list_append(player->subtitles, subtitle);
3542
3543 }
3544
3545 if (strstr(mplayer_output->str, "ID_SID_") != 0) {
3546 buf = strstr(mplayer_output->str, "ID_SID_");
3547 sscanf(buf, "ID_SID_%i_", &id);
3548 g_string_truncate(mplayer_output, mplayer_output->len - 1);
3549 buf = strstr(mplayer_output->str, "_LANG=");
3550 if (buf != NULL) {
3551 buf += strlen("_LANG=");
3552 iter = player->subtitles;
3553 while (iter) {
3554 subtitle = ((GmtkMediaPlayerSubtitle *) (iter->data));
3555 if (subtitle->id == id && subtitle->is_file == FALSE) {
3556 if (subtitle->lang != NULL) {
3557 g_free(subtitle->lang);
3558 subtitle->lang = NULL;
3559 }
3560 subtitle->lang = g_strdup(buf);
3561 }
3562 iter = iter->next;
3563 }
3564 }
3565 buf = strstr(mplayer_output->str, "_NAME=");
3566 if (buf != NULL) {
3567 buf += strlen("_NAME=");
3568 iter = player->subtitles;
3569 while (iter) {
3570 subtitle = ((GmtkMediaPlayerSubtitle *) (iter->data));
3571 if (subtitle->id == id && subtitle->is_file == FALSE) {
3572 if (subtitle->name != NULL) {
3573 g_free(subtitle->name);
3574 subtitle->name = NULL;
3575 }
3576 subtitle->name = g_strdup(buf);
3577 }
3578 iter = iter->next;
3579 }
3580 }
3581 if (subtitle) {
3582 if (subtitle->label != NULL) {
3583 g_free(subtitle->label);
3584 subtitle->label = NULL;
3585 }
3586 subtitle->label =
3587 g_strdup_printf("%s (%s) - %i",
3588 (subtitle->name) ? subtitle->name : g_dgettext(GETTEXT_PACKAGE, "Unknown"),
3589 subtitle->lang, subtitle->id);
3590 }
3591 }
3592
3593 if (strstr(mplayer_output->str, "ID_FILE_SUB_ID=") != 0) {
3594 buf = strstr(mplayer_output->str, "ID_FILE_SUB_ID");
3595 sscanf(buf, "ID_FILE_SUB_ID=%i", &id);
3596 subtitle = g_new0(GmtkMediaPlayerSubtitle, 1);
3597 subtitle->id = id;
3598 subtitle->is_file = TRUE;
3599 subtitle->label = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "External Subtitle #%i"), id + 1);
3600 player->subtitles = g_list_append(player->subtitles, subtitle);
3601 create_event_int(player, "subtitles-changed", g_list_length(player->subtitles));
3602 }
3603
3604 if (strstr(mplayer_output->str, "ID_AUDIO_ID=") != 0) {
3605 buf = strstr(mplayer_output->str, "ID_AUDIO_ID");
3606 sscanf(buf, "ID_AUDIO_ID=%i", &id);
3607 iter = player->audio_tracks;
3608 gboolean found = FALSE;
3609 while (iter) {
3610 audio_track = ((GmtkMediaPlayerAudioTrack *) (iter->data));
3611 if (audio_track->id == id) {
3612 found = TRUE;
3613 }
3614 iter = iter->next;
3615 }
3616
3617 if (!found) {
3618 audio_track = g_new0(GmtkMediaPlayerAudioTrack, 1);
3619 audio_track->id = id;
3620 audio_track->lang = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Unknown"));
3621 audio_track->name = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Unknown"));
3622 audio_track->label = g_strdup_printf("%s (%s) - %i", audio_track->name, audio_track->lang,
3623 audio_track->id);
3624 player->audio_tracks = g_list_append(player->audio_tracks, audio_track);
3625 }
3626 }
3627
3628 if (strstr(mplayer_output->str, "ID_AID_") != 0) {
3629 buf = strstr(mplayer_output->str, "ID_AID_");
3630 sscanf(buf, "ID_AID_%i_", &id);
3631 g_string_truncate(mplayer_output, mplayer_output->len - 1);
3632 buf = strstr(mplayer_output->str, "_LANG=");
3633 if (buf != NULL) {
3634 buf += strlen("_LANG=");
3635 iter = player->audio_tracks;
3636 gboolean updated = FALSE;
3637 while (iter) {
3638 audio_track = ((GmtkMediaPlayerAudioTrack *) (iter->data));
3639 if (audio_track->id == id) {
3640 updated = TRUE;
3641 if (audio_track->lang != NULL) {
3642 g_free(audio_track->lang);
3643 audio_track->lang = NULL;
3644 }
3645 audio_track->lang = g_strdup(buf);
3646 }
3647 iter = iter->next;
3648 }
3649 if (updated == FALSE) {
3650 audio_track = g_new0(GmtkMediaPlayerAudioTrack, 1);
3651 audio_track->id = id;
3652 audio_track->lang = g_strdup_printf("%s", buf);
3653 audio_track->name = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Unknown"));
3654 audio_track->label = g_strdup_printf("%s (%s) - %i", audio_track->name, audio_track->lang,
3655 audio_track->id);
3656 player->audio_tracks = g_list_append(player->audio_tracks, audio_track);
3657 create_event_int(player, "audio-tracks-changed", g_list_length(player->audio_tracks));
3658 }
3659 }
3660 buf = strstr(mplayer_output->str, "_NAME=");
3661 if (buf != NULL) {
3662 buf += strlen("_NAME=");
3663 iter = player->audio_tracks;
3664 while (iter) {
3665 audio_track = ((GmtkMediaPlayerAudioTrack *) (iter->data));
3666 if (audio_track->id == id) {
3667 if (audio_track->name != NULL) {
3668 g_free(audio_track->name);
3669 audio_track->name = NULL;
3670 }
3671 audio_track->name = g_strdup(buf);
3672 }
3673 iter = iter->next;
3674 }
3675 }
3676
3677 if (audio_track) {
3678 if (audio_track->label != NULL) {
3679 g_free(audio_track->label);
3680 audio_track->label = NULL;
3681 }
3682
3683 audio_track->label =
3684 g_strdup_printf("%s (%s) - %i",
3685 (audio_track->name) ? audio_track->name : g_dgettext(GETTEXT_PACKAGE, "Unknown"),
3686 audio_track->lang, audio_track->id);
3687 }
3688 }
3689
3690 if ((strstr(mplayer_output->str, "ID_CHAPTERS=") != NULL)) {
3691 buf = strstr(mplayer_output->str, "ID_CHAPTERS");
3692 sscanf(buf, "ID_CHAPTERS=%i", &player->chapters);
3693 if (player->chapters > 1) {
3694 player->has_chapters = TRUE;
3695 } else {
3696 player->has_chapters = FALSE;
3697 }
3698 create_event_int(player, "attribute-changed", ATTRIBUTE_HAS_CHAPTERS);
3699 create_event_int(player, "attribute-changed", ATTRIBUTE_CHAPTERS);
3700 }
3701
3702 if ((strstr(mplayer_output->str, "ID_SEEKABLE=") != NULL)
3703 && !(strstr(mplayer_output->str, "ID_SEEKABLE=0") != NULL)) {
3704 player->seekable = TRUE;
3705 create_event_int(player, "attribute-changed", ATTRIBUTE_SEEKABLE);
3706 }
3707
3708 if (strstr(mplayer_output->str, "ID_VIDEO_FORMAT") != 0) {
3709 g_string_truncate(mplayer_output, mplayer_output->len - 1);
3710 buf = strstr(mplayer_output->str, "ID_VIDEO_FORMAT") + strlen("ID_VIDEO_FORMAT=");
3711 if (player->video_format != NULL) {
3712 g_free(player->video_format);
3713 player->video_format = NULL;
3714 }
3715 player->video_format = g_strdup(buf);
3716 create_event_int(player, "attribute-changed", ATTRIBUTE_VIDEO_FORMAT);
3717 if (player->video_width == 0 && player->video_height == 0) {
3718 gm_log(player->debug, G_LOG_LEVEL_INFO,
3719 "Setting to minimum size so that mplayer has something to draw to");
3720 allocation.width = 32;
3721 allocation.height = 16;
3722 create_event_allocation(player, "size_allocate", &allocation);
3723 }
3724 }
3725
3726 if (strstr(mplayer_output->str, "ID_VIDEO_CODEC") != 0) {
3727 g_string_truncate(mplayer_output, mplayer_output->len - 1);
3728 buf = strstr(mplayer_output->str, "ID_VIDEO_CODEC") + strlen("ID_VIDEO_CODEC=");
3729 if (player->video_codec != NULL) {
3730 g_free(player->video_codec);
3731 player->video_codec = NULL;
3732 }
3733 player->video_codec = g_strdup(buf);
3734 create_event_int(player, "attribute-changed", ATTRIBUTE_VIDEO_CODEC);
3735 }
3736
3737 if (strstr(mplayer_output->str, "ID_VIDEO_FPS") != 0) {
3738 buf = strstr(mplayer_output->str, "ID_VIDEO_FPS");
3739 sscanf(buf, "ID_VIDEO_FPS=%lf", &player->video_fps);
3740 create_event_int(player, "attribute-changed", ATTRIBUTE_VIDEO_FPS);
3741 }
3742
3743 if (strstr(mplayer_output->str, "ID_VIDEO_BITRATE") != 0) {
3744 buf = strstr(mplayer_output->str, "ID_VIDEO_BITRATE");
3745 sscanf(buf, "ID_VIDEO_BITRATE=%i", &player->video_bitrate);
3746 create_event_int(player, "attribute-changed", ATTRIBUTE_VIDEO_BITRATE);
3747 }
3748
3749 if (strstr(mplayer_output->str, "ID_AUDIO_FORMAT") != 0) {
3750 g_string_truncate(mplayer_output, mplayer_output->len - 1);
3751 buf = strstr(mplayer_output->str, "ID_AUDIO_FORMAT") + strlen("ID_AUDIO_FORMAT=");
3752 if (player->audio_format != NULL) {
3753 g_free(player->audio_format);
3754 player->audio_format = NULL;
3755 }
3756 player->audio_format = g_strdup(buf);
3757 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_FORMAT);
3758 }
3759
3760 if (strstr(mplayer_output->str, "ID_AUDIO_CODEC") != 0) {
3761 g_string_truncate(mplayer_output, mplayer_output->len - 1);
3762 buf = strstr(mplayer_output->str, "ID_AUDIO_CODEC") + strlen("ID_AUDIO_CODEC=");
3763 if (player->audio_codec != NULL) {
3764 g_free(player->audio_codec);
3765 player->audio_codec = NULL;
3766 }
3767 player->audio_codec = g_strdup(buf);
3768 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_CODEC);
3769 }
3770
3771 if (strstr(mplayer_output->str, "ID_AUDIO_BITRATE") != 0) {
3772 buf = strstr(mplayer_output->str, "ID_AUDIO_BITRATE");
3773 sscanf(buf, "ID_AUDIO_BITRATE=%i", &player->audio_bitrate);
3774 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_BITRATE);
3775 }
3776
3777 if (strstr(mplayer_output->str, "ID_AUDIO_RATE") != 0) {
3778 buf = strstr(mplayer_output->str, "ID_AUDIO_RATE");
3779 sscanf(buf, "ID_AUDIO_RATE=%i", &player->audio_rate);
3780 g_signal_emit_by_name(player, "attribute-changed", ATTRIBUTE_AUDIO_RATE);
3781 }
3782
3783 if (strstr(mplayer_output->str, "ID_AUDIO_NCH") != 0) {
3784 buf = strstr(mplayer_output->str, "ID_AUDIO_NCH");
3785 sscanf(buf, "ID_AUDIO_NCH=%i", &player->audio_nch);
3786 create_event_int(player, "attribute-changed", ATTRIBUTE_AUDIO_NCH);
3787 }
3788
3789 if (strstr(mplayer_output->str, "*** screenshot") != 0) {
3790 buf = strstr(mplayer_output->str, "'") + 1;
3791 buf[12] = '\0';
3792 message = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "Screenshot saved to '%s'"), buf);
3793 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO,
3794 GTK_BUTTONS_OK, "%s", message);
3795 gtk_window_set_title(GTK_WINDOW(dialog), g_dgettext(GETTEXT_PACKAGE, "GNOME MPlayer Notification"));
3796 gtk_dialog_run(GTK_DIALOG(dialog));
3797 gtk_widget_destroy(dialog);
3798 g_free(message);
3799 message = NULL;
3800 }
3801
3802 if (strstr(mplayer_output->str, "failed (forgot -vf screenshot?)") != 0) {
3803 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
3804 GTK_BUTTONS_OK, g_dgettext(GETTEXT_PACKAGE, "Failed to take screenshot"));
3805 gtk_window_set_title(GTK_WINDOW(dialog), g_dgettext(GETTEXT_PACKAGE, "GNOME MPlayer Notification"));
3806 gtk_dialog_run(GTK_DIALOG(dialog));
3807 gtk_widget_destroy(dialog);
3808 }
3809
3810 if (g_regex_match(player->name_regex, mplayer_output->str, 0, NULL)
3811 && (g_strrstr(mplayer_output->str, "CPU vendor name:") == NULL)) {
3812 gm_logs(player->debug, G_LOG_LEVEL_DEBUG, "recognized movie name - updating UI etc");
3813 split = g_regex_split(player->name_regex, mplayer_output->str, 0);
3814 index = 0;
3815 while (split[index]) {
3816 if (strlen(split[index]) > 0) {
3817 if (player->title != NULL) {
3818 g_free(player->title);
3819 player->title = NULL;
3820 }
3821
3822 player->title = g_locale_to_utf8(split[index], -1, NULL, NULL, NULL);
3823 if (player->title == NULL) {
3824 player->title = g_strdup(split[index]);
3825 gm_str_strip_unicode(player->title, strlen(player->title));
3826 }
3827 player->has_metadata = TRUE;
3828 create_event_int(player, "attribute-changed", ATTRIBUTE_TITLE);
3829 }
3830 index++;
3831 }
3832 g_strfreev(split);
3833 }
3834
3835 if (g_regex_match(player->genre_regex, mplayer_output->str, 0, NULL)) {
3836 gm_logs(player->debug, G_LOG_LEVEL_DEBUG, "recognized genre - updating UI etc");
3837 split = g_regex_split(player->genre_regex, mplayer_output->str, 0);
3838 index = 0;
3839 while (split[index]) {
3840 if (strlen(split[index]) > 0) {
3841 if (player->genre != NULL) {
3842 g_free(player->genre);
3843 player->genre = NULL;
3844 }
3845
3846 player->genre = g_locale_to_utf8(split[index], -1, NULL, NULL, NULL);
3847 if (player->genre == NULL) {
3848 player->genre = g_strdup(split[index]);
3849 gm_str_strip_unicode(player->genre, strlen(player->genre));
3850 }
3851 player->has_metadata = TRUE;
3852 create_event_int(player, "attribute-changed", ATTRIBUTE_GENRE);
3853 }
3854 index++;
3855 }
3856 g_strfreev(split);
3857 }
3858
3859 if (g_regex_match(player->title_regex, mplayer_output->str, 0, NULL)) {
3860 gm_logs(player->debug, G_LOG_LEVEL_DEBUG, "recognized title - updating UI etc");
3861 split = g_regex_split(player->title_regex, mplayer_output->str, 0);
3862 index = 0;
3863 while (split[index]) {
3864 if (strlen(split[index]) > 0) {
3865 if (player->title != NULL) {
3866 g_free(player->title);
3867 player->title = NULL;
3868 }
3869
3870 player->title = g_locale_to_utf8(split[index], -1, NULL, NULL, NULL);
3871 if (player->title == NULL) {
3872 player->title = g_strdup(split[index]);
3873 gm_str_strip_unicode(player->title, strlen(player->title));
3874 }
3875 player->has_metadata = TRUE;
3876 create_event_int(player, "attribute-changed", ATTRIBUTE_TITLE);
3877 }
3878 index++;
3879 }
3880 g_strfreev(split);
3881 }
3882
3883 if (g_regex_match(player->artist_regex, mplayer_output->str, 0, NULL)) {
3884 gm_logs(player->debug, G_LOG_LEVEL_DEBUG, "recognized artist - updating UI etc");
3885 split = g_regex_split(player->artist_regex, mplayer_output->str, 0);
3886 index = 0;
3887 while (split[index]) {
3888 if (strlen(split[index]) > 0) {
3889 if (player->artist != NULL) {
3890 g_free(player->artist);
3891 player->artist = NULL;
3892 }
3893
3894 player->artist = g_locale_to_utf8(split[index], -1, NULL, NULL, NULL);
3895 if (player->artist == NULL) {
3896 player->artist = g_strdup(split[index]);
3897 gm_str_strip_unicode(player->artist, strlen(player->artist));
3898 }
3899 player->has_metadata = TRUE;
3900 create_event_int(player, "attribute-changed", ATTRIBUTE_ARTIST);
3901 }
3902 index++;
3903 }
3904 g_strfreev(split);
3905 }
3906
3907 if (g_regex_match(player->album_regex, mplayer_output->str, 0, NULL)) {
3908 gm_logs(player->debug, G_LOG_LEVEL_DEBUG, "recognized album - updating UI etc");
3909 split = g_regex_split(player->album_regex, mplayer_output->str, 0);
3910 index = 0;
3911 while (split[index]) {
3912 if (strlen(split[index]) > 0) {
3913 if (player->album != NULL) {
3914 g_free(player->album);
3915 player->album = NULL;
3916 }
3917
3918 player->album = g_locale_to_utf8(split[index], -1, NULL, NULL, NULL);
3919 if (player->album == NULL) {
3920 player->album = g_strdup(split[index]);
3921 gm_str_strip_unicode(player->album, strlen(player->album));
3922 }
3923 player->has_metadata = TRUE;
3924 create_event_int(player, "attribute-changed", ATTRIBUTE_ALBUM);
3925 }
3926 index++;
3927 }
3928 g_strfreev(split);
3929 }
3930
3931 if (player->minimum_mplayer == FALSE) {
3932 message = g_strdup_printf(g_dgettext(GETTEXT_PACKAGE, "MPlayer should be Upgraded to a Newer Version"));
3933 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO,
3934 GTK_BUTTONS_OK, "%s", message);
3935 gtk_window_set_title(GTK_WINDOW(dialog), g_dgettext(GETTEXT_PACKAGE, "GNOME MPlayer Notification"));
3936 gtk_dialog_run(GTK_DIALOG(dialog));
3937 gtk_widget_destroy(dialog);
3938 g_free(message);
3939 message = NULL;
3940 player->minimum_mplayer = TRUE;
3941 }
3942
3943 if (strstr(mplayer_output->str, "ICY Info") != NULL) {
3944 buf = strstr(mplayer_output->str, "'");
3945 if (message) {
3946 g_free(message);
3947 message = NULL;
3948 }
3949 if (buf != NULL) {
3950 for (i = 1; i < (int) strlen(buf) - 1; i++) {
3951 if (!strncmp(&buf[i], "\';", 2)) {
3952 buf[i] = '\0';
3953 break;
3954 }
3955 }
3956 if (g_ascii_strcasecmp(buf + 1, " - ") != 0) {
3957 if (g_utf8_validate(buf + 1, strlen(buf + 1), 0))
3958 message = g_markup_printf_escaped("<small>\n\t<big><b>%s</b></big>\n</small>", buf + 1);
3959 }
3960 }
3961 if (message) {
3962 // reset max values in audio meter
3963 g_free(message);
3964 message = g_markup_printf_escaped("\n\t<b>%s</b>\n", buf + 1);
3965 icy = g_strdup(buf + 1);
3966 buf = strstr(icy, " - ");
3967 title = buf + 3;
3968
3969 if (buf == NULL) {
3970 buf = strstr(icy, ":");
3971 title = buf + 1;
3972 }
3973
3974 if (buf != NULL) {
3975
3976 if (player->title)
3977 g_free(player->title);
3978 player->title = g_strdup(title);
3979 create_event_int(player, "attribute-changed", ATTRIBUTE_TITLE);
3980 buf[0] = '\0';
3981 if (player->artist)
3982 g_free(player->artist);
3983 player->artist = g_strdup(icy);
3984 create_event_int(player, "attribute-changed", ATTRIBUTE_ARTIST);
3985 if (player->album)
3986 g_free(player->album);
3987 player->album = NULL;
3988 create_event_int(player, "attribute-changed", ATTRIBUTE_ALBUM);
3989
3990 }
3991 g_free(icy);
3992 icy = NULL;
3993 g_free(message);
3994 message = NULL;
3995 }
3996 }
3997
3998 if (strstr(mplayer_output->str, "ID_FILENAME") != NULL && player->has_metadata == FALSE) {
3999 buf = g_strrstr(mplayer_output->str, ".");
4000 if (buf)
4001 buf[0] = '\0';
4002
4003 buf = g_strrstr(mplayer_output->str, "/");
4004 icy = g_strdup(buf + 1);
4005 buf = strstr(icy, " - ");
4006 title = buf + 3;
4007
4008 if (buf == NULL) {
4009 buf = strstr(icy, ":");
4010 title = buf + 1;
4011 }
4012
4013 if (buf != NULL) {
4014
4015 if (player->title)
4016 g_free(player->title);
4017 player->title = g_strdup(title);
4018 create_event_int(player, "attribute-changed", ATTRIBUTE_TITLE);
4019 buf[0] = '\0';
4020 if (player->artist)
4021 g_free(player->artist);
4022 player->artist = g_strdup(icy);
4023 create_event_int(player, "attribute-changed", ATTRIBUTE_ARTIST);
4024 if (player->album)
4025 g_free(player->album);
4026 player->album = NULL;
4027 create_event_int(player, "attribute-changed", ATTRIBUTE_ALBUM);
4028
4029 }
4030 g_free(icy);
4031 icy = NULL;
4032 g_free(message);
4033 message = NULL;
4034 }
4035
4036 if (strstr(mplayer_output->str, "ID_SIGNAL") != 0) {
4037 if (player->position == 0) {
4038 player->playback_error = ERROR_RETRY;
4039 }
4040 }
4041
4042 }
4043
4044 g_string_free(mplayer_output, TRUE);
4045 return TRUE;
4046 }
4047
4048 // this executes in the main thread
thread_query(gpointer data)4049 gboolean thread_query(gpointer data)
4050 {
4051 GmtkMediaPlayer *player = GMTK_MEDIA_PLAYER(data);
4052 gint written;
4053
4054 // gm_log(player->debug, G_LOG_LEVEL_DEBUG, "in thread_query, data = %p", data);
4055 if (player == NULL) {
4056 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "thread_query called with player == NULL");
4057 finalize_mplayer(player);
4058 return FALSE;
4059 }
4060
4061 if (player->player_state == PLAYER_STATE_RUNNING) {
4062 if (player->media_state == MEDIA_STATE_PLAY) {
4063 // gm_log(player->debug, G_LOG_LEVEL_DEBUG, "writing");
4064 if (player->use_mplayer2) {
4065 written = write(player->std_in, "get_time_pos\n", strlen("get_time_pos\n"));
4066 } else {
4067 written =
4068 write(player->std_in, "pausing_keep_force get_time_pos\n",
4069 strlen("pausing_keep_force get_time_pos\n"));
4070 }
4071 // gm_log(player->debug, G_LOG_LEVEL_DEBUG, "written = %i", written);
4072 if (written == -1) {
4073 //return TRUE;
4074 gm_log(player->debug, G_LOG_LEVEL_INFO, "thread_query, write failed");
4075 return FALSE;
4076 } else {
4077 return TRUE;
4078 }
4079 } else {
4080 return TRUE;
4081 }
4082 } else {
4083 gm_log(player->debug, G_LOG_LEVEL_DEBUG, "thread_query, player is dead");
4084 finalize_mplayer(player);
4085 return FALSE;
4086 }
4087 }
4088
write_to_mplayer(GmtkMediaPlayer * player,const gchar * cmd)4089 gboolean write_to_mplayer(GmtkMediaPlayer * player, const gchar * cmd)
4090 {
4091 GIOStatus result;
4092 gsize bytes_written;
4093 gchar *pkf_cmd;
4094
4095 /* ending \n is part of cmd */
4096 gm_logsp(player->debug, G_LOG_LEVEL_DEBUG, ">", cmd);
4097
4098 if (player->channel_in) {
4099 if (player->use_mplayer2) {
4100 pkf_cmd = g_strdup(cmd);
4101 } else {
4102 /* if cmd starts with "pause" (non case sensitive) */
4103 if (g_ascii_strncasecmp(cmd, "pause", strlen("pause")) == 0) {
4104 pkf_cmd = g_strdup(cmd);
4105 } else {
4106 pkf_cmd = g_strdup_printf("pausing_keep_force %s", cmd);
4107 }
4108 }
4109 result = g_io_channel_write_chars(player->channel_in, pkf_cmd, -1, &bytes_written, NULL);
4110 g_free(pkf_cmd);
4111 if (result != G_IO_STATUS_ERROR && bytes_written > 0) {
4112 result = g_io_channel_flush(player->channel_in, NULL);
4113 return TRUE;
4114 } else {
4115 return FALSE;
4116 }
4117 } else {
4118 return FALSE;
4119 }
4120
4121 }
4122
detect_mplayer_features(GmtkMediaPlayer * player)4123 gboolean detect_mplayer_features(GmtkMediaPlayer * player)
4124 {
4125 gchar *av[255];
4126 gint ac = 0, i;
4127 gchar **output;
4128 GError *error;
4129 gint exit_status;
4130 gchar *out = NULL;
4131 gchar *err = NULL;
4132 gboolean ret = TRUE;
4133
4134 if (player->features_detected)
4135 return ret;
4136
4137 if (player->mplayer_binary == NULL || !g_file_test(player->mplayer_binary, G_FILE_TEST_EXISTS)) {
4138 av[ac++] = g_strdup_printf("mplayer");
4139 } else {
4140 av[ac++] = g_strdup_printf("%s", player->mplayer_binary);
4141 }
4142 av[ac++] = g_strdup_printf("-noidle");
4143 av[ac++] = g_strdup_printf("-softvol");
4144 av[ac++] = g_strdup_printf("-volume");
4145 av[ac++] = g_strdup_printf("100");
4146 av[ac++] = g_strdup_printf("-nostop-xscreensaver");
4147
4148 // enable these lines to force newer mplayer
4149 //av[ac++] = g_strdup_printf("-gamma");
4150 //av[ac++] = g_strdup_printf("0");
4151
4152 av[ac] = NULL;
4153
4154 error = NULL;
4155
4156 g_spawn_sync(NULL, av, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &out, &err, &exit_status, &error);
4157
4158 for (i = 0; i < ac; i++) {
4159 g_free(av[i]);
4160 }
4161
4162 if (error != NULL) {
4163 gm_log(player->debug, G_LOG_LEVEL_MESSAGE, "Error when running: %s", error->message);
4164 g_error_free(error);
4165 error = NULL;
4166 if (out != NULL) {
4167 g_free(out);
4168 out = NULL;
4169 }
4170 if (err != NULL) {
4171 g_free(err);
4172 err = NULL;
4173 }
4174 return FALSE;
4175 }
4176 output = g_strsplit(out, "\n", 0);
4177 ac = 0;
4178 while (output[ac] != NULL) {
4179 /* if output[ac] starts with "Unknown option" (non case sensitive) */
4180 if (g_ascii_strncasecmp(output[ac], "Unknown option", strlen("Unknown option")) == 0) {
4181 ret = FALSE;
4182 }
4183 /* if output[ac] starts with "MPlayer2" (non case sensitive) */
4184 if (g_ascii_strncasecmp(output[ac], "MPlayer2", strlen("MPlayer2")) == 0) {
4185 player->use_mplayer2 = TRUE;
4186 }
4187 ac++;
4188 }
4189 g_strfreev(output);
4190 g_free(out);
4191 out = NULL;
4192 g_free(err);
4193 err = NULL;
4194
4195 player->features_detected = TRUE;
4196 if (!ret) {
4197 gm_log(player->debug, G_LOG_LEVEL_MESSAGE,
4198 g_dgettext(GETTEXT_PACKAGE, "You might want to consider upgrading mplayer to a newer version"));
4199 }
4200 return ret;
4201 }
4202