Contribs, Fribidi: allow to not build bins nor tests
[vlc.git] / src / input / thumbnailer.c
blob783eb2886b7f44c9abe8d5a314a107921456c387
1 /*****************************************************************************
2 * thumbnailer.c: Thumbnailing API
3 *****************************************************************************
4 * Copyright (C) 2018 VLC authors and VideoLAN
6 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <vlc_thumbnailer.h>
28 #include "input_internal.h"
29 #include "misc/background_worker.h"
31 struct vlc_thumbnailer_t
33 vlc_object_t* parent;
34 struct background_worker* worker;
37 typedef struct vlc_thumbnailer_params_t
39 union
41 vlc_tick_t time;
42 float pos;
44 enum
46 VLC_THUMBNAILER_SEEK_TIME,
47 VLC_THUMBNAILER_SEEK_POS,
48 } type;
49 bool fast_seek;
50 input_item_t* input_item;
51 /**
52 * A positive value will be used as the timeout duration
53 * VLC_TICK_INVALID means no timeout
55 vlc_tick_t timeout;
56 vlc_thumbnailer_cb cb;
57 void* user_data;
58 } vlc_thumbnailer_params_t;
60 struct vlc_thumbnailer_request_t
62 vlc_thumbnailer_t *thumbnailer;
63 input_thread_t *input_thread;
65 vlc_thumbnailer_params_t params;
67 vlc_mutex_t lock;
68 bool done;
71 static void
72 on_thumbnailer_input_event( input_thread_t *input,
73 const struct vlc_input_event *event, void *userdata )
75 VLC_UNUSED(input);
76 if ( event->type != INPUT_EVENT_THUMBNAIL_READY &&
77 ( event->type != INPUT_EVENT_STATE || ( event->state.value != ERROR_S &&
78 event->state.value != END_S ) ) )
79 return;
81 vlc_thumbnailer_request_t* request = userdata;
82 picture_t *pic = NULL;
84 if ( event->type == INPUT_EVENT_THUMBNAIL_READY )
87 * Stop the input thread ASAP, delegate its release to
88 * thumbnailer_request_Release
90 input_Stop( request->input_thread );
91 pic = event->thumbnail;
93 vlc_mutex_lock( &request->lock );
94 request->done = true;
96 * If the request has not been cancelled, we can invoke the completion
97 * callback.
99 if ( request->params.cb )
101 request->params.cb( request->params.user_data, pic );
102 request->params.cb = NULL;
104 vlc_mutex_unlock( &request->lock );
105 background_worker_RequestProbe( request->thumbnailer->worker );
108 static void thumbnailer_request_Hold( void* data )
110 VLC_UNUSED(data);
113 static void thumbnailer_request_Release( void* data )
115 vlc_thumbnailer_request_t* request = data;
116 if ( request->input_thread )
117 input_Close( request->input_thread );
119 input_item_Release( request->params.input_item );
120 free( request );
123 static int thumbnailer_request_Start( void* owner, void* entity, void** out )
125 vlc_thumbnailer_t* thumbnailer = owner;
126 vlc_thumbnailer_request_t* request = entity;
127 input_thread_t* input = request->input_thread =
128 input_CreateThumbnailer( thumbnailer->parent,
129 on_thumbnailer_input_event, request,
130 request->params.input_item );
131 if ( unlikely( input == NULL ) )
133 request->params.cb( request->params.user_data, NULL );
134 return VLC_EGENERIC;
136 if ( request->params.type == VLC_THUMBNAILER_SEEK_TIME )
138 input_SetTime( input, request->params.time,
139 request->params.fast_seek );
141 else
143 assert( request->params.type == VLC_THUMBNAILER_SEEK_POS );
144 input_SetPosition( input, request->params.pos,
145 request->params.fast_seek );
147 if ( input_Start( input ) != VLC_SUCCESS )
149 request->params.cb( request->params.user_data, NULL );
150 return VLC_EGENERIC;
152 *out = request;
153 return VLC_SUCCESS;
156 static void thumbnailer_request_Stop( void* owner, void* handle )
158 VLC_UNUSED(owner);
160 vlc_thumbnailer_request_t *request = handle;
161 vlc_mutex_lock( &request->lock );
163 * If the callback hasn't been invoked yet, we assume a timeout and
164 * signal it back to the user
166 if ( request->params.cb != NULL )
168 request->params.cb( request->params.user_data, NULL );
169 request->params.cb = NULL;
171 vlc_mutex_unlock( &request->lock );
172 assert( request->input_thread != NULL );
173 input_Stop( request->input_thread );
176 static int thumbnailer_request_Probe( void* owner, void* handle )
178 VLC_UNUSED(owner);
179 vlc_thumbnailer_request_t *request = handle;
180 vlc_mutex_lock( &request->lock );
181 int res = request->done;
182 vlc_mutex_unlock( &request->lock );
183 return res;
186 static vlc_thumbnailer_request_t*
187 thumbnailer_RequestCommon( vlc_thumbnailer_t* thumbnailer,
188 const vlc_thumbnailer_params_t* params )
190 vlc_thumbnailer_request_t *request = malloc( sizeof( *request ) );
191 if ( unlikely( request == NULL ) )
192 return NULL;
193 request->thumbnailer = thumbnailer;
194 request->input_thread = NULL;
195 request->params = *(vlc_thumbnailer_params_t*)params;
196 request->done = false;
197 input_item_Hold( request->params.input_item );
198 vlc_mutex_init( &request->lock );
200 int timeout = params->timeout == VLC_TICK_INVALID ?
201 0 : MS_FROM_VLC_TICK( params->timeout );
202 if ( background_worker_Push( thumbnailer->worker, request, request,
203 timeout ) != VLC_SUCCESS )
205 thumbnailer_request_Release( request );
206 return NULL;
208 return request;
211 vlc_thumbnailer_request_t*
212 vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
213 vlc_tick_t time,
214 enum vlc_thumbnailer_seek_speed speed,
215 input_item_t *input_item, vlc_tick_t timeout,
216 vlc_thumbnailer_cb cb, void* user_data )
218 return thumbnailer_RequestCommon( thumbnailer,
219 &(const vlc_thumbnailer_params_t){
220 .time = time,
221 .type = VLC_THUMBNAILER_SEEK_TIME,
222 .fast_seek = speed == VLC_THUMBNAILER_SEEK_FAST,
223 .input_item = input_item,
224 .timeout = timeout,
225 .cb = cb,
226 .user_data = user_data,
230 vlc_thumbnailer_request_t*
231 vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
232 float pos, enum vlc_thumbnailer_seek_speed speed,
233 input_item_t *input_item, vlc_tick_t timeout,
234 vlc_thumbnailer_cb cb, void* user_data )
236 return thumbnailer_RequestCommon( thumbnailer,
237 &(const vlc_thumbnailer_params_t){
238 .pos = pos,
239 .type = VLC_THUMBNAILER_SEEK_POS,
240 .fast_seek = speed == VLC_THUMBNAILER_SEEK_FAST,
241 .input_item = input_item,
242 .timeout = timeout,
243 .cb = cb,
244 .user_data = user_data,
248 void vlc_thumbnailer_Cancel( vlc_thumbnailer_t* thumbnailer,
249 vlc_thumbnailer_request_t* req )
251 vlc_mutex_lock( &req->lock );
252 /* Ensure we won't invoke the callback if the input was running. */
253 req->params.cb = NULL;
254 vlc_mutex_unlock( &req->lock );
255 background_worker_Cancel( thumbnailer->worker, req );
258 vlc_thumbnailer_t *vlc_thumbnailer_Create( vlc_object_t* parent)
260 vlc_thumbnailer_t *thumbnailer = malloc( sizeof( *thumbnailer ) );
261 if ( unlikely( thumbnailer == NULL ) )
262 return NULL;
263 thumbnailer->parent = parent;
264 struct background_worker_config cfg = {
265 .default_timeout = -1,
266 .max_threads = 1,
267 .pf_release = thumbnailer_request_Release,
268 .pf_hold = thumbnailer_request_Hold,
269 .pf_start = thumbnailer_request_Start,
270 .pf_probe = thumbnailer_request_Probe,
271 .pf_stop = thumbnailer_request_Stop,
273 thumbnailer->worker = background_worker_New( thumbnailer, &cfg );
274 if ( unlikely( thumbnailer->worker == NULL ) )
276 free( thumbnailer );
277 return NULL;
279 return thumbnailer;
282 void vlc_thumbnailer_Release( vlc_thumbnailer_t *thumbnailer )
284 background_worker_Delete( thumbnailer->worker );
285 free( thumbnailer );