1 /* vim: set ts=4 sw=4 et: */
3 * maemo-recorder-file.c
4 * File-related operations
6 * Copyright (C) 2006 Nokia Corporation
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <libgnomevfs/gnome-vfs.h>
29 #include "maemo-recorder.h"
30 #include "maemo-recorder-file.h"
31 #include "maemo-recorder-au.h"
34 static gboolean moveFile(const gchar *src, const gchar *dst);
39 doSave(const gchar *current, const gchar *target, AudioFormat format)
41 if (!current|| !target)
57 return moveFile(current, target);
60 return moveFile(current, target);
65 moveFile(const gchar *src, const gchar *dst)
71 tmpcmd = g_strdup_printf("mv '%s' '%s'", src, dst);
82 getExtension(gint format)
87 return EXTENSION_ILBC;
89 /* return EXTENSION_PCMA; */
92 /* return EXTENSION_PCMU; */
104 * @param filename the filename from save dialog
105 * @param tmpfile the tmpfile where the actual data is
106 * @param format format of the tmpfile
107 * @param newfile the file (filename + extension) where the data was saved is returned here
110 saveFile(const gchar *filename, const gchar *tmpfile, AudioFormat format, gchar **newfile)
113 GnomeVFSHandle *tmp_handle = NULL;
114 GnomeVFSHandle *to_handle = NULL;
117 if (!filename || !tmpfile)
120 ext = getExtension(format);
122 /* don't append extension if the filename already has it */
123 if (g_str_has_suffix(filename, ext))
124 newfile_tmp = g_strdup(filename);
126 newfile_tmp = g_strconcat(filename, ext, NULL);
128 g_assert(newfile_tmp);
130 if (strcmp(ext, EXTENSION_AU) == 0)
132 GnomeVFSFileSize len = 0;
133 guint32 encoding = 0;
135 GnomeVFSURI *uri = NULL;
139 len = getFileLength(tmpfile);
142 ULOG_WARN("%s: file length was zero", G_STRFUNC);
146 encoding = au_get_encoding(format);
150 /* open tmpfile(r) */
151 text_uri = file2uri(tmpfile);
153 if (gnome_vfs_open(&tmp_handle, text_uri, GNOME_VFS_OPEN_READ) != GNOME_VFS_OK)
155 ULOG_WARN("%s: gnome_vfs_open() failed", G_STRFUNC);
163 /* open/create newfile for writing */
164 text_uri = file2uri(newfile_tmp);
165 uri = gnome_vfs_uri_new(text_uri);
169 /* TODO: check for symlink and other dangerous stuff */
170 res = gnome_vfs_create_uri(&to_handle, uri,
171 GNOME_VFS_OPEN_WRITE,
173 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH /* perm */);
174 if (res != GNOME_VFS_OK)
176 ULOG_WARN("%s: gnome_vfs_create_uri() failed for '%s': %s", G_STRFUNC, gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE), gnome_vfs_result_to_string(res));
177 gnome_vfs_uri_unref(uri);
181 /* TODO: future work: get rate and channels from AudioFormatSpec */
182 written = au_write_copy(to_handle, encoding, DEFAULT_RATE, DEFAULT_CHANNELS, tmp_handle, len);
184 gnome_vfs_uri_unref(uri);
185 /* not very clever check but should catch most errors */
188 ULOG_WARN("%s: au_write_copy() failed", G_STRFUNC);
192 /* todo esta bien, close things and exit */
193 gnome_vfs_close(tmp_handle);
194 gnome_vfs_close(to_handle);
196 /* finally, place the filename into newfile */
197 *newfile = newfile_tmp;
203 /* everything but AU files are RAW, just rename */
204 if (moveFile(tmpfile, newfile_tmp))
206 *newfile = newfile_tmp;
215 gnome_vfs_close(tmp_handle);
218 gnome_vfs_close(to_handle);
223 /* don't touch newfile if we're returning false */
224 /* *newfile = NULL; */
229 /* openFile takes in the filename and returns:
230 * - whether it is supported format (the boolean return value)
231 * - audio format (FORMAT_XXX)
232 * - the tmpfile where the raw data is (or the same file name if the file was raw)
233 * TODO: add parameter (GError?) to report back an error string
236 openFile(const gchar *filename, AudioFormat *format, gchar **tmpfile)
238 if (g_strrstr(filename, EXTENSION_PCMA))
240 ULOG_INFO("%s() - file was %s, assuming raw %s, %d Hz, 1 ch", G_STRFUNC, EXTENSION_PCMA, GST_TYPE_PCMA, PCM_RATE);
241 *format = FORMAT_PCMA;
242 *tmpfile = g_strdup(filename);
244 else if (g_strrstr(filename, EXTENSION_PCMU))
246 ULOG_INFO("%s() - file was %s, assuming raw %s, %d Hz, 1 ch", G_STRFUNC, EXTENSION_PCMU, GST_TYPE_PCMU, PCM_RATE);
247 *format = FORMAT_PCMU;
248 *tmpfile = g_strdup(filename);
250 else if (g_strrstr(filename, EXTENSION_RAW))
252 ULOG_INFO("%s() - file was %s, assuming raw %s, %d Hz, 1 ch, 16-bit", G_STRFUNC, EXTENSION_RAW, GST_TYPE_PCM, PCM_RATE);
253 *format = FORMAT_PCM;
254 *tmpfile = g_strdup(filename);
256 else if (g_strrstr(filename, EXTENSION_MP3))
258 ULOG_INFO("%s() - file was %s", G_STRFUNC, EXTENSION_MP3);
259 *format = FORMAT_MP3;
260 *tmpfile = g_strdup(filename);
262 else if (g_strrstr(filename, EXTENSION_WAV))
264 ULOG_INFO("%s() - file was %s", G_STRFUNC, EXTENSION_WAV);
265 *format = FORMAT_WAV;
266 /* TODO: we should dig out the rate, channels and stuff from the WAV file here or get the caps from some GstPad */
267 *tmpfile = g_strdup(filename);
269 else if (g_strrstr(filename, EXTENSION_ILBC))
271 ULOG_INFO("%s() - file was %s", G_STRFUNC, EXTENSION_ILBC);
272 *format = FORMAT_ILBC;
273 *tmpfile = g_strdup(filename);
275 else if (g_strrstr(filename, EXTENSION_AU) || g_strrstr(filename, EXTENSION_SND))
278 GnomeVFSHandle *from_handle, *tmp_handle;
280 guint32 fmt, rate, channels, data_size, data_offset;
285 ULOG_INFO("%s() - file was AU/SND", G_STRFUNC);
286 /* decode and extract raw AU data */
287 text_uri = file2uri(filename);
288 if (gnome_vfs_open(&from_handle, text_uri, GNOME_VFS_OPEN_READ) != GNOME_VFS_OK)
290 ULOG_WARN("%s() - gnome_vfs_open() failed", G_STRFUNC);
296 if ((ret = au_get_info(from_handle, &fmt, &rate, &channels, &data_size, &data_offset)) <= 0)
298 ULOG_WARN("%s() - au_get_info() failed", G_STRFUNC);
299 gnome_vfs_close(from_handle);
303 ULOG_DEBUG("%s() - format: %u, rate: %u, channels: %u, data_size: %u, data_offset: %u", G_STRFUNC, fmt, rate, channels, data_size, data_offset);
304 if (rate != DEFAULT_RATE || channels != DEFAULT_CHANNELS || data_size == 0)
306 ULOG_WARN("%s() - unsupported format", G_STRFUNC);
307 gnome_vfs_close(from_handle);
314 text_uri = g_strdup_printf("file://%s/%s", get_default_dir(), DEFAULT_TMP_PCMA_FILE);
317 text_uri = g_strdup_printf("file://%s/%s", get_default_dir(), DEFAULT_TMP_PCMU_FILE);
321 text_uri = g_strdup_printf("file://%s/%s", get_default_dir(), DEFAULT_TMP_FILE);
325 uri = gnome_vfs_uri_new(text_uri);
329 /* TODO: check for symlink and other dangerous stuff */
330 res = gnome_vfs_create_uri(&tmp_handle, uri,
331 GNOME_VFS_OPEN_WRITE,
333 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH /* perm */);
334 if (res != GNOME_VFS_OK)
336 ULOG_WARN("%s() - gnome_vfs_create() failed for '%s': %s", G_STRFUNC, gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE), gnome_vfs_result_to_string(res));
337 gnome_vfs_uri_unref(uri);
341 ret = au_copy_data(tmp_handle, from_handle, data_offset /* from_offset */);
342 gnome_vfs_close(from_handle);
345 ULOG_WARN("%s() - couldn't copy file data to %s", G_STRFUNC, gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE));
346 gnome_vfs_uri_unref(uri);
350 /* everything ok, tmpfile created */
353 *tmpfile = g_strdup(gnome_vfs_uri_get_path(uri));
354 ULOG_DEBUG("%s() - created tmpfile '%s'", G_STRFUNC, *tmpfile);
356 gnome_vfs_uri_unref(uri);
361 ULOG_WARN("%s() - non-matching file name", G_STRFUNC);
368 getFileLength(const gchar *file)
370 GnomeVFSFileInfo *info;
373 GnomeVFSFileSize ret = 0;
378 text_uri = file2uri(file);
379 info = gnome_vfs_file_info_new();
380 res = gnome_vfs_get_file_info(text_uri,
382 GNOME_VFS_FILE_INFO_DEFAULT);
385 if (res == GNOME_VFS_OK && (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE))
391 ULOG_WARN("%s: couldn't get file size", G_STRFUNC);
395 gnome_vfs_file_info_unref(info);
401 file2uri(const gchar *filename)
403 if (NULL == filename)
406 if (g_str_has_prefix(filename, "file://"))
407 return g_strdup(filename);
410 return g_strconcat("file://", filename, NULL);
412 return g_filename_to_uri(filename, NULL, NULL);