static gboolean vid_area_render_handler( GtkGLArea *area, GdkGLContext *context, gpointer data ) { gmpv_handle *ctx = data; int width; int height; int fbo; if(!ctx->opengl_ready) { mpv_check_error(mpv_opengl_cb_init_gl( ctx->opengl_ctx, NULL, get_proc_address, NULL )); ctx->opengl_ready = TRUE; } width = gtk_widget_get_allocated_width(GTK_WIDGET(area)); height = (-1)*gtk_widget_get_allocated_height(GTK_WIDGET(area)); fbo = -1; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo); mpv_opengl_cb_draw(ctx->opengl_ctx, fbo, width, height); return TRUE; }
void remove_current_playlist_entry(gmpv_handle *ctx) { const gchar *cmd[] = {"playlist_remove", NULL, NULL}; PlaylistWidget *playlist; GtkTreePath *path; playlist = PLAYLIST_WIDGET(ctx->gui->playlist); gtk_tree_view_get_cursor ( GTK_TREE_VIEW(playlist->tree_view), &path, NULL ); if(path) { gint index; gchar *index_str; index = gtk_tree_path_get_indices(path)[0]; index_str = g_strdup_printf("%d", index); cmd[1] = index_str; g_signal_handlers_block_matched ( playlist->list_store, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, ctx ); playlist_widget_remove(playlist, index); if(ctx->loaded) { mpv_check_error(mpv_command(ctx->mpv_ctx, cmd)); } if(playlist_widget_empty(playlist)) { control_box_set_enabled (CONTROL_BOX(ctx->gui->control_box), FALSE); } g_signal_handlers_unblock_matched ( playlist->list_store, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, ctx ); g_free(index_str); } }
void gmpv_mpv_opt_handle_msg_level(GmpvMpv *mpv) { const struct { gchar *name; mpv_log_level level; } level_map[] = { {"no", MPV_LOG_LEVEL_NONE}, {"fatal", MPV_LOG_LEVEL_FATAL}, {"error", MPV_LOG_LEVEL_ERROR}, {"warn", MPV_LOG_LEVEL_WARN}, {"info", MPV_LOG_LEVEL_INFO}, {"v", MPV_LOG_LEVEL_V}, {"debug", MPV_LOG_LEVEL_DEBUG}, {"trace", MPV_LOG_LEVEL_TRACE}, {NULL, MPV_LOG_LEVEL_NONE} }; gchar *optbuf = NULL; gchar **tokens = NULL; mpv_log_level min_level = DEFAULT_LOG_LEVEL; gint i; optbuf = mpv_get_property_string(mpv->mpv_ctx, "options/msg-level"); if(optbuf) { tokens = g_strsplit(optbuf, ",", 0); } if(mpv->log_level_list) { g_slist_free_full(mpv->log_level_list, g_free); mpv->log_level_list = NULL; } for(i = 0; tokens && tokens[i]; i++) { gchar **pair = g_strsplit(tokens[i], "=", 2); module_log_level *level = g_malloc(sizeof(module_log_level)); gboolean found = FALSE; gint j; level->prefix = g_strdup(pair[0]); for(j = 0; level_map[j].name && !found; j++) { if(g_strcmp0(pair[1], level_map[j].name) == 0) { level->level = level_map[j].level; found = TRUE; } } /* Ignore if the given level is invalid */ if(found) { /* Lower log levels have higher values */ if(level->level > min_level) { min_level = level->level; } if(g_strcmp0(level->prefix, "all") != 0) { mpv->log_level_list = g_slist_append (mpv->log_level_list, level); } } g_strfreev(pair); } for(i = 0; level_map[i].level != min_level; i++); mpv_check_error (mpv_request_log_messages(mpv->mpv_ctx, level_map[i].name)); mpv_free(optbuf); g_strfreev(tokens); }
void gmpv_mpv_obj_initialize(GmpvMpvObj *mpv) { GSettings *main_settings = g_settings_new(CONFIG_ROOT); gchar *config_dir = get_config_dir_path(); gchar *mpvopt = NULL; gchar *current_vo = NULL; gchar *mpv_version = NULL; const struct { const gchar *name; const gchar *value; } options[] = { {"osd-level", "1"}, {"softvol", "yes"}, {"force-window", "yes"}, {"input-default-bindings", "yes"}, {"audio-client-name", ICON_NAME}, {"title", "${media-title}"}, {"autofit-larger", "75%"}, {"window-scale", "1"}, {"pause", "no"}, {"ytdl", "yes"}, {"osd-bar", "no"}, {"input-cursor", "no"}, {"cursor-autohide", "no"}, {"softvol-max", "100"}, {"config", "yes"}, {"screenshot-template", "gnome-mpv-shot%n"}, {"config-dir", config_dir}, {NULL, NULL} }; g_assert(mpv->mpv_ctx); for(gint i = 0; options[i].name; i++) { g_debug( "Applying default option --%s=%s", options[i].name, options[i].value ); mpv_set_option_string( mpv->mpv_ctx, options[i].name, options[i].value ); } if(g_settings_get_boolean(main_settings, "mpv-config-enable")) { gchar *mpv_conf = g_settings_get_string (main_settings, "mpv-config-file"); g_info("Loading config file: %s", mpv_conf); mpv_load_config_file(mpv->mpv_ctx, mpv_conf); g_free(mpv_conf); } if(g_settings_get_boolean(main_settings, "mpv-input-config-enable")) { gchar *input_conf = g_settings_get_string (main_settings, "mpv-input-config-file"); g_info("Loading input config file: %s", input_conf); load_input_conf(mpv, input_conf); g_free(input_conf); } else { load_input_conf(mpv, NULL); } mpvopt = g_settings_get_string(main_settings, "mpv-options"); g_debug("Applying extra mpv options: %s", mpvopt); /* Apply extra options */ if(mpv_obj_apply_args(mpv->mpv_ctx, mpvopt) < 0) { const gchar *msg = _("Failed to apply one or more MPV options."); g_signal_emit_by_name(mpv, "mpv-error", msg); } if(mpv->force_opengl) { g_info("Forcing --vo=opengl-cb"); mpv_set_option_string(mpv->mpv_ctx, "vo", "opengl-cb"); } else { g_debug( "Attaching mpv window to wid %#x", (guint)mpv->wid ); mpv_set_option(mpv->mpv_ctx, "wid", MPV_FORMAT_INT64, &mpv->wid); } mpv_observe_property(mpv->mpv_ctx, 0, "aid", MPV_FORMAT_INT64); mpv_observe_property(mpv->mpv_ctx, 0, "chapters", MPV_FORMAT_INT64); mpv_observe_property(mpv->mpv_ctx, 0, "core-idle", MPV_FORMAT_FLAG); mpv_observe_property(mpv->mpv_ctx, 0, "fullscreen", MPV_FORMAT_FLAG); mpv_observe_property(mpv->mpv_ctx, 0, "pause", MPV_FORMAT_FLAG); mpv_observe_property(mpv->mpv_ctx, 0, "length", MPV_FORMAT_DOUBLE); mpv_observe_property(mpv->mpv_ctx, 0, "media-title", MPV_FORMAT_STRING); mpv_observe_property(mpv->mpv_ctx, 0, "playlist-pos", MPV_FORMAT_INT64); mpv_observe_property(mpv->mpv_ctx, 0, "track-list", MPV_FORMAT_NODE); mpv_observe_property(mpv->mpv_ctx, 0, "volume", MPV_FORMAT_DOUBLE); mpv_set_wakeup_callback(mpv->mpv_ctx, wakeup_callback, mpv); mpv_check_error(mpv_initialize(mpv->mpv_ctx)); mpv_version = gmpv_mpv_obj_get_property_string(mpv, "mpv-version"); current_vo = gmpv_mpv_obj_get_property_string(mpv, "current-vo"); g_info("Using %s", mpv_version); if(current_vo && !GDK_IS_X11_DISPLAY(gdk_display_get_default())) { g_info( "The chosen vo is %s but the display is not X11; " "forcing --vo=opengl-cb and resetting", current_vo ); mpv->force_opengl = TRUE; mpv->state.paused = FALSE; gmpv_mpv_obj_reset(mpv); } else { GSettings *win_settings; gdouble volume; win_settings = g_settings_new(CONFIG_WIN_STATE); volume = g_settings_get_double(win_settings, "volume")*100; g_debug("Setting volume to %f", volume); mpv_set_property( mpv->mpv_ctx, "volume", MPV_FORMAT_DOUBLE, &volume ); /* The vo should be opengl-cb if current_vo is NULL*/ if(!current_vo) { mpv->opengl_ctx = mpv_get_sub_api ( mpv->mpv_ctx, MPV_SUB_API_OPENGL_CB ); } gmpv_mpv_opt_handle_msg_level(mpv); gmpv_mpv_opt_handle_fs(mpv); gmpv_mpv_opt_handle_geometry(mpv); mpv->force_opengl = FALSE; mpv->state.ready = TRUE; g_signal_emit_by_name(mpv, "mpv-init"); g_clear_object(&win_settings); } g_clear_object(&main_settings); g_free(config_dir); g_free(mpvopt); mpv_free(current_vo); mpv_free(mpv_version); }
static void mpv_obj_update_playlist(GmpvMpvObj *mpv) { /* The length of "playlist//filename" including null-terminator (19) * plus the number of digits in the maximum value of 64 bit int (19). */ const gsize filename_prop_str_size = 38; GtkListStore *store = gmpv_playlist_get_store(mpv->playlist); gchar *filename_prop_str = g_malloc(filename_prop_str_size); gboolean iter_end = FALSE; GtkTreeIter iter; mpv_node mpv_playlist; gint playlist_count; gint i; mpv_check_error(mpv_get_property( mpv->mpv_ctx, "playlist", MPV_FORMAT_NODE, &mpv_playlist )); playlist_count = mpv_playlist.u.list->num; gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); for(i = 0; i < playlist_count; i++) { mpv_node_list *prop_list = mpv_playlist.u.list->values[i].u.list; gchar *uri = NULL; gchar *title = NULL; gchar *name = NULL; for(gint j = 0; j < prop_list->num; j++) { const gchar *key = prop_list->keys[j]; const mpv_node value = prop_list->values[j]; if(g_strcmp0(key, "filename") == 0) { g_assert(value.format == MPV_FORMAT_STRING); uri = value.u.string; } else if(g_strcmp0(key, "title") == 0) { g_assert(value.format == MPV_FORMAT_STRING); title = value.u.string; } } name = title?g_strdup(title):get_name_from_path(uri); /* Overwrite current entry if it doesn't match the new value */ if(!iter_end) { gchar *old_name = NULL; gchar *old_uri = NULL; gboolean name_update; gboolean uri_update; gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, PLAYLIST_NAME_COLUMN, &old_name, PLAYLIST_URI_COLUMN, &old_uri, -1 ); name_update = (g_strcmp0(name, old_name) != 0); uri_update = (g_strcmp0(uri, old_uri) != 0); /* Only set the name if either the title can be * retrieved or the name is unset. This preserves the * correct title if it becomes unavailable later such as * when restarting mpv. */ if(name_update && (!old_name || title || uri_update)) { gtk_list_store_set ( store, &iter, PLAYLIST_NAME_COLUMN, name, -1 ); } if(uri_update) { gtk_list_store_set ( store, &iter, PLAYLIST_URI_COLUMN, uri, -1 ); } iter_end = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter); g_free(old_name); g_free(old_uri); } /* Append entries to the playlist if there are fewer entries in * the playlist widget than mpv's playlist. */ else { gmpv_playlist_append(mpv->playlist, name, uri); } g_free(name); } /* If there are more entries in the playlist widget than mpv's playlist, * remove the excess entries from the playlist widget. */ if(!iter_end) { while(gtk_list_store_remove(store, &iter)); } g_free(filename_prop_str); mpv_free_node_contents(&mpv_playlist); }
void gmpv_mpv_obj_load( GmpvMpvObj *mpv, const gchar *uri, gboolean append, gboolean update ) { const gchar *load_cmd[] = {"loadfile", NULL, NULL, NULL}; GtkListStore *playlist_store = gmpv_playlist_get_store(mpv->playlist); GtkTreeIter iter; gboolean empty; g_info( "Loading file (append=%s, update=%s): %s", append?"TRUE":"FALSE", update?"TRUE":"FALSE", uri?:"<PLAYLIST_ITEMS>" ); empty = !gtk_tree_model_get_iter_first (GTK_TREE_MODEL(playlist_store), &iter); load_cmd[2] = (append && !empty)?"append":"replace"; if(!append && uri && update) { gmpv_playlist_clear(mpv->playlist); mpv->state.new_file = TRUE; mpv->state.loaded = FALSE; } if(!uri) { gboolean append = FALSE; gboolean rc; if(!mpv->state.init_load) { gmpv_mpv_obj_set_property_flag(mpv, "pause", FALSE); } rc = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(playlist_store), &iter); while(rc) { gchar *uri; gtk_tree_model_get( GTK_TREE_MODEL(playlist_store), &iter, PLAYLIST_URI_COLUMN, &uri, -1 ); /* append = FALSE only on first iteration */ gmpv_mpv_obj_load(mpv, uri, append, FALSE); append = TRUE; rc = gtk_tree_model_iter_next (GTK_TREE_MODEL(playlist_store), &iter); g_free(uri); } } if(uri && playlist_store) { gchar *path = get_path_from_uri(uri); load_cmd[1] = path; if(!append) { mpv->state.loaded = FALSE; if(!mpv->state.init_load) { gmpv_mpv_obj_set_property_flag (mpv, "pause", FALSE); } } if(update) { gchar *name = get_name_from_path(path); gmpv_playlist_append(mpv->playlist, name, uri); g_free(name); } g_assert(mpv->mpv_ctx); mpv_check_error(mpv_request_event( mpv->mpv_ctx, MPV_EVENT_END_FILE, 0 )); mpv_check_error(mpv_command(mpv->mpv_ctx, load_cmd)); mpv_check_error(mpv_request_event( mpv->mpv_ctx, MPV_EVENT_END_FILE, 1 )); g_free(path); } }
void gmpv_mpv_obj_reset(GmpvMpvObj *mpv) { const gchar *quit_cmd[] = {"quit_watch_later", NULL}; gchar *loop_str; gboolean loop; gint64 playlist_pos; gint playlist_pos_rc; g_assert(mpv->mpv_ctx); loop_str = gmpv_mpv_obj_get_property_string(mpv, "loop"); loop = (g_strcmp0(loop_str, "inf") == 0); mpv_free(loop_str); playlist_pos_rc = mpv_get_property( mpv->mpv_ctx, "playlist-pos", MPV_FORMAT_INT64, &playlist_pos ); /* Reset mpv->mpv_ctx */ mpv->state.ready = FALSE; mpv_check_error(gmpv_mpv_obj_command(mpv, quit_cmd)); gmpv_mpv_obj_quit(mpv); mpv->mpv_ctx = mpv_create(); gmpv_mpv_obj_initialize(mpv); gmpv_mpv_obj_set_event_callback ( mpv, mpv->event_callback, mpv->event_callback_data ); gmpv_mpv_obj_set_opengl_cb_callback ( mpv, mpv->opengl_cb_callback, mpv->opengl_cb_callback_data ); gmpv_mpv_obj_set_property_string(mpv, "loop", loop?"inf":"no"); if(mpv->playlist) { if(mpv->state.loaded) { gint rc; rc = mpv_request_event (mpv->mpv_ctx, MPV_EVENT_FILE_LOADED, 0); mpv_check_error(rc); gmpv_mpv_obj_load(mpv, NULL, FALSE, TRUE); rc = mpv_request_event (mpv->mpv_ctx, MPV_EVENT_FILE_LOADED, 1); mpv_check_error(rc); } if(playlist_pos_rc >= 0 && playlist_pos > 0) { gmpv_mpv_obj_set_property( mpv, "playlist-pos", MPV_FORMAT_INT64, &playlist_pos ); } gmpv_mpv_obj_set_property( mpv, "pause", MPV_FORMAT_FLAG, &mpv->state.paused ); } }