1 /* Copyright Rafaël Carré (licence WTFPL) */
2 /* A video thumbnailer compatible with nautilus */
3 /* Copyright © 2007-2011 Rafaël Carré <funman@videolanorg> */
5 /* Works with : libvlc 2.0.0
6 gcc -pedantic -Wall -Werror -Wextra `pkg-config --cflags --libs libvlc` -lpthread
8 # to register the thumbnailer on gnome 3.x:
9 cp vlc-thumb.thumbnailer /usr/share/thumbnailers
11 # to register the thumbnailer on gnome 2.x:
12 list=`grep ^Mime vlc.desktop|cut -d= -f2-|sed -e s/";"/\\\n/g -e s,/,@,g`
13 vid=`echo $mimes|grep ^vid`
16 key=/desktop/gnome/thumbnailers/$i/enable
17 gconftool-2 -t boolean -s $key true
18 gconftool-2 -t string -s $key "vlc-thumb -s %s %u %o"
32 #if !defined (_POSIX_CLOCK_SELECTION)
33 # define _POSIX_CLOCK_SELECTION (-1)
36 #if (_POSIX_CLOCK_SELECTION < 0)
37 # error Clock selection is not available!
42 /* position at which the snapshot is taken */
43 #define VLC_THUMBNAIL_POSITION (30./100.)
45 static void usage(const char *name
, int ret
)
47 fprintf(stderr
, "Usage: %s [-s width] <video> <output.png>\n", name
);
51 /* extracts options from command line */
52 static void cmdline(int argc
, const char **argv
, const char **in
,
53 char **out
, char **out_with_ext
, int *w
)
58 if (argc
!= 3 && argc
!= 5)
59 usage(argv
[0], argc
!= 2 || strcmp(argv
[1], "-h"));
64 if (strcmp(argv
[1], "-s"))
67 idx
+= 2; /* skip "-s width" */
72 *out
= strdup(argv
[idx
++]);
77 if (len
>= 4 && !strcmp(*out
+ len
- 4, ".png")) {
82 /* We need to add .png extension to filename,
83 * VLC relies on it to detect output format,
84 * and nautilus doesn't give filenames ending in .png */
86 *out_with_ext
= malloc(len
+ sizeof ".png");
89 strcpy(*out_with_ext
, *out
);
90 strcat(*out_with_ext
, ".png");
93 static libvlc_instance_t
*create_libvlc(void)
95 static const char* const args
[] = {
96 "--intf", "dummy", /* no interface */
97 "--vout", "dummy", /* we don't want video (output) */
98 "--no-audio", /* we don't want audio (decoding) */
99 "--no-video-title-show", /* nor the filename displayed */
100 "--no-stats", /* no stats */
101 "--no-sub-autodetect-file", /* we don't want subtitles */
102 "--no-inhibit", /* we don't want interfaces */
103 "--no-disable-screensaver", /* we don't want interfaces */
104 "--no-snapshot-preview", /* no blending in dummy vout */
106 "--verbose=2", /* full log */
110 return libvlc_new(sizeof args
/ sizeof *args
, args
);
113 static pthread_mutex_t lock
= PTHREAD_MUTEX_INITIALIZER
;
114 static pthread_cond_t wait
;
117 static void callback(const libvlc_event_t
*ev
, void *param
)
122 pthread_mutex_lock(&lock
);
124 case libvlc_MediaPlayerPositionChanged
:
125 new_position
= ev
->u
.media_player_position_changed
.new_position
;
126 if (new_position
< VLC_THUMBNAIL_POSITION
* .9 /* 90% margin */)
128 case libvlc_MediaPlayerSnapshotTaken
:
130 pthread_cond_signal(&wait
);
136 pthread_mutex_unlock(&lock
);
139 static void event_wait(const char *error
)
143 #define VLC_THUMBNAIL_TIMEOUT 5.0 /* 5 secs */
145 clock_gettime(CLOCK_MONOTONIC
, &ts
);
146 ts
.tv_sec
+= VLC_THUMBNAIL_TIMEOUT
;
147 pthread_mutex_lock(&lock
);
148 ret
= done
? 0 : pthread_cond_timedwait(&wait
, &lock
, &ts
);
149 pthread_mutex_unlock(&lock
);
151 assert(!ret
|| ret
== ETIMEDOUT
);
155 "%s (timeout after %.2f secs!\n", error
, VLC_THUMBNAIL_TIMEOUT
);
160 static void set_position(libvlc_media_player_t
*mp
)
162 libvlc_event_manager_t
*em
= libvlc_media_player_event_manager(mp
);
165 libvlc_event_attach(em
, libvlc_MediaPlayerPositionChanged
, callback
, NULL
);
167 libvlc_media_player_set_position(mp
, VLC_THUMBNAIL_POSITION
);
168 event_wait("Couldn't set position");
169 libvlc_event_detach(em
, libvlc_MediaPlayerPositionChanged
, callback
, NULL
);
172 static void snapshot(libvlc_media_player_t
*mp
, int width
, char *out_with_ext
)
174 libvlc_event_manager_t
*em
= libvlc_media_player_event_manager(mp
);
177 libvlc_event_attach(em
, libvlc_MediaPlayerSnapshotTaken
, callback
, NULL
);
179 libvlc_video_take_snapshot(mp
, 0, out_with_ext
, width
, 0);
180 event_wait("Snapshot has not been written");
181 libvlc_event_detach(em
, libvlc_MediaPlayerSnapshotTaken
, callback
, NULL
);
184 int main(int argc
, const char **argv
)
187 char *out
, *out_with_ext
;
189 pthread_condattr_t attr
;
190 libvlc_instance_t
*libvlc
;
191 libvlc_media_player_t
*mp
;
194 /* mandatory to support UTF-8 filenames (provided the locale is well set)*/
195 setlocale(LC_ALL
, "");
197 cmdline(argc
, argv
, &in
, &out
, &out_with_ext
, &width
);
199 pthread_condattr_init(&attr
);
200 pthread_condattr_setclock(&attr
, CLOCK_MONOTONIC
);
201 pthread_cond_init(&wait
, &attr
);
202 pthread_condattr_destroy(&attr
);
205 libvlc
= create_libvlc();
208 m
= libvlc_media_new_path(libvlc
, in
);
211 mp
= libvlc_media_player_new_from_media(m
);
214 libvlc_media_player_play(mp
);
218 snapshot(mp
, width
, out_with_ext
);
220 libvlc_media_player_stop(mp
);
223 if (out
!= out_with_ext
) {
224 rename(out_with_ext
, out
);
229 libvlc_media_player_release(mp
);
230 libvlc_media_release(m
);
231 libvlc_release(libvlc
);
233 pthread_cond_destroy(&wait
);