Coverage Report

Created: 2026-11-12 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/src/player/vout.c
Line
Count
Source
1
/*****************************************************************************
2
 * player_vout.c: Player vout implementation
3
 *****************************************************************************
4
 * Copyright © 2018-2019 VLC authors and VideoLAN
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 <limits.h>
26
27
#include <vlc_common.h>
28
#include "player.h"
29
#include "input/resource.h"
30
31
0
#define vlc_player_vout_SendEvent(player, event, ...) do { \
32
0
    vlc_mutex_lock(&player->vout_listeners_lock); \
33
0
    vlc_player_vout_listener_id *listener; \
34
0
    vlc_list_foreach(listener, &player->vout_listeners, node) \
35
0
    { \
36
0
        if (listener->cbs->event) \
37
0
            listener->cbs->event(__VA_ARGS__, listener->cbs_data); \
38
0
    } \
39
0
    vlc_mutex_unlock(&player->vout_listeners_lock); \
40
0
} while(0)
41
42
vout_thread_t *
43
vlc_player_vout_Hold(vlc_player_t *player)
44
0
{
45
0
    vout_thread_t *vout = input_resource_HoldVout(player->resource);
46
0
    return vout ? vout : input_resource_HoldDummyVout(player->resource);
47
0
}
48
49
vout_thread_t **
50
vlc_player_vout_HoldAll(vlc_player_t *player, size_t *count)
51
0
{
52
0
    vout_thread_t **vouts;
53
0
    input_resource_HoldVouts(player->resource, &vouts, count);
54
55
0
    if (*count == 0)
56
0
    {
57
0
        vouts = vlc_alloc(1, sizeof(*vouts));
58
0
        if (vouts)
59
0
        {
60
0
            *count = 1;
61
0
            vouts[0] = input_resource_HoldDummyVout(player->resource);
62
0
        }
63
0
    }
64
0
    return vouts;
65
0
}
66
67
vlc_player_vout_listener_id *
68
vlc_player_vout_AddListener(vlc_player_t *player,
69
                            const struct vlc_player_vout_cbs *cbs,
70
                            void *cbs_data)
71
0
{
72
0
    assert(cbs);
73
74
0
    vlc_player_vout_listener_id *listener = malloc(sizeof(*listener));
75
0
    if (!listener)
76
0
        return NULL;
77
78
0
    listener->cbs = cbs;
79
0
    listener->cbs_data = cbs_data;
80
81
0
    vlc_mutex_lock(&player->vout_listeners_lock);
82
0
    vlc_list_append(&listener->node, &player->vout_listeners);
83
0
    vlc_mutex_unlock(&player->vout_listeners_lock);
84
85
0
    return listener;
86
0
}
87
88
void
89
vlc_player_vout_RemoveListener(vlc_player_t *player,
90
                               vlc_player_vout_listener_id *id)
91
0
{
92
0
    assert(id);
93
94
0
    vlc_mutex_lock(&player->vout_listeners_lock);
95
0
    vlc_list_remove(&id->node);
96
0
    vlc_mutex_unlock(&player->vout_listeners_lock);
97
0
    free(id);
98
0
}
99
100
bool
101
vlc_player_vout_IsFullscreen(vlc_player_t *player)
102
0
{
103
0
    vout_thread_t *vout = vlc_player_vout_Hold(player);
104
0
    bool fs =  var_GetBool(vout, "fullscreen");
105
0
    vout_Release(vout);
106
0
    return fs;
107
0
}
108
109
static int
110
vlc_player_VoutCallback(vlc_object_t *this, const char *var,
111
                        vlc_value_t oldval, vlc_value_t newval, void *data)
112
0
{
113
0
    vlc_player_t *player = data;
114
115
0
    if (strcmp(var, "fullscreen") == 0)
116
0
    {
117
0
        if (oldval.b_bool != newval.b_bool )
118
0
            vlc_player_vout_SendEvent(player, on_fullscreen_changed,
119
0
                                      (vout_thread_t *)this, newval.b_bool);
120
0
    }
121
0
    else if (strcmp(var, "video-wallpaper") == 0)
122
0
    {
123
0
        if (oldval.b_bool != newval.b_bool )
124
0
            vlc_player_vout_SendEvent(player, on_wallpaper_mode_changed,
125
0
                                      (vout_thread_t *)this, newval.b_bool);
126
0
    }
127
0
    else
128
0
        vlc_assert_unreachable();
129
130
0
    return VLC_SUCCESS;
131
0
}
132
133
static const char osd_vars[][sizeof("secondary-sub-margin")] = {
134
    "aspect-ratio", "autoscale", "crop", "crop-bottom",
135
    "crop-top", "crop-left", "crop-right", "deinterlace",
136
    "deinterlace-mode", "sub-margin", "secondary-sub-margin", "zoom"
137
};
138
139
void
140
vlc_player_vout_AddCallbacks(vlc_player_t *player, vout_thread_t *vout)
141
0
{
142
0
    var_AddCallback(vout, "fullscreen", vlc_player_VoutCallback, player);
143
0
    var_AddCallback(vout, "video-wallpaper", vlc_player_VoutCallback, player);
144
145
0
    for (size_t i = 0; i < ARRAY_SIZE(osd_vars); ++i)
146
0
        var_AddCallback(vout, osd_vars[i], vlc_player_vout_OSDCallback, player);
147
0
}
148
149
void
150
vlc_player_vout_DelCallbacks(vlc_player_t *player, vout_thread_t *vout)
151
0
{
152
0
    var_DelCallback(vout, "fullscreen", vlc_player_VoutCallback, player);
153
0
    var_DelCallback(vout, "video-wallpaper", vlc_player_VoutCallback, player);
154
155
0
    for (size_t i = 0; i < ARRAY_SIZE(osd_vars); ++i)
156
0
        var_DelCallback(vout, osd_vars[i], vlc_player_vout_OSDCallback, player);
157
0
}
158
159
static void
160
vlc_player_vout_SetVar(vlc_player_t *player, const char *name, int type,
161
                       vlc_value_t val)
162
0
{
163
0
    vout_thread_t *vout = vlc_player_vout_Hold(player);
164
0
    var_SetChecked(vout, name, type, val);
165
0
    vout_Release(vout);
166
0
}
167
168
169
static void
170
vlc_player_vout_TriggerOption(vlc_player_t *player, const char *option)
171
0
{
172
    /* Don't use vlc_player_vout_Hold() since there is nothing to trigger if it
173
     * returns a dummy vout */
