Coverage Report

Created: 2025-07-18 07:04

/src/vlc/src/posix/specific.c
Line
Count
Source
1
/*****************************************************************************
2
 * specific.c: stubs for POSIX OS-specific initialization
3
 *****************************************************************************
4
 * Copyright © 2008 Rémi Denis-Courmont
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this program; if not, write to the Free Software Foundation,
18
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19
 *****************************************************************************/
20
21
#ifdef HAVE_CONFIG_H
22
# include "config.h"
23
#endif
24
25
#include <vlc_common.h>
26
#include "../libvlc.h"
27
#include "../lib/libvlc_internal.h"
28
29
#ifdef HAVE_DBUS
30
/* used for one-instance mode */
31
# include <dbus/dbus.h>
32
# include <vlc_url.h>
33
#endif
34
35
void system_Init (void)
36
2
{
37
2
}
38
39
static void system_ConfigureDbus(libvlc_int_t *vlc, int argc,
40
                                 const char *const argv[])
41
2
{
42
/* FIXME: could be replaced by using Unix sockets */
43
#ifdef HAVE_DBUS
44
# define MPRIS_APPEND "/org/mpris/MediaPlayer2/TrackList/Append"
45
# define MPRIS_BUS_NAME "org.mpris.MediaPlayer2.vlc"
46
# define MPRIS_OBJECT_PATH "/org/mpris/MediaPlayer2"
47
# define MPRIS_TRACKLIST_INTERFACE "org.mpris.MediaPlayer2.TrackList"
48
49
    dbus_threads_init_default();
50
51
    if (var_InheritBool(vlc, "dbus"))
52
        libvlc_InternalAddIntf(vlc, "dbus,none");
53
54
    if (!var_InheritBool(vlc, "one-instance")
55
     && !(var_InheritBool(vlc, "one-instance-when-started-from-file")
56
       && var_InheritBool(vlc, "started-from-file")))
57
         return;
58
59
    for (int i = 0; i < argc; i++)
60
        if (argv[i][0] == ':')
61
        {
62
            msg_Err(vlc, "item option %s incompatible with single instance",
63
                    argv[i]);
64
            return;
65
        }
66
67
    char *name = var_GetString(vlc, "dbus-mpris-name");
68
    if (name != NULL)
69
    {
70
        bool singleton = !strcmp(name, MPRIS_BUS_NAME);
71
        free(name);
72
        if (singleton)
73
        {
74
            msg_Dbg(vlc, "no running VLC instance - continuing normally...");
75
            return; /* This is the single instance */
76
        }
77
    }
78
79
    /* Initialise D-Bus interface, check for other instances */
80
    DBusError err;
81
    dbus_error_init(&err);
82
83
    /* connect to the session bus */
84
    DBusConnection *conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
85
    if (conn == NULL)
86
    {
87
        msg_Err(vlc, "D-Bus session bus connection failure: %s",
88
                 err.message);
89
        dbus_error_free(&err);
90
        return;
91
    }
92
93
    msg_Warn(vlc, "running VLC instance - exiting...");
94
95
    const dbus_bool_t play = !var_InheritBool(vlc, "playlist-enqueue");
96
97
    for (int i = 0; i < argc; i++)
98
    {
99
        DBusMessage *req = dbus_message_new_method_call(MPRIS_BUS_NAME,
100
            MPRIS_OBJECT_PATH, MPRIS_TRACKLIST_INTERFACE, "AddTrack");
101
        if (unlikely(req == NULL))
102
            continue;
103
104
        /* We need to resolve relative paths in this instance */
105
        char *mrlbuf = NULL;
106
        const char *mrl;
107
108
        if (strstr(argv[i], "://"))
109
            mrl = argv[i];
110
        else
111
        {
112
            mrlbuf = vlc_path2uri(argv[i], NULL);
113
            if (unlikely(mrlbuf == NULL))
114
            {
115
                dbus_message_unref(req);
116
                continue;
117
            }
118
            mrl = mrlbuf;
119
        }
120
121
        /* append MRLs */
122
        msg_Dbg(vlc, "adding track %s to running instance", mrl);
123
124
        const char *after_track = MPRIS_APPEND;
125
        dbus_bool_t ok = dbus_message_append_args(req, DBUS_TYPE_STRING, &mrl,
126
                                           DBUS_TYPE_OBJECT_PATH, &after_track,
127
                                           DBUS_TYPE_BOOLEAN, &play,
128
                                           DBUS_TYPE_INVALID);
129
        free(mrlbuf);
130
        if (unlikely(!ok))
131
        {
132
             dbus_message_unref(req);
133
             continue;
134
        }
135
136
        /* send message and get a handle for a reply */
137
        DBusMessage *reply = dbus_connection_send_with_reply_and_block(conn,
138
                                                                req, -1, &err);
139
        dbus_message_unref(req);
140
        if (reply == NULL)
141
        {
142
            msg_Err(vlc, "D-Bus error: %s", err.message);
143
            dbus_error_free(&err);
144
            continue;
145
        }
146
        dbus_message_unref(reply);
147
    }
148
149
    /* we unreference the connection when we've finished with it */
150
    dbus_connection_unref(conn);
151
    exit(0);
152
#else
153
2
    (void) vlc; (void) argc; (void) argv;
154
2
#endif // HAVE_DBUS
155
2
}
156
157
void system_Configure(libvlc_int_t *libvlc,
158
                      int argc, const char *const argv[])
159
2
{
160
2
    system_ConfigureDbus(libvlc, argc, argv);
161
2
}