gui: macos: use float for rate
[vlc.git] / src / input / thumbnailer.c
blobb1bbf2ae36b111cf72c34305193157622e856974
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 <vlc_input.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 != ERROR_S &&
78 event->state != 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 vlc_mutex_destroy( &request->lock );
121 free( request );
124 static int thumbnailer_request_Start( void* owner, void* entity, void** out )
126 vlc_thumbnailer_t* thumbnailer = owner;
127 vlc_thumbnailer_request_t* request = entity;
128 input_thread_t* input = request->input_thread =
129 input_CreateThumbnailer( thumbnailer->parent,
130 on_thumbnailer_input_event, request,
131 request->params.input_item );
132 if ( unlikely( input == NULL ) )
134 request->params.cb( request->params.user_data, NULL );
135 return VLC_EGENERIC;
137 if ( request->params.type == VLC_THUMBNAILER_SEEK_TIME )
139 input_SetTime( input, request->params.time,
140 request->params.fast_seek );
142 else
144 assert( request->params.type == VLC_THUMBNAILER_SEEK_POS );
145 input_SetPosition( input, request->params.pos,
146 request->params.fast_seek );
148 if ( input_Start( input ) != VLC_SUCCESS )
150 request->params.cb( request->params.user_data, NULL );
151 return VLC_EGENERIC;
153 *out = request;
154 return VLC_SUCCESS;
157 static void thumbnailer_request_Stop( void* owner, void* handle )
159 VLC_UNUSED(owner);
161 vlc_thumbnailer_request_t *request = handle;
162 vlc_mutex_lock( &request->lock );
164 * If the callback hasn't been invoked yet, we assume a timeout and
165 * signal it back to the user
167 if ( request->params.cb != NULL )
169 request->params.cb( request->params.user_data, NULL );
170 request->params.cb = NULL;
172 vlc_mutex_unlock( &request->lock );
173 assert( request->input_thread != NULL );
174 input_Stop( request->input_thread );
177 static int thumbnailer_request_Probe( void* owner, void* handle )
179 VLC_UNUSED(owner);
180 vlc_thumbnailer_request_t *request = handle;
181 vlc_mutex_lock( &request->lock );
182 int res = request->done;
183 vlc_mutex_unlock( &request->lock );
184 return res;
187 static vlc_thumbnailer_request_t*
188 thumbnailer_RequestCommon( vlc_thumbnailer_t* thumbnailer,
189 const vlc_thumbnailer_params_t* params )
191 vlc_thumbnailer_request_t *request = malloc( sizeof( *request ) );
192 if ( unlikely( request == NULL ) )
193 return NULL;
194 request->thumbnailer = thumbnailer;
195 request->input_thread = NULL;
196 request->params = *(vlc_thumbnailer_params_t*)params;
197 request->done = false;
198 input_item_Hold( request->params.input_item );
199 vlc_mutex_init( &request->lock );
201 int timeout = params->timeout == VLC_TICK_INVALID ?
202 0 : MS_FROM_VLC_TICK( params->timeout );
203 if ( background_worker_Push( thumbnailer->worker, request, request,
204 timeout ) != VLC_SUCCESS )
206 thumbnailer_request_Release( request );
207 return NULL;
209 return request;
212 vlc_thumbnailer_request_t*
213 vlc_thumbnailer_RequestByTime( vlc_thumbnailer_t *thumbnailer,
214 vlc_tick_t time,
215 enum vlc_thumbnailer_seek_speed speed,
216 input_item_t *input_item, vlc_tick_t timeout,
217 vlc_thumbnailer_cb cb, void* user_data )
219 return thumbnailer_RequestCommon( thumbnailer,
220 &(const vlc_thumbnailer_params_t){
221 .time = time,
222 .type = VLC_THUMBNAILER_SEEK_TIME,
223 .fast_seek = speed == VLC_THUMBNAILER_SEEK_FAST,
224 .input_item = input_item,
225 .timeout = timeout,
226 .cb = cb,
227 .user_data = user_data,
231 vlc_thumbnailer_request_t*
232 vlc_thumbnailer_RequestByPos( vlc_thumbnailer_t *thumbnailer,
233 float pos, enum vlc_thumbnailer_seek_speed speed,
234 input_item_t *input_item, vlc_tick_t timeout,
235 vlc_thumbnailer_cb cb, void* user_data )
237 return thumbnailer_RequestCommon( thumbnailer,
238 &(const vlc_thumbnailer_params_t){
239 .pos = pos,
240 .type = VLC_THUMBNAILER_SEEK_POS,
241 .fast_seek = speed == VLC_THUMBNAILER_SEEK_FAST,
242 .input_item = input_item,
243 .timeout = timeout,
244 .cb = cb,
245 .user_data = user_data,
249 void vlc_thumbnailer_Cancel( vlc_thumbnailer_t* thumbnailer,
250 vlc_thumbnailer_request_t* req )
252 vlc_mutex_lock( &req->lock );
253 /* Ensure we won't invoke the callback if the input was running. */
254 req->params.cb = NULL;
255 vlc_mutex_unlock( &req->lock );
256 background_worker_Cancel( thumbnailer->worker, req );
259 vlc_thumbnailer_t *vlc_thumbnailer_Create( vlc_object_t* parent)
261 vlc_thumbnailer_t *thumbnailer = malloc( sizeof( *thumbnailer ) );
262 if ( unlikely( thumbnailer == NULL ) )
263 return NULL;
264 thumbnailer->parent = parent;
265 struct background_worker_config cfg = {
266 .default_timeout = -1,
267 .max_threads = 1,
268 .pf_release = thumbnailer_request_Release,
269 .pf_hold = thumbnailer_request_Hold,
270 .pf_start = thumbnailer_request_Start,
271 .pf_probe = thumbnailer_request_Probe,
272 .pf_stop = thumbnailer_request_Stop,
274 thumbnailer->worker = background_worker_New( thumbnailer, &cfg );
275 if ( unlikely( thumbnailer->worker == NULL ) )
277 free( thumbnailer );
278 return NULL;
280 return thumbnailer;
283 void vlc_thumbnailer_Release( vlc_thumbnailer_t *thumbnailer )
285 background_worker_Delete( thumbnailer->worker );
286 free( thumbnailer );