174
0
    vout_thread_t *vout = input_resource_HoldVout(player->resource);
175
0
    if (vout == NULL)
176
0
        return;
177
0
    var_TriggerCallback(vout, option);
178
0
    vout_Release(vout);
179
0
}
180
181
182
void
183
vlc_player_vout_SetFullscreen(vlc_player_t *player, bool enabled)
184
0
{
185
0
    vlc_player_vout_SetVar(player, "fullscreen", VLC_VAR_BOOL,
186
0
                           (vlc_value_t) { .b_bool = enabled });
187
0
    vlc_player_vout_SendEvent(player, on_fullscreen_changed, NULL, enabled);
188
0
}
189
190
bool
191
vlc_player_vout_IsWallpaperModeEnabled(vlc_player_t *player)
192
0
{
193
0
    vout_thread_t *vout = vlc_player_vout_Hold(player);
194
0
    bool wm =  var_GetBool(vout, "video-wallpaper");
195
0
    vout_Release(vout);
196
0
    return wm;
197
0
}
198
199
void
200
vlc_player_vout_SetWallpaperModeEnabled(vlc_player_t *player, bool enabled)
201
0
{
202
0
    vlc_player_vout_SetVar(player, "video-wallpaper", VLC_VAR_BOOL,
203
0
                           (vlc_value_t) { .b_bool = enabled });
204
0
    vlc_player_vout_SendEvent(player, on_wallpaper_mode_changed, NULL, enabled);
205
0
}
206
207
void
208
vlc_player_vout_Snapshot(vlc_player_t *player)
209
0
{
210
0
    vlc_player_vout_TriggerOption(player, "video-snapshot");
211
0
}