medialib.c 10.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*****************************************************************************
 * medialib.c: Player/Media Library interractions
 *****************************************************************************
 * Copyright © 2018-2019 VLC authors and VideoLAN
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>
#include "player.h"
#include "misc/variables.h"

void
30
vlc_player_input_RestoreMlStates(struct vlc_player_input* input, bool force_pos)
31
32
33
34
{
    vlc_player_t* player = input->player;
    vlc_player_assert_locked(player);

35
36
37
38
    int restore_pos;
    if (force_pos)
        restore_pos = VLC_PLAYER_RESTORE_PLAYBACK_POS_ALWAYS;
    else
39
40
41
        restore_pos = var_InheritInteger(input->thread, "restore-playback-pos");

    const bool restore_states = var_InheritBool(input->thread, "restore-playback-states");
42

43
44
45
    vlc_medialibrary_t* ml = vlc_ml_instance_get(input->player);
    if (!ml)
        return;
46
    input_item_t* item = input_GetItem(input->thread);
47
    vlc_ml_media_t* media = vlc_ml_get_media_by_mrl( ml, item->psz_uri);
48
    if (!media)
49
        return;
50
51
52
53
54
    if (media->i_type != VLC_ML_MEDIA_TYPE_VIDEO ||
        vlc_ml_media_get_all_playback_pref(ml, media->i_id,
                                           &input->ml.states) != VLC_SUCCESS)
    {
        vlc_ml_release(media);
55
        return;
56
57
    }

58
59
60
    input->ml.restore = (restore_pos == VLC_PLAYER_RESTORE_PLAYBACK_POS_ALWAYS) ?
                            VLC_RESTOREPOINT_TITLE : VLC_RESTOREPOINT_NONE;
    input->ml.restore_states = restore_states;
61
62
63
64
    /* If we are aiming at a specific title, wait for it to be added, and
     * only then select it & set the position.
     * If we're not aiming at a specific title, just set the position now.
     */
65
66
    if (restore_pos == VLC_PLAYER_RESTORE_PLAYBACK_POS_ALWAYS &&
            input->ml.states.current_title == -1 &&
67
68
            media->f_progress > .0f)
        input_SetPosition(input->thread, media->f_progress, false);
69
    else if (restore_pos == VLC_PLAYER_RESTORE_PLAYBACK_POS_ASK &&
70
71
             media->f_progress > .0f)
    {
72
        input->ml.delay_restore = true;
73
74
75
76
        input->ml.pos = media->f_progress;
    }

    vlc_ml_release(media);
77
78
79

    if (!restore_states)
        return;
80
81
82
    if (input->ml.states.rate != .0f)
        vlc_player_ChangeRate(player, input->ml.states.rate);

83
84
85
86
87
88
89
90
91
92
93
94
95
96

    const char *video_track_ids = input->ml.states.current_video_track;
    const char *audio_track_ids = input->ml.states.current_audio_track;
    const char *subtitle_track_ids = input->ml.states.current_subtitle_track;

    if (video_track_ids)
        vlc_player_input_SelectTracksByStringIds(input, VIDEO_ES,
                                                 video_track_ids);
    if (audio_track_ids)
        vlc_player_input_SelectTracksByStringIds(input, AUDIO_ES,
                                                 audio_track_ids);
    if (subtitle_track_ids)
        vlc_player_input_SelectTracksByStringIds(input, SPU_ES,
                                                 subtitle_track_ids);
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

    vout_thread_t* vout = vlc_player_vout_Hold(player);
    if (vout != NULL)
    {
        if (input->ml.states.zoom >= .0f)
            var_SetFloat(vout, "zoom", input->ml.states.zoom);
        else
            var_SetFloat(vout, "zoom", 1.f);
        if (input->ml.states.aspect_ratio)
            var_SetString(vout, "aspect-ratio", input->ml.states.aspect_ratio);
        else
            var_SetString(vout, "aspect-ratio", NULL);
        if (input->ml.states.deinterlace)
        {
            var_SetString(vout, "deinterlace-mode", input->ml.states.deinterlace);
            var_SetInteger(vout, "deinterlace", 1);
        }
        else
        {
            var_SetString(vout, "deinterlace-mode", NULL);
            var_SetInteger(vout, "deinterlace", 0);
        }
        if (input->ml.states.video_filter)
            var_SetString(vout, "video-filter", input->ml.states.video_filter);
        else
            var_SetString(vout, "video-filter", NULL);
        vout_Release(vout);
    }
}

