1 /* vim: set sts=4 sw=4 et: */
4 * Support for reading and writing AU/SND files
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
24 #include <libgnomevfs/gnome-vfs.h>
27 #include "maemo-recorder.h"
28 #include "maemo-recorder-au.h"
30 #define AU_DEFAULT_ANNOTATION_LEN 8
31 #define COPY_BUFSIZE 1024
34 au_write_header(GnomeVFSHandle *handle, guint32 encoding, guint32 rate, guint32 channels, size_t len);
37 au_write(GnomeVFSHandle *handle, guint32 encoding, guint32 rate, guint32 channels, gconstpointer data, size_t len)
39 GnomeVFSFileSize written;
44 written = au_write_header(handle, encoding, rate, channels, len);
48 res = gnome_vfs_write(handle,
50 (GnomeVFSFileSize) len,
52 if (res != GNOME_VFS_OK)
54 ULOG_ERR("%s: write failed: %s", G_STRFUNC, gnome_vfs_result_to_string(res));
62 au_write_copy(GnomeVFSHandle *to_handle, guint32 encoding, guint32 rate, guint32 channels, GnomeVFSHandle *from_handle, size_t len)
64 GnomeVFSFileSize written;
67 g_assert(from_handle);
69 written = au_write_header(to_handle, encoding, rate, channels, len);
73 /* copy the raw data from src to dst */
74 return au_copy_data(to_handle, from_handle, 0);
78 au_write_header(GnomeVFSHandle *handle, guint32 encoding, guint32 rate, guint32 channels, size_t len)
80 GnomeVFSFileSize written;
83 struct au_header *hdr = NULL;
85 hdr = (struct au_header *) g_malloc0(sizeof(struct au_header) + AU_DEFAULT_ANNOTATION_LEN);
86 hdr->magic = GUINT32_TO_BE(AU_MAGIC);
87 /* http://www.groupground.org/public/external/auformat.html says:
88 * length of annotation field must be non-zero and multiple of 8 bytes,
89 * the annotation must be terminated with at least one null byte */
90 hdr->data_offset = GUINT32_TO_BE(sizeof(struct au_header) + AU_DEFAULT_ANNOTATION_LEN);
91 hdr->data_size = GUINT32_TO_BE((guint32) len);
92 hdr->encoding = GUINT32_TO_BE(encoding);
93 hdr->sample_rate = GUINT32_TO_BE(rate);
94 hdr->channels = GUINT32_TO_BE(channels);
96 res = gnome_vfs_write(handle,
98 (GnomeVFSFileSize) (sizeof(struct au_header) + AU_DEFAULT_ANNOTATION_LEN),
100 if (res != GNOME_VFS_OK)
102 ULOG_ERR("%s: write failed: %s", G_STRFUNC, gnome_vfs_result_to_string(res));
106 /*return fwrite(hdr, sizeof(hdr), 1, file);*/
111 au_get_info(GnomeVFSHandle *handle, guint32 *format, guint32 *rate, guint32 *channels, guint32 *data_size, guint32 *data_offset)
113 GnomeVFSFileSize read, read_tot = 0;
118 struct au_header *hdr = NULL;
120 hdr = (struct au_header *) g_malloc0(sizeof(struct au_header));
123 /* read in the header */
124 while (read_tot < sizeof(hdr))
126 res = gnome_vfs_read(handle,
128 (sizeof(struct au_header) - read_tot),
130 if (res != GNOME_VFS_OK)
138 tmp = GUINT32_FROM_BE(hdr->magic);
141 ULOG_ERR("%s: wrong magic: %x, expected %x", G_STRFUNC, tmp, AU_MAGIC);
145 *data_offset = GUINT32_FROM_BE(hdr->data_offset);
146 *data_size = GUINT32_FROM_BE(hdr->data_size);
148 tmp = GUINT32_FROM_BE(hdr->encoding);
151 case AU_ENCODING_MULAW_8:
152 *format = FORMAT_PCMU;
155 case AU_ENCODING_ALAW_8:
156 *format = FORMAT_PCMA;
159 case AU_ENCODING_LINEAR_16:
160 *format = FORMAT_PCM;
164 ULOG_ERR("%s: unsupported AU encoding %u", G_STRFUNC, tmp);
168 *rate = GUINT32_FROM_BE(hdr->sample_rate);
169 *channels = GUINT32_FROM_BE(hdr->channels);
175 au_copy_data(GnomeVFSHandle *to_handle, GnomeVFSHandle *from_handle, guint32 from_offset)
180 GnomeVFSFileSize read, written, written_tot = 0;
182 res = gnome_vfs_seek(from_handle,
183 GNOME_VFS_SEEK_START,
184 (GnomeVFSFileOffset) from_offset);
186 if (res != GNOME_VFS_OK)
189 buffer = (gpointer) g_malloc0(COPY_BUFSIZE);
194 res = gnome_vfs_read(from_handle,
199 if (res != GNOME_VFS_OK)
202 if (res != GNOME_VFS_ERROR_EOF)
204 ULOG_ERR("%s: read failed: %s", G_STRFUNC, gnome_vfs_result_to_string(res));
211 res = gnome_vfs_write(to_handle,
216 if (res != GNOME_VFS_OK)
218 ULOG_ERR("%s: write failed: %s", G_STRFUNC, gnome_vfs_result_to_string(res));
223 ULOG_ERR("%s: read != written", G_STRFUNC);
227 written_tot += written;
240 guint32 au_get_encoding(AudioFormat format)
245 return AU_ENCODING_MULAW_8;
248 return AU_ENCODING_ALAW_8;
251 return AU_ENCODING_LINEAR_16;
254 ULOG_ERR("%s: unsupported format for AU encoding %u", G_STRFUNC, format);