Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package mpv-mpris for openSUSE:Factory checked in at 2026-01-08 15:26:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mpv-mpris (Old) and /work/SRC/openSUSE:Factory/.mpv-mpris.new.1928 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mpv-mpris" Thu Jan 8 15:26:14 2026 rev:8 rq:1325795 version:1.2 Changes: -------- --- /work/SRC/openSUSE:Factory/mpv-mpris/mpv-mpris.changes 2024-11-17 16:42:12.469747497 +0100 +++ /work/SRC/openSUSE:Factory/.mpv-mpris.new.1928/mpv-mpris.changes 2026-01-08 15:27:15.072614183 +0100 @@ -1,0 +2,15 @@ +Wed Jan 7 14:11:04 UTC 2026 - Mia Herkt <[email protected]> + +- Update to 1.2 + * More consistent external album art finding with mpv + * Use audio-client-name when naming mpv session bus + * Fix shuffle functionality + * Fix race condition at initialisation which sometimes caused + error logging + * Fix using multiple instances with flatpak by using a random + string rather than pid to identify multiple players + * Now properly report of Next and previous are available based on + current position in playlist +- Don’t create symlink in no-longer-packaged /etc/mpv directory + +------------------------------------------------------------------- Old: ---- mpv-mpris-1.1.tar.gz New: ---- mpv-mpris-1.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mpv-mpris.spec ++++++ --- /var/tmp/diff_new_pack.hMQ3D2/_old 2026-01-08 15:27:15.576635424 +0100 +++ /var/tmp/diff_new_pack.hMQ3D2/_new 2026-01-08 15:27:15.576635424 +0100 @@ -1,7 +1,7 @@ # # spec file for package mpv-mpris # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,11 +17,10 @@ Name: mpv-mpris -Version: 1.1 +Version: 1.2 Release: 0 Summary: MPRIS plugin for mpv License: MIT -Group: Productivity/Multimedia/Video/Players URL: https://github.com/hoyon/mpv-mpris Source0: https://github.com/hoyon/mpv-mpris/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz BuildRequires: dbus-1 @@ -43,16 +42,13 @@ as well as through tools like playerctl. %prep -%setup -q -%autopatch -p1 +%autosetup -p1 %build %make_build %install install -Dm0755 mpris.so %{buildroot}%{_libdir}/mpv/mpris.so -mkdir -p %{buildroot}%{_sysconfdir}/mpv/scripts -ln -s %{_libdir}/mpv/mpris.so %{buildroot}%{_sysconfdir}/mpv/scripts/mpris.so # test suite does not work on OBS VM # %%check @@ -61,6 +57,4 @@ %files %license LICENSE %{_libdir}/mpv -%dir %{_sysconfdir}/mpv/scripts -%{_sysconfdir}/mpv/scripts/mpris.so ++++++ mpv-mpris-1.1.tar.gz -> mpv-mpris-1.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpv-mpris-1.1/.github/workflows/build.yml new/mpv-mpris-1.2/.github/workflows/build.yml --- old/mpv-mpris-1.1/.github/workflows/build.yml 2023-08-30 19:19:38.000000000 +0200 +++ new/mpv-mpris-1.2/.github/workflows/build.yml 2026-01-01 23:21:19.000000000 +0100 @@ -15,14 +15,14 @@ sudo apt install libmpv-dev libglib2.0-dev libavformat-dev - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Build run: | make - name: Upload binary - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v6 with: name: mpris.so path: mpris.so diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mpv-mpris-1.1/mpris.c new/mpv-mpris-1.2/mpris.c --- old/mpv-mpris-1.1/mpris.c 2023-08-30 19:19:38.000000000 +0200 +++ new/mpv-mpris-1.2/mpris.c 2026-01-01 23:21:19.000000000 +0100 @@ -72,19 +72,26 @@ { mpv_handle *mpv; GMainLoop *loop; + GMainContext *ctx; + int wakeup_pipe[2]; gint bus_id; GDBusConnection *connection; GDBusInterfaceInfo *root_interface_info; GDBusInterfaceInfo *player_interface_info; guint root_interface_id; guint player_interface_id; + char *client_name; const char *status; const char *loop_status; + gboolean shuffle; GHashTable *changed_properties; GVariant *metadata; gboolean seek_expected; gboolean idle; gboolean paused; + gboolean events_setup; + int64_t playlist_count; + int64_t playlist_pos; } UserData; static const char *STATUS_PLAYING = "Playing"; @@ -94,6 +101,10 @@ static const char *LOOP_TRACK = "Track"; static const char *LOOP_PLAYLIST = "Playlist"; +static void setup_mpv_event_sources(UserData *ud); +static gboolean can_go_next(UserData *ud); +static gboolean can_go_previous(UserData *ud); + static gchar *string_to_utf8(gchar *maybe_utf8) { gchar *attempted_validation; @@ -156,9 +167,6 @@ static gchar *path_to_uri(mpv_handle *mpv, char *path) { -#if GLIB_CHECK_VERSION(2, 58, 0) - // version which uses g_canonicalize_filename which expands .. and . - // and makes the uris neater char* working_dir; gchar* canonical; gchar *uri; @@ -171,25 +179,6 @@ g_free(canonical); return uri; -#else - // for compatibility with older versions of glib - gchar *converted; - if (g_path_is_absolute(path)) { - converted = g_filename_to_uri(path, NULL, NULL); - } else { - char* working_dir; - gchar* absolute; - - working_dir = mpv_get_property_string(mpv, "working-directory"); - absolute = g_build_filename(working_dir, path, NULL); - converted = g_filename_to_uri(absolute, NULL, NULL); - - mpv_free(working_dir); - g_free(absolute); - } - - return converted; -#endif } static void add_metadata_uri(mpv_handle *mpv, GVariantDict *dict) @@ -215,46 +204,62 @@ mpv_free(path); } -// Copied from https://github.com/videolan/vlc/blob/master/modules/meta_engine/folder.c -static const char art_files[][20] = { - "Folder.jpg", /* Windows */ - "Folder.png", - "AlbumArtSmall.jpg", /* Windows */ - "AlbumArt.jpg", /* Windows */ - "Album.jpg", - ".folder.png", /* KDE? */ - "cover.jpg", /* rockbox */ - "cover.png", - "cover.gif", - "front.jpg", - "front.png", - "front.gif", - "front.bmp", - "thumb.jpg", -}; +static gchar* try_get_cover_art_file(mpv_handle *mpv) +{ + char *files_str = mpv_get_property_string(mpv, "cover-art-files"); + if (!files_str || files_str[0] == '\0') { + mpv_free(files_str); + return NULL; + } -static const int art_files_count = sizeof(art_files) / sizeof(art_files[0]); + // cover-art-files is a comma-separated list, use the first one + gchar **files = g_strsplit(files_str, ",", -1); + mpv_free(files_str); -static gchar* try_get_local_art(mpv_handle *mpv, char *path) -{ - gchar *dirname = g_path_get_dirname(path), *out = NULL; - gboolean found = FALSE; + gchar *out = NULL; + if (files[0] && files[0][0] != '\0') { + out = path_to_uri(mpv, files[0]); + } + + g_strfreev(files); + return out; +} - for (int i = 0; i < art_files_count; i++) { - gchar *filename = g_build_filename(dirname, art_files[i], NULL); +static gchar* try_get_folder_art(mpv_handle *mpv, char *path) +{ + gchar *out = NULL; + gchar *dirname = g_path_get_dirname(path); - if (g_file_test(filename, G_FILE_TEST_EXISTS)) { - out = path_to_uri(mpv, filename); - found = TRUE; - } + char *exts_str = mpv_get_property_string(mpv, "image-exts"); + char *names_str = mpv_get_property_string(mpv, "cover-art-whitelist"); - g_free(filename); + if (!exts_str || !names_str) { + mpv_free(exts_str); + mpv_free(names_str); + g_free(dirname); + return NULL; + } - if (found) { - break; + gchar **exts = g_strsplit(exts_str, ",", -1); + gchar **names = g_strsplit(names_str, ",", -1); + mpv_free(exts_str); + mpv_free(names_str); + + for (gchar **name = names; *name; ++name) { + for (gchar **ext = exts; *ext; ++ext) { + gchar *filename = g_strdup_printf("%s/%s.%s", dirname, *name, *ext); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) { + out = path_to_uri(mpv, filename); + g_free(filename); + goto done; + } + g_free(filename); } } +done: + g_strfreev(exts); + g_strfreev(names); g_free(dirname); return out; } @@ -286,15 +291,16 @@ } static gchar* extract_embedded_art(AVFormatContext *context) { - if (avformat_find_stream_info(context, NULL) < 0) { - g_printerr("failed to find stream info"); - return NULL; - } - AVPacket *packet = NULL; for (unsigned int i = 0; i < context->nb_streams; i++) { if (context->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { - packet = &context->streams[i]->attached_pic; + AVPacket *p = &context->streams[i]->attached_pic; + + // Skip the thumbnail if the size is bigger than 25MiB to avoid crashes + if (p->size <= 25*0x100000) { + packet = p; + break; + } } } if (!packet) { @@ -320,6 +326,23 @@ return out; } +static gchar* get_art_url(mpv_handle *mpv, char *path) +{ + gchar *url; + gboolean is_remote = g_str_has_prefix(path, "http"); + + if ((url = try_get_cover_art_file(mpv))) + return url; + if (is_remote && (url = try_get_youtube_thumbnail(path))) + return url; + if (!is_remote && (url = try_get_embedded_art(path))) + return url; + if (!is_remote && (url = try_get_folder_art(mpv, path))) + return url; + + return NULL; +} + // cached last file path, owned by mpv static char *cached_path = NULL; @@ -339,15 +362,7 @@ mpv_free(cached_path); g_free(cached_art_url); cached_path = path; - - if (g_str_has_prefix(path, "http")) { - cached_art_url = try_get_youtube_thumbnail(path); - } else { - cached_art_url = try_get_embedded_art(path); - if (!cached_art_url) { - cached_art_url = try_get_local_art(mpv, path); - } - } + cached_art_url = get_art_url(mpv, path); } else { mpv_free(path); } @@ -388,7 +403,6 @@ static GVariant *create_metadata(UserData *ud) { GVariantDict dict; - int64_t track; double duration; char *temp_str; int res; @@ -396,12 +410,11 @@ g_variant_dict_init(&dict, NULL); // mpris:trackid - mpv_get_property(ud->mpv, "playlist-pos", MPV_FORMAT_INT64, &track); - // playlist-pos < 0 if there is no playlist or current track - if (track < 0) { + // playlist_pos < 0 if there is no playlist or current track + if (ud->playlist_pos < 0) { temp_str = g_strdup("/noplaylist"); } else { - temp_str = g_strdup_printf("/%" PRId64, track); + temp_str = g_strdup_printf("/%" PRId64, ud->playlist_pos); } g_variant_dict_insert(&dict, "mpris:trackid", "o", temp_str); g_free(temp_str); @@ -412,10 +425,7 @@ g_variant_dict_insert(&dict, "mpris:length", "x", (int64_t)(duration * 1000000.0)); } - // initial value. Replaced with metadata value if available add_metadata_item_string(ud->mpv, &dict, "media-title", "xesam:title"); - - add_metadata_item_string(ud->mpv, &dict, "metadata/by-key/Title", "xesam:title"); add_metadata_item_string(ud->mpv, &dict, "metadata/by-key/Album", "xesam:album"); add_metadata_item_string(ud->mpv, &dict, "metadata/by-key/Genre", "xesam:genre"); @@ -632,16 +642,14 @@ g_free(offset_str); } else if (g_strcmp0(method_name, "SetPosition") == 0) { - int64_t current_id; char *object_path; double new_position_s; int64_t new_position_us; - mpv_get_property(ud->mpv, "playlist-pos", MPV_FORMAT_INT64, ¤t_id); g_variant_get(parameters, "(&ox)", &object_path, &new_position_us); new_position_s = ((float)new_position_us) / 1000000.0; // us -> s - if (current_id == g_ascii_strtoll(object_path + 1, NULL, 10)) { + if (ud->playlist_pos == g_ascii_strtoll(object_path + 1, NULL, 10)) { mpv_set_property(ud->mpv, "time-pos", MPV_FORMAT_DOUBLE, &new_position_s); } @@ -684,7 +692,7 @@ } else if (g_strcmp0(property_name, "Shuffle") == 0) { int shuffle; - mpv_get_property(ud->mpv, "playlist-shuffle", MPV_FORMAT_FLAG, &shuffle); + mpv_get_property(ud->mpv, "shuffle", MPV_FORMAT_FLAG, &shuffle); ret = g_variant_new_boolean(shuffle); } else if (g_strcmp0(property_name, "Metadata") == 0) { @@ -715,10 +723,10 @@ ret = g_variant_new_double(100); } else if (g_strcmp0(property_name, "CanGoNext") == 0) { - ret = g_variant_new_boolean(TRUE); + ret = g_variant_new_boolean(can_go_next(ud)); } else if (g_strcmp0(property_name, "CanGoPrevious") == 0) { - ret = g_variant_new_boolean(TRUE); + ret = g_variant_new_boolean(can_go_previous(ud)); } else if (g_strcmp0(property_name, "CanPlay") == 0) { ret = g_variant_new_boolean(TRUE); @@ -774,7 +782,14 @@ } else if (g_strcmp0(property_name, "Shuffle") == 0) { int shuffle = g_variant_get_boolean(value); - mpv_set_property(ud->mpv, "playlist-shuffle", MPV_FORMAT_FLAG, &shuffle); + if (shuffle && !ud->shuffle) { + const char *cmd[] = {"playlist-shuffle", NULL}; + mpv_command_async(ud->mpv, 0, cmd); + } else if (!shuffle && ud->shuffle) { + const char *cmd[] = {"playlist-unshuffle", NULL}; + mpv_command_async(ud->mpv, 0, cmd); + } + mpv_set_property(ud->mpv, "shuffle", MPV_FORMAT_FLAG, &shuffle); } else if (g_strcmp0(property_name, "Volume") == 0) { double volume = g_variant_get_double(value); @@ -826,6 +841,7 @@ params, &error); if (error != NULL) { g_printerr("%s", error->message); + g_clear_error(&error); } g_hash_table_remove_all(ud->changed_properties); @@ -851,9 +867,32 @@ if (error != NULL) { g_printerr("%s", error->message); + g_clear_error(&error); } } +static gboolean can_go_next(UserData *ud) +{ + if (ud->playlist_pos < 0 || ud->playlist_count <= 0) + return FALSE; + if (ud->playlist_count == 1) + return FALSE; + if (g_strcmp0(ud->loop_status, LOOP_PLAYLIST) == 0) + return TRUE; + return ud->playlist_pos < ud->playlist_count - 1; +} + +static gboolean can_go_previous(UserData *ud) +{ + if (ud->playlist_pos < 0 || ud->playlist_count <= 0) + return FALSE; + if (ud->playlist_count == 1) + return FALSE; + if (g_strcmp0(ud->loop_status, LOOP_PLAYLIST) == 0) + return TRUE; + return ud->playlist_pos > 0; +} + static GVariant * set_playback_status(UserData *ud) { if (ud->idle) { @@ -879,7 +918,7 @@ emit_property_changes(ud); } -// Register D-Bus object and interfaces +// Register D-Bus object and interfaces, then set up mpv event handlers static void on_bus_acquired(GDBusConnection *connection, G_GNUC_UNUSED const char *name, gpointer user_data) @@ -888,39 +927,84 @@ UserData *ud = user_data; ud->connection = connection; - ud->root_interface_id = - g_dbus_connection_register_object(connection, "/org/mpris/MediaPlayer2", - ud->root_interface_info, - &vtable_root, - user_data, NULL, &error); - if (error != NULL) { - g_printerr("%s", error->message); + if (ud->root_interface_id == 0) { + ud->root_interface_id = + g_dbus_connection_register_object(connection, "/org/mpris/MediaPlayer2", + ud->root_interface_info, + &vtable_root, + user_data, NULL, &error); + if (error != NULL) { + g_printerr("Failed to register root interface: %s\n", error->message); + g_clear_error(&error); + } } - ud->player_interface_id = - g_dbus_connection_register_object(connection, "/org/mpris/MediaPlayer2", - ud->player_interface_info, - &vtable_player, - user_data, NULL, &error); - if (error != NULL) { - g_printerr("%s", error->message); + if (ud->player_interface_id == 0) { + ud->player_interface_id = + g_dbus_connection_register_object(connection, "/org/mpris/MediaPlayer2", + ud->player_interface_info, + &vtable_player, + user_data, NULL, &error); + if (error != NULL) { + g_printerr("Failed to register player interface: %s\n", error->message); + g_clear_error(&error); + } } + + if (!ud->events_setup) { + setup_mpv_event_sources(ud); + ud->events_setup = TRUE; + } +} + +static char *generate_random_id(void) +{ + static const char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + const int len = 8; + + char *id = g_malloc(len + 1); + for (int i = 0; i < len; i++) { + id[i] = alpha[g_random_int_range(0, sizeof(alpha) - 1)]; + } + id[len] = '\0'; + return id; +} + +static char *build_bus_name(const char *client_name, gboolean unique_suffix) +{ + GString *name = g_string_new("org.mpris.MediaPlayer2.mpv"); + + // don't append client name if it is the default value 'mpv' + if (g_strcmp0(client_name, "mpv") != 0) { + g_string_append_printf(name, ".%s", client_name); + } + + if (unique_suffix) { + char *id = generate_random_id(); + g_string_append_printf(name, ".instance-%s", id); + g_free(id); + } + + return g_string_free(name, FALSE); } static void on_name_lost(GDBusConnection *connection, G_GNUC_UNUSED const char *_name, gpointer user_data) { + UserData *ud = user_data; + if (connection) { - UserData *ud = user_data; - pid_t pid = getpid(); - char *name = g_strdup_printf("org.mpris.MediaPlayer2.mpv.instance%d", pid); + char *name = build_bus_name(ud->client_name, TRUE); ud->bus_id = g_bus_own_name(G_BUS_TYPE_SESSION, name, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, &ud, NULL); g_free(name); + } else { + ud->root_interface_id = 0; + ud->player_interface_id = 0; } } @@ -928,6 +1012,8 @@ { const char *prop_name = NULL; GVariant *prop_value = NULL; + gboolean update_can_go_next_prev = FALSE; + if (g_strcmp0(name, "pause") == 0) { ud->paused = *(int*)data; prop_name = "PlaybackStatus"; @@ -975,6 +1061,7 @@ } prop_name = "LoopStatus"; prop_value = g_variant_new_string(ud->loop_status); + update_can_go_next_prev = TRUE; } else if (g_strcmp0(name, "loop-playlist") == 0) { char *status = *(char **)data; @@ -992,12 +1079,26 @@ } prop_name = "LoopStatus"; prop_value = g_variant_new_string(ud->loop_status); + update_can_go_next_prev = TRUE; + + } else if (g_strcmp0(name, "shuffle") == 0) { + int shuffle = *(int*)data; + ud->shuffle = shuffle; + prop_name = "Shuffle"; + prop_value = g_variant_new_boolean(shuffle); } else if (g_strcmp0(name, "fullscreen") == 0) { gboolean *status = data; prop_name = "Fullscreen"; prop_value = g_variant_new_boolean(*status); + } else if (g_strcmp0(name, "playlist-count") == 0) { + ud->playlist_count = *(int64_t *)data; + update_can_go_next_prev = TRUE; + + } else if (g_strcmp0(name, "playlist-pos") == 0) { + ud->playlist_pos = *(int64_t *)data; + update_can_go_next_prev = TRUE; } if (prop_name) { @@ -1007,6 +1108,13 @@ g_hash_table_insert(ud->changed_properties, (gpointer)prop_name, prop_value); } + + if (update_can_go_next_prev) { + g_hash_table_insert(ud->changed_properties, "CanGoNext", + g_variant_new_boolean(can_go_next(ud))); + g_hash_table_insert(ud->changed_properties, "CanGoPrevious", + g_variant_new_boolean(can_go_previous(ud))); + } } static gboolean event_handler(int fd, G_GNUC_UNUSED GIOCondition condition, gpointer data) @@ -1054,6 +1162,37 @@ (void)!write(*((int*)fd), "0", 1); } +static void setup_mpv_event_sources(UserData *ud) +{ + GError *error = NULL; + GSource *mpv_pipe_source; + GSource *timeout_source; + + g_unix_open_pipe(ud->wakeup_pipe, 0, &error); + if (error != NULL) { + g_printerr("%s", error->message); + g_clear_error(&error); + } + fcntl(ud->wakeup_pipe[0], F_SETFL, O_NONBLOCK); + mpv_set_wakeup_callback(ud->mpv, wakeup_handler, &ud->wakeup_pipe[1]); + + mpv_pipe_source = g_unix_fd_source_new(ud->wakeup_pipe[0], G_IO_IN); + g_source_set_callback(mpv_pipe_source, + G_SOURCE_FUNC(event_handler), + ud, + NULL); + g_source_attach(mpv_pipe_source, ud->ctx); + g_source_unref(mpv_pipe_source); + + timeout_source = g_timeout_source_new(100); + g_source_set_callback(timeout_source, + G_SOURCE_FUNC(emit_property_changes), + ud, + NULL); + g_source_attach(timeout_source, ud->ctx); + g_source_unref(timeout_source); +} + // Plugin entry point int mpv_open_cplugin(mpv_handle *mpv) { @@ -1062,9 +1201,6 @@ UserData ud = {0}; GError *error = NULL; GDBusNodeInfo *introspection_data = NULL; - int pipe[2]; - GSource *mpv_pipe_source; - GSource *timeout_source; ctx = g_main_context_new(); loop = g_main_loop_new(ctx, FALSE); @@ -1073,6 +1209,7 @@ introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); if (error != NULL) { g_printerr("%s", error->message); + g_clear_error(&error); } ud.root_interface_info = g_dbus_node_info_lookup_interface(introspection_data, "org.mpris.MediaPlayer2"); @@ -1081,22 +1218,29 @@ ud.mpv = mpv; ud.loop = loop; + ud.ctx = ctx; ud.status = STATUS_STOPPED; ud.loop_status = LOOP_NONE; ud.changed_properties = g_hash_table_new(g_str_hash, g_str_equal); ud.seek_expected = FALSE; ud.idle = FALSE; ud.paused = FALSE; + ud.shuffle = FALSE; + ud.client_name = mpv_get_property_string(mpv, "audio-client-name"); + mpv_get_property(mpv, "playlist-count", MPV_FORMAT_INT64, &ud.playlist_count); + mpv_get_property(mpv, "playlist-pos", MPV_FORMAT_INT64, &ud.playlist_pos); + char *bus_name = build_bus_name(ud.client_name, FALSE); g_main_context_push_thread_default(ctx); ud.bus_id = g_bus_own_name(G_BUS_TYPE_SESSION, - "org.mpris.MediaPlayer2.mpv", + bus_name, G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, on_bus_acquired, NULL, on_name_lost, &ud, NULL); g_main_context_pop_thread_default(ctx); + g_free(bus_name); // Receive event for property changes mpv_observe_property(mpv, 0, "pause", MPV_FORMAT_FLAG); @@ -1107,35 +1251,13 @@ mpv_observe_property(mpv, 0, "loop-file", MPV_FORMAT_STRING); mpv_observe_property(mpv, 0, "loop-playlist", MPV_FORMAT_STRING); mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_INT64); + mpv_observe_property(mpv, 0, "shuffle", MPV_FORMAT_FLAG); mpv_observe_property(mpv, 0, "fullscreen", MPV_FORMAT_FLAG); - - // Run callback whenever there are events - g_unix_open_pipe(pipe, 0, &error); - if (error != NULL) { - g_printerr("%s", error->message); - } - fcntl(pipe[0], F_SETFL, O_NONBLOCK); - mpv_set_wakeup_callback(mpv, wakeup_handler, &pipe[1]); - mpv_pipe_source = g_unix_fd_source_new(pipe[0], G_IO_IN); - g_source_set_callback(mpv_pipe_source, - G_SOURCE_FUNC(event_handler), - &ud, - NULL); - g_source_attach(mpv_pipe_source, ctx); - - // Emit any new property changes every 100ms - timeout_source = g_timeout_source_new(100); - g_source_set_callback(timeout_source, - G_SOURCE_FUNC(emit_property_changes), - &ud, - NULL); - g_source_attach(timeout_source, ctx); + mpv_observe_property(mpv, 0, "playlist-count", MPV_FORMAT_INT64); + mpv_observe_property(mpv, 0, "playlist-pos", MPV_FORMAT_INT64); g_main_loop_run(loop); - g_source_unref(mpv_pipe_source); - g_source_unref(timeout_source); - g_dbus_connection_unregister_object(ud.connection, ud.root_interface_id); g_dbus_connection_unregister_object(ud.connection, ud.player_interface_id); @@ -1143,6 +1265,7 @@ g_main_loop_unref(loop); g_main_context_unref(ctx); g_dbus_node_info_unref(introspection_data); + mpv_free(ud.client_name); return 0; }