127
128
129
130
131
132
static bool
vlc_player_UpdateMediaType(const struct vlc_player_input* input,
                           vlc_medialibrary_t* ml, vlc_ml_media_t* media)
{
    assert(media->i_type == VLC_ML_MEDIA_TYPE_UNKNOWN);
    vlc_ml_media_type_t media_type;
133
    if (input->ml.has_video_tracks)
134
        media_type = VLC_ML_MEDIA_TYPE_VIDEO;
135
    else if (input->ml.has_audio_tracks)
136
137
138
139
140
141
142
143
144
        media_type = VLC_ML_MEDIA_TYPE_AUDIO;
    else
        return false;
    if (vlc_ml_media_set_type(ml, media->i_id, media_type) != VLC_SUCCESS)
        return false;
    media->i_type = media_type;
    return true;
}

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
static void
vlc_player_CompareAssignState(char **target_ptr, char **input_ptr)
{
    /* We only want to save these states if they are different, and not the
     * default values (NULL), so this means that either one is NULL and the
     * other isn't, or they are both non null and differ lexicographically */

    char *target = *target_ptr;
    char *input = *input_ptr;
    if ( ( input != NULL && target != NULL &&
           strcmp(input, target ) ) ||
         ( input == NULL && target != NULL ) ||
         ( input != NULL && target == NULL ) )
    {
        free(target);
        *target_ptr = input;
        *input_ptr = NULL;
    }
    else
    {
        free(target);
        *target_ptr = NULL;
    }
}

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
void
vlc_player_UpdateMLStates(vlc_player_t *player, struct vlc_player_input* input)
{
    /* Do not save states for any secondary player. If this player's parent is
       the main vlc object, then it's the main player */
    if (player->obj.priv->parent != (vlc_object_t*)vlc_object_instance(player))
        return;

    vlc_medialibrary_t* ml = vlc_ml_instance_get(player);
    if (!ml)
        return;
    input_item_t* item = input_GetItem(input->thread);
    if (!item)
        return;
    vlc_ml_media_t* media = vlc_ml_get_media_by_mrl(ml, item->psz_uri);
    if (!media)
    {
        /* We don't know this media yet, let's add it as an external media so
         * we can still store its playback preferences
         */
        media = vlc_ml_new_external_media(ml, item->psz_uri);
        if (media == NULL)
            return;
    }

195
196
197
    if (media->i_type == VLC_ML_MEDIA_TYPE_UNKNOWN)
    {
        if (!vlc_player_UpdateMediaType(input, ml, media))
198
199
        {
            vlc_ml_release( media );
200
            return;
201
        }
202
203
204
    }
    assert(media->i_type != VLC_ML_MEDIA_TYPE_UNKNOWN);

205
206
    if ( var_GetBool( input->thread, "save-recentplay" ) )
        vlc_ml_media_update_progress( ml, media->i_id, input->position );
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

    /* If the value changed during the playback, update it in the medialibrary.
     * If not, set each state to their "unset" values, so that they aren't saved
     * in database */
    if ((input->ml.states.current_title == -1 && input->title_selected != 0) ||
         (input->ml.states.current_title != -1 &&
          input->ml.states.current_title != (int)input->title_selected))
    {
        input->ml.states.current_title = input->title_selected;
    }
    else
        input->ml.states.current_title = -1;

    /* We use .0f to signal an unsaved rate. We want to save it to the ml if it
     * changed, and if it's not the player's default value when the value was
     * never saved in the ML */
    if (input->rate != input->ml.states.rate &&
            (input->rate != 1.f || input->ml.states.rate != .0f))
        input->ml.states.rate = input->rate;
    else
        input->ml.states.rate = -1.f;

    struct vlc_player_track_priv* t;
    vout_thread_t* vout = NULL;

    vlc_vector_foreach(t, &input->video_track_vector)
    {
        if (!t->t.selected)
            continue;
        enum vlc_vout_order order;
        vout = vlc_player_GetEsIdVout(player, t->t.es_id, &order);
        if (vout != NULL && order == VLC_VOUT_ORDER_PRIMARY)
            break;
        vout = NULL;
    }
    if (vout != NULL)
    {
244
245
246
247
        char* aspect_ratio = var_GetNonEmptyString(vout, "aspect-ratio");
        char* crop = var_GetNonEmptyString(vout, "crop");
        char* deinterlace = var_GetNonEmptyString(vout, "deinterlace-mode");
        char* video_filter = var_GetNonEmptyString(vout, "video-filter");
248

249
250
251
252
253
254
255
256
257
        vlc_player_CompareAssignState(&input->ml.states.aspect_ratio, &aspect_ratio);
        vlc_player_CompareAssignState(&input->ml.states.crop, &crop);
        vlc_player_CompareAssignState(&input->ml.states.deinterlace, &deinterlace);
        vlc_player_CompareAssignState(&input->ml.states.video_filter, &video_filter);

        free(video_filter);
        free(deinterlace);
        free(crop);
        free(aspect_ratio);
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

        if (input->ml.states.deinterlace != NULL &&
            !strcmp(input->ml.states.deinterlace, "auto"))
        {
            free(input->ml.states.deinterlace);
            input->ml.states.deinterlace = NULL;
        }

        float zoom = var_GetFloat(vout, "zoom");
        if (zoom != input->ml.states.zoom &&
            (zoom != 1.f && input->ml.states.zoom >= .0f))
            input->ml.states.zoom = zoom;
        else
            input->ml.states.zoom = -1.f;
    }

274
275
276
277
278
279
    char *video_track_ids =
        vlc_player_input_GetSelectedTrackStringIds(input, VIDEO_ES);
    char *audio_track_ids =
        vlc_player_input_GetSelectedTrackStringIds(input, AUDIO_ES);
    char *subtitle_track_ids =
        vlc_player_input_GetSelectedTrackStringIds(input, SPU_ES);
280

281
282
283
    vlc_player_CompareAssignState(&input->ml.states.current_video_track, &video_track_ids);
    vlc_player_CompareAssignState(&input->ml.states.current_audio_track, &audio_track_ids);
    vlc_player_CompareAssignState(&input->ml.states.current_subtitle_track, &subtitle_track_ids);
284

285
286
287
    free(video_track_ids);
    free(audio_track_ids);
    free(subtitle_track_ids);
288
289

    vlc_ml_media_set_all_playback_states(ml, media->i_id, &input->ml.states);
290

291
292
293
    vlc_ml_release(&input->ml.states);
    vlc_ml_release(media);
}
294
295
296
297
298
299

void
vlc_player_RestorePlaybackPos(vlc_player_t *player)
{
    vlc_player_input_RestoreMlStates(player->input, true);
}