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"
33 static gboolean moveFile(const gchar *src, const gchar *dst);
38 doSave(const gchar *current, const gchar *target, AudioFormat format)
40 if (!current|| !target)
56 return moveFile(current, target);
59 return moveFile(current, target);
64 moveFile(const gchar *src, const gchar *dst)
70 tmpcmd = g_strdup_printf("mv '%s' '%s'", src, dst);
81 getExtension(gint format)
86 return EXTENSION_ILBC;
88 /* return EXTENSION_PCMA; */
91 /* return EXTENSION_PCMU; */
101 * @param filename the filename from save dialog
102 * @param tmpfile the tmpfile where the actual data is
103 * @param format format of the tmpfile
104 * @param newfile the file (filename + extension) where the data was saved is returned here
107 saveFile(const gchar *filename, const gchar *tmpfile, AudioFormat format, gchar **newfile)
110 GnomeVFSHandle *tmp_handle = NULL;
111 GnomeVFSHandle *to_handle = NULL;
114 if (!filename || !tmpfile)
117 ext = getExtension(format);
119 /* don't append extension if the filename already has it */
120 if (g_str_has_suffix(filename, ext))
121 newfile_tmp = g_strdup(filename);
123 newfile_tmp = g_strconcat(filename, ext, NULL);
125 g_assert(newfile_tmp);
127 if (strcmp(ext, EXTENSION_AU) == 0)
129 GnomeVFSFileSize len = 0;
130 guint32 encoding = 0;
132 GnomeVFSURI *uri = NULL;
136 len = getFileLength(tmpfile);
139 ULOG_WARN("%s: file length was zero", G_STRFUNC);
143 encoding = au_get_encoding(format);
147 /* open tmpfile(r) */
148 text_uri = g_strconcat("file://", tmpfile, NULL);
150 if (gnome_vfs_open(&tmp_handle, text_uri, GNOME_VFS_OPEN_READ) != GNOME_VFS_OK)
152 ULOG_WARN("%s: gnome_vfs_open() failed", G_STRFUNC);
160 /* open/create newfile for writing */
161 text_uri = g_strconcat("file://", newfile_tmp, NULL);
162 uri = gnome_vfs_uri_new(text_uri);
166 /* TODO: check for symlink and other dangerous stuff */
167 res = gnome_vfs_create_uri(&to_handle, uri,
168 GNOME_VFS_OPEN_WRITE,
170 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH /* perm */);
171 if (res != GNOME_VFS_OK)
173 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));
174 gnome_vfs_uri_unref(uri);
178 /* TODO: future work: get rate and channels from AudioFormatSpec */
179 written = au_write_copy(to_handle, encoding, DEFAULT_RATE, DEFAULT_CHANNELS, tmp_handle, len);
181 gnome_vfs_uri_unref(uri);
182 /* not very clever check but should catch most errors */
185 ULOG_WARN("%s: au_write_copy() failed", G_STRFUNC);
189 /* todo esta bien, close things and exit */
190 gnome_vfs_close(tmp_handle);
191 gnome_vfs_close(to_handle);
193 /* finally, place the filename into newfile */
194 *newfile = newfile_tmp;
200 /* everything but AU files are RAW, just rename */
201 if (moveFile(tmpfile, newfile_tmp))
203 *newfile = newfile_tmp;
212 gnome_vfs_close(tmp_handle);
215 gnome_vfs_close(to_handle);
220 /* don't touch newfile if we're returning false */
221 /* *newfile = NULL; */
226 /* openFile takes in the filename and returns:
227 * - whether it is supported format (the boolean return value)
228 * - audio format (FORMAT_XXX)
229 * - the tmpfile where the raw data is (or the same file name if the file was raw)
230 * TODO: add parameter (GError?) to report back an error string
232 gboolean openFile(const gchar *filename, AudioFormat *format, gchar **tmpfile)
234 if (g_strrstr(filename, EXTENSION_PCMA))
236 ULOG_INFO("%s() - file was %s, assuming raw %s, %d Hz, 1 ch", G_STRFUNC, EXTENSION_PCMA, GST_TYPE_PCMA, PCM_RATE);
237 *format = FORMAT_PCMA;
238 *tmpfile = g_strdup(filename);
240 else if (g_strrstr(filename, EXTENSION_PCMU))
242 ULOG_INFO("%s() - file was %s, assuming raw %s, %d Hz, 1 ch", G_STRFUNC, EXTENSION_PCMU, GST_TYPE_PCMU, PCM_RATE);
243 *format = FORMAT_PCMU;
244 *tmpfile = g_strdup(filename);
246 else if (g_strrstr(filename, EXTENSION_RAW))
248 ULOG_INFO("%s() - file was %s, assuming raw %s, %d Hz, 1 ch, 16-bit", G_STRFUNC, EXTENSION_RAW, GST_TYPE_PCM, PCM_RATE);
249 *format = FORMAT_PCM;
250 *tmpfile = g_strdup(filename);
252 else if (g_strrstr(filename, EXTENSION_MP3))
254 ULOG_INFO("%s() - file was %s", G_STRFUNC, EXTENSION_MP3);
255 *format = FORMAT_MP3;
256 *tmpfile = g_strdup(filename);
258 else if (g_strrstr(filename, EXTENSION_WAV))
260 ULOG_INFO("%s() - file was %s", G_STRFUNC, EXTENSION_WAV);
261 *format = FORMAT_WAV;
262 *tmpfile = g_strdup(filename);
264 else if (g_strrstr(filename, EXTENSION_ILBC))
266 ULOG_INFO("%s() - file was %s", G_STRFUNC, EXTENSION_ILBC);
267 *format = FORMAT_ILBC;
268 *tmpfile = g_strdup(filename);
270 else if (g_strrstr(filename, EXTENSION_AU) || g_strrstr(filename, EXTENSION_SND))
273 GnomeVFSHandle *from_handle, *tmp_handle;
275 guint32 fmt, rate, channels, data_size, data_offset;
280 ULOG_INFO("%s() - file was AU/SND", G_STRFUNC);
281 /* decode and extract raw AU data */
282 text_uri = g_strdup_printf("file://%s", filename);
283 if (gnome_vfs_open(&from_handle, text_uri, GNOME_VFS_OPEN_READ) != GNOME_VFS_OK)
285 ULOG_WARN("%s() - gnome_vfs_open() failed", G_STRFUNC);
291 if ((ret = au_get_info(from_handle, &fmt, &rate, &channels, &data_size, &data_offset)) <= 0)
293 ULOG_WARN("%s() - au_get_info() failed", G_STRFUNC);
294 gnome_vfs_close(from_handle);
298 ULOG_DEBUG("%s() - format: %u, rate: %u, channels: %u, data_size: %u, data_offset: %u", G_STRFUNC, fmt, rate, channels, data_size, data_offset);
299 if (rate != DEFAULT_RATE || channels != DEFAULT_CHANNELS || data_size == 0)
301 ULOG_WARN("%s() - unsupported format", G_STRFUNC);
302 gnome_vfs_close(from_handle);
309 text_uri = g_strdup_printf("file://%s", DEFAULT_TMP_PCMA_FILE);
312 text_uri = g_strdup_printf("file://%s", DEFAULT_TMP_PCMU_FILE);
316 text_uri = g_strdup_printf("file://%s", DEFAULT_TMP_FILE);
320 uri = gnome_vfs_uri_new(text_uri);
324 /* TODO: check for symlink and other dangerous stuff */
325 res = gnome_vfs_create_uri(&tmp_handle, uri,
326 GNOME_VFS_OPEN_WRITE,
328 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH /* perm */);
329 if (res != GNOME_VFS_OK)
331 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));
332 gnome_vfs_uri_unref(uri);
336 ret = au_copy_data(tmp_handle, from_handle, data_offset /* from_offset */);
337 gnome_vfs_close(from_handle);
340 ULOG_WARN("%s() - couldn't copy file data to %s", G_STRFUNC, gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE));
341 gnome_vfs_uri_unref(uri);
345 /* everything ok, tmpfile created */
348 *tmpfile = g_strdup(gnome_vfs_uri_get_path(uri));
349 ULOG_DEBUG("%s() - created tmpfile '%s'", G_STRFUNC, *tmpfile);
351 gnome_vfs_uri_unref(uri);
356 ULOG_WARN("%s() - non-matching file name", G_STRFUNC);
362 GnomeVFSFileSize getFileLength(const gchar *file)
364 GnomeVFSFileInfo *info;
367 GnomeVFSFileSize ret = 0;
372 text_uri = g_strdup_printf("file://%s", file);
373 info = gnome_vfs_file_info_new();
374 res = gnome_vfs_get_file_info(text_uri,
376 GNOME_VFS_FILE_INFO_DEFAULT);
379 if (res == GNOME_VFS_OK && (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE))
385 ULOG_WARN("%s: couldn't get file size", G_STRFUNC);
389 gnome_vfs_file_info_unref(info);