Qt(dialog provider): fix utf8 issue with generic dialog box title
[vlc.git] / src / video_output / snapshot.c
blobc8096ef60930bbf20670c68bf19b77be9e936c9c
1 /*****************************************************************************
2 * snapshot.c : vout internal snapshot
3 *****************************************************************************
4 * Copyright (C) 2009 Laurent Aimar
5 * $Id$
7 * Authors: Gildas Bazin <gbazin _AT_ videolan _DOT_ org>
8 * Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
29 #include <assert.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <dirent.h>
34 #include <time.h>
36 #include <vlc_common.h>
37 #include <vlc_fs.h>
38 #include <vlc_strings.h>
39 #include <vlc_block.h>
40 #include <vlc_vout.h>
42 #include "snapshot.h"
43 #include "vout_internal.h"
45 /* */
46 void vout_snapshot_Init(vout_snapshot_t *snap)
48 vlc_mutex_init(&snap->lock);
49 vlc_cond_init(&snap->wait);
51 snap->is_available = true;
52 snap->request_count = 0;
53 snap->picture = NULL;
55 void vout_snapshot_Clean(vout_snapshot_t *snap)
57 picture_t *picture = snap->picture;
58 while (picture) {
59 picture_t *next = picture->p_next;
60 picture_Release(picture);
61 picture = next;
64 vlc_cond_destroy(&snap->wait);
65 vlc_mutex_destroy(&snap->lock);
68 void vout_snapshot_End(vout_snapshot_t *snap)
70 vlc_mutex_lock(&snap->lock);
72 snap->is_available = false;
74 vlc_cond_broadcast(&snap->wait);
75 vlc_mutex_unlock(&snap->lock);
78 /* */
79 picture_t *vout_snapshot_Get(vout_snapshot_t *snap, mtime_t timeout)
81 vlc_mutex_lock(&snap->lock);
83 /* */
84 snap->request_count++;
86 /* */
87 const mtime_t deadline = mdate() + timeout;
88 while (snap->is_available && !snap->picture && mdate() < deadline)
89 vlc_cond_timedwait(&snap->wait, &snap->lock, deadline);
91 /* */
92 picture_t *picture = snap->picture;
93 if (picture)
94 snap->picture = picture->p_next;
95 else if (snap->request_count > 0)
96 snap->request_count--;
98 vlc_mutex_unlock(&snap->lock);
100 return picture;
103 /* */
104 bool vout_snapshot_IsRequested(vout_snapshot_t *snap)
106 bool has_request = false;
107 if (!vlc_mutex_trylock(&snap->lock)) {
108 has_request = snap->request_count > 0;
109 vlc_mutex_unlock(&snap->lock);
111 return has_request;
113 void vout_snapshot_Set(vout_snapshot_t *snap,
114 const video_format_t *fmt,
115 const picture_t *picture)
117 if (!fmt)
118 fmt = &picture->format;
120 vlc_mutex_lock(&snap->lock);
121 while (snap->request_count > 0) {
122 picture_t *dup = picture_NewFromFormat(fmt);
123 if (!dup)
124 break;
126 picture_Copy(dup, picture);
128 dup->p_next = snap->picture;
129 snap->picture = dup;
130 snap->request_count--;
132 vlc_cond_broadcast(&snap->wait);
133 vlc_mutex_unlock(&snap->lock);
135 /* */
136 char *vout_snapshot_GetDirectory(void)
138 return config_GetUserDir(VLC_PICTURES_DIR);
140 /* */
141 int vout_snapshot_SaveImage(char **name, int *sequential,
142 const block_t *image,
143 vout_thread_t *p_vout,
144 const vout_snapshot_save_cfg_t *cfg)
146 /* */
147 char *filename;
148 DIR *pathdir = vlc_opendir(cfg->path);
149 input_thread_t *input = (input_thread_t*)p_vout->p->input;
150 if (pathdir != NULL) {
151 /* The use specified a directory path */
152 closedir(pathdir);
154 /* */
155 char *prefix = NULL;
156 if (cfg->prefix_fmt)
157 prefix = str_format(input, cfg->prefix_fmt);
158 if (prefix)
159 filename_sanitize(prefix);
160 else {
161 prefix = strdup("vlcsnap-");
162 if (!prefix)
163 goto error;
166 if (cfg->is_sequential) {
167 for (int num = cfg->sequence; ; num++) {
168 struct stat st;
170 if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s",
171 cfg->path, prefix, num, cfg->format) < 0) {
172 free(prefix);
173 goto error;
175 if (vlc_stat(filename, &st)) {
176 *sequential = num;
177 break;
179 free(filename);
181 } else {
182 struct timeval tv;
183 struct tm curtime;
184 char buffer[128];
186 gettimeofday(&tv, NULL);
187 if (localtime_r(&tv.tv_sec, &curtime) == NULL)
188 gmtime_r(&tv.tv_sec, &curtime);
189 if (strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss",
190 &curtime) == 0)
191 strcpy(buffer, "error");
193 if (asprintf(&filename, "%s" DIR_SEP "%s%s%03lu.%s",
194 cfg->path, prefix, buffer, tv.tv_usec / 1000,
195 cfg->format) < 0)
196 filename = NULL;
198 free(prefix);
199 } else {
200 /* The user specified a full path name (including file name) */
201 filename = str_format(input, cfg->path);
202 path_sanitize(filename);
205 if (!filename)
206 goto error;
208 /* Save the snapshot */
209 FILE *file = vlc_fopen(filename, "wb");
210 if (!file) {
211 msg_Err(p_vout, "Failed to open '%s'", filename);
212 free(filename);
213 goto error;
215 if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) {
216 msg_Err(p_vout, "Failed to write to '%s'", filename);
217 fclose(file);
218 free(filename);
219 goto error;
221 fclose(file);
223 /* */
224 if (name)
225 *name = filename;
226 else
227 free(filename);
229 return VLC_SUCCESS;
231 error:
232 msg_Err(p_vout, "could not save snapshot");
233 return VLC_EGENERIC;