kwave  18.07.70
VirtualAudioFile.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  VirtualAudioFile.cpp - adapter between QIODevice and libaudiofile
3  -------------------
4  begin : Mon May 06 2002
5  copyright : (C) 2002 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 #include <QIODevice>
20 #include <stdlib.h> // for calloc()
21 #include <unistd.h>
22 
23 #include "libkwave/Utils.h"
25 
30 static QMap<AFvirtualfile*, Kwave::VirtualAudioFile*> *_adapter_map = Q_NULLPTR;
31 
33 static long _last_audiofile_error = -1;
34 
37 
38 //***************************************************************************
46 static void _handle_audiofile_error(long int error, const char *str)
47 {
48  qDebug("libaudiofile error %ld: '%s'", error, str);
49  _last_audiofile_error = error;
50  _last_audiofile_error_text = QString::fromLatin1(str);
51 }
52 
53 //***************************************************************************
55 static long _lastAudiofileError()
56 {
57  long err = _last_audiofile_error;
59 
60  // ignore "bad alloc", which might occur on a "malloc(0)"
61  if (err == AF_BAD_MALLOC) err = -1;
62  return err;
63 }
64 
65 //***************************************************************************
66 static ssize_t af_file_read(AFvirtualfile *vfile, void *data,
67  size_t nbytes)
68 {
70  return (adapter) ?
71  static_cast<ssize_t>(adapter->read(
72  static_cast<char *>(data),
73  Kwave::toUint(nbytes)
74  )) : 0;
75 }
76 
77 //***************************************************************************
78 static AFfileoffset af_file_length(AFvirtualfile *vfile)
79 {
81  return (adapter) ? static_cast<AFfileoffset>(adapter->length()) : -1;
82 }
83 
84 //***************************************************************************
85 static ssize_t af_file_write(AFvirtualfile *vfile, const void *data,
86  size_t nbytes)
87 {
89  return (adapter) ?
90  static_cast<ssize_t>(adapter->write(
91  static_cast<const char *>(data),
92  Kwave::toUint(nbytes)
93  )) : 0;
94 }
95 
96 //***************************************************************************
97 static void af_file_destroy(AFvirtualfile */*vfile*/)
98 {
99 }
100 
101 //***************************************************************************
102 static AFfileoffset af_file_seek(AFvirtualfile *vfile, AFfileoffset offset,
103  int is_relative)
104 {
106  return (adapter) ?
107  static_cast<AFfileoffset>(adapter->seek(
108  static_cast<qint64>(offset),
109  (is_relative != 0)
110  )) : -1;
111 }
112 
113 //***************************************************************************
114 static AFfileoffset af_file_tell(AFvirtualfile *vfile)
115 {
117  return (adapter) ? static_cast<AFfileoffset>(adapter->tell()) : -1;
118 }
119 
120 //***************************************************************************
129 static AFvirtualfile *__af_virtual_file_new(void)
130 {
131  return static_cast<AFvirtualfile *>(calloc(sizeof(AFvirtualfile), 1));
132 }
133 
134 //***************************************************************************
135 //***************************************************************************
137  :m_device(device), m_file_handle(Q_NULLPTR), m_virtual_file(Q_NULLPTR),
138  m_last_error(-1), m_last_error_text()
139 {
140  // create the virtual file structure for libaudiofile
142  Q_ASSERT(m_virtual_file);
143  if (!m_virtual_file) return;
144 
145  // enter our wrapper functions
146  m_virtual_file->closure = Q_NULLPTR;
148  m_virtual_file->write = af_file_write;
149  m_virtual_file->length = af_file_length;
150  m_virtual_file->destroy = af_file_destroy;
153 }
154 
155 //***************************************************************************
157  AFfilesetup setup)
158 {
159  // register ourself
160  adapter(Q_NULLPTR); // dummy lookup, for creating a new map if needed
161  Q_ASSERT(_adapter_map);
162  if (_adapter_map) _adapter_map->insert(m_virtual_file, x);
163 
164  // determine the mode: rw/w/r
165  const char *mode = Q_NULLPTR;
166  if (m_device.isWritable()) mode = "w";
167  else if (m_device.isReadable()) mode = "r";
168  Q_ASSERT(mode);
169 
170  AFerrfunc old_handler;
171  old_handler = afSetErrorHandler(_handle_audiofile_error);
172 
173  // reset the file position when opening the device, otherwise libaudiofile
174  // might fail when seeking to the current position and the position of
175  // the device currently is at EOF (in libaudiofile, File::canSeek)
176  m_device.seek(0);
177 
178  // open the virtual file and get a handle for it
179  m_file_handle = afOpenVirtualFile(m_virtual_file, mode, setup);
182 
183  afSetErrorHandler(old_handler);
184 }
185 
186 //***************************************************************************
188 {
189  // close libaudiofile stuff
190  afCloseFile(m_file_handle);
191 
192  // de-register ourself
194 
195  m_virtual_file = Q_NULLPTR;
196  m_file_handle = Q_NULLPTR;
197 }
198 
199 //***************************************************************************
201 {
202  if (m_virtual_file) close();
203 }
204 
205 //***************************************************************************
206 qint64 Kwave::VirtualAudioFile::read(char *data, unsigned int nbytes)
207 {
208  Q_ASSERT(data);
209  if (!data) return 0;
210  return m_device.read(data, nbytes);
211 }
212 
213 //***************************************************************************
215 {
216  return m_device.size();
217 }
218 
219 //***************************************************************************
220 qint64 Kwave::VirtualAudioFile::write(const char *data, unsigned int nbytes)
221 {
222  Q_ASSERT(data);
223  if (!data) return 0;
224  return m_device.write(data, nbytes);
225 }
226 
227 //***************************************************************************
229 {
230 }
231 
232 //***************************************************************************
233 qint64 Kwave::VirtualAudioFile::seek(qint64 offset, bool is_relative)
234 {
235  qint64 abs_pos = (is_relative) ? (m_device.pos() + offset) : offset;
236  if (abs_pos >= m_device.size())
237  return -1; // avoid seek after EOF
238  bool ok = m_device.seek(abs_pos);
239  return (ok) ? m_device.pos() : -1;
240 }
241 
242 //***************************************************************************
244 {
245  return m_device.pos();
246 }
247 
248 //***************************************************************************
250 {
251  // create a new empty map if necessary
252  if (!_adapter_map) _adapter_map =
253  new QMap<AFvirtualfile*,VirtualAudioFile*>();
254  Q_ASSERT(_adapter_map);
255  if (!_adapter_map) return Q_NULLPTR;
256 
257  // lookup in the map
258  return _adapter_map->contains(vfile) ? (*_adapter_map)[vfile] : Q_NULLPTR;
259 }
260 
261 //***************************************************************************
262 //***************************************************************************
virtual qint64 read(char *data, unsigned int nbytes)
static void af_file_destroy(AFvirtualfile *)
static AFfileoffset af_file_seek(AFvirtualfile *vfile, AFfileoffset offset, int is_relative)
static AFfileoffset af_file_length(AFvirtualfile *vfile)
static Kwave::VirtualAudioFile * adapter(AFvirtualfile *vfile)
virtual void open(Kwave::VirtualAudioFile *x, AFfilesetup setup)
static ssize_t af_file_read(AFvirtualfile *vfile, void *data, size_t nbytes)
static long _lastAudiofileError()
static ssize_t af_file_write(AFvirtualfile *vfile, const void *data, size_t nbytes)
static long _last_audiofile_error
static void _handle_audiofile_error(long int error, const char *str)
AFvirtualfile * m_virtual_file
virtual qint64 write(const char *data, unsigned int nbytes)
VirtualAudioFile(QIODevice &device)
static QString _last_audiofile_error_text
static QMap< AFvirtualfile *, Kwave::VirtualAudioFile * > * _adapter_map
static AFfileoffset af_file_tell(AFvirtualfile *vfile)
unsigned int toUint(T x)
Definition: Utils.h:109
static AFvirtualfile * __af_virtual_file_new(void)
virtual qint64 seek(qint64 offset, bool is_relative)