annotate data/fileio/BZipFileDevice.cpp @ 1359:1c9bbbb6116a 3.0-integration

Use W64 instead of WAV for decoded files; use Ogg reader in preference to WAV one for Ogg files (WAV reader works, via libsndfile, but doesn't load metadata); fix Ogg reader to use QFile open instead of non-Win32-compatible API; add more encoder tests, audio writer test, midi reader test
author Chris Cannam
date Tue, 10 Jan 2017 10:58:25 +0000
parents b3cb0edc25cd
children ce08318aad83
rev   line source
Chris@148 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@148 2
Chris@148 3 /*
Chris@148 4 Sonic Visualiser
Chris@148 5 An audio file viewer and annotation editor.
Chris@148 6 Centre for Digital Music, Queen Mary, University of London.
Chris@148 7 This file copyright 2006 Chris Cannam.
Chris@148 8
Chris@148 9 This program is free software; you can redistribute it and/or
Chris@148 10 modify it under the terms of the GNU General Public License as
Chris@148 11 published by the Free Software Foundation; either version 2 of the
Chris@148 12 License, or (at your option) any later version. See the file
Chris@148 13 COPYING included with this distribution for more information.
Chris@148 14 */
Chris@148 15
Chris@148 16 #include "BZipFileDevice.h"
Chris@148 17
Chris@148 18 #include <bzlib.h>
Chris@148 19
Chris@148 20 #include <iostream>
Chris@148 21
Chris@843 22 #include "base/Debug.h"
Chris@843 23
Chris@148 24 BZipFileDevice::BZipFileDevice(QString fileName) :
Chris@148 25 m_fileName(fileName),
Chris@1348 26 m_qfile(fileName),
Chris@148 27 m_file(0),
Chris@148 28 m_bzFile(0),
Chris@207 29 m_atEnd(true),
Chris@207 30 m_ok(true)
Chris@148 31 {
Chris@148 32 }
Chris@148 33
Chris@148 34 BZipFileDevice::~BZipFileDevice()
Chris@148 35 {
Chris@690 36 // SVDEBUG << "BZipFileDevice::~BZipFileDevice(" << m_fileName << ")" << endl;
Chris@148 37 if (m_bzFile) close();
Chris@148 38 }
Chris@148 39
Chris@148 40 bool
Chris@207 41 BZipFileDevice::isOK() const
Chris@207 42 {
Chris@207 43 return m_ok;
Chris@207 44 }
Chris@207 45
Chris@207 46 bool
Chris@148 47 BZipFileDevice::open(OpenMode mode)
Chris@148 48 {
Chris@203 49 setErrorString("");
Chris@203 50
Chris@148 51 if (m_bzFile) {
Chris@148 52 setErrorString(tr("File is already open"));
Chris@148 53 return false;
Chris@148 54 }
Chris@148 55
Chris@148 56 if (mode & Append) {
Chris@148 57 setErrorString(tr("Append mode not supported"));
Chris@207 58 m_ok = false;
Chris@148 59 return false;
Chris@148 60 }
Chris@148 61
Chris@148 62 if ((mode & (ReadOnly | WriteOnly)) == 0) {
Chris@148 63 setErrorString(tr("File access mode not specified"));
Chris@207 64 m_ok = false;
Chris@148 65 return false;
Chris@148 66 }
Chris@148 67
Chris@148 68 if ((mode & ReadOnly) && (mode & WriteOnly)) {
Chris@148 69 setErrorString(tr("Read and write modes both specified"));
Chris@207 70 m_ok = false;
Chris@148 71 return false;
Chris@148 72 }
Chris@148 73
Chris@148 74 if (mode & WriteOnly) {
Chris@148 75
Chris@1348 76 if (!m_qfile.open(QIODevice::WriteOnly)) {
Chris@1348 77 setErrorString(tr("Failed to open file for writing"));
Chris@1348 78 m_ok = false;
Chris@1348 79 return false;
Chris@1348 80 }
Chris@1348 81
Chris@1348 82 m_file = fdopen(m_qfile.handle(), "wb");
Chris@148 83 if (!m_file) {
Chris@1348 84 setErrorString(tr("Failed to open file handle for writing"));
Chris@1348 85 m_qfile.close();
Chris@207 86 m_ok = false;
Chris@148 87 return false;
Chris@148 88 }
Chris@148 89
Chris@148 90 int bzError = BZ_OK;
Chris@148 91 m_bzFile = BZ2_bzWriteOpen(&bzError, m_file, 9, 0, 0);
Chris@148 92
Chris@148 93 if (!m_bzFile) {
Chris@148 94 fclose(m_file);
Chris@148 95 m_file = 0;
Chris@1348 96 m_qfile.close();
Chris@148 97 setErrorString(tr("Failed to open bzip2 stream for writing"));
Chris@207 98 m_ok = false;
Chris@148 99 return false;
Chris@148 100 }
Chris@148 101
Chris@843 102 // cerr << "BZipFileDevice: opened \"" << m_fileName << "\" for writing" << endl;
Chris@148 103
Chris@148 104 setErrorString(QString());
Chris@148 105 setOpenMode(mode);
Chris@148 106 return true;
Chris@148 107 }
Chris@148 108
Chris@148 109 if (mode & ReadOnly) {
Chris@148 110
Chris@1348 111 if (!m_qfile.open(QIODevice::ReadOnly)) {
Chris@1348 112 setErrorString(tr("Failed to open file for reading"));
Chris@1348 113 m_ok = false;
Chris@1348 114 return false;
Chris@1348 115 }
Chris@1348 116
Chris@1348 117 m_file = fdopen(m_qfile.handle(), "rb");
Chris@148 118 if (!m_file) {
Chris@1348 119 setErrorString(tr("Failed to open file handle for reading"));
Chris@207 120 m_ok = false;
Chris@148 121 return false;
Chris@148 122 }
Chris@148 123
Chris@148 124 int bzError = BZ_OK;
Chris@148 125 m_bzFile = BZ2_bzReadOpen(&bzError, m_file, 0, 0, NULL, 0);
Chris@148 126
Chris@148 127 if (!m_bzFile) {
Chris@148 128 fclose(m_file);
Chris@148 129 m_file = 0;
Chris@1348 130 m_qfile.close();
Chris@148 131 setErrorString(tr("Failed to open bzip2 stream for reading"));
Chris@207 132 m_ok = false;
Chris@148 133 return false;
Chris@148 134 }
Chris@148 135
Chris@843 136 // cerr << "BZipFileDevice: opened \"" << m_fileName << "\" for reading" << endl;
Chris@148 137
Chris@148 138 m_atEnd = false;
Chris@148 139
Chris@148 140 setErrorString(QString());
Chris@148 141 setOpenMode(mode);
Chris@148 142 return true;
Chris@148 143 }
Chris@148 144
Chris@148 145 setErrorString(tr("Internal error (open for neither read nor write)"));
Chris@207 146 m_ok = false;
Chris@148 147 return false;
Chris@148 148 }
Chris@148 149
Chris@148 150 void
Chris@148 151 BZipFileDevice::close()
Chris@148 152 {
Chris@148 153 if (!m_bzFile) {
Chris@148 154 setErrorString(tr("File not open"));
Chris@207 155 m_ok = false;
Chris@148 156 return;
Chris@148 157 }
Chris@148 158
Chris@148 159 int bzError = BZ_OK;
Chris@148 160
Chris@148 161 if (openMode() & WriteOnly) {
Chris@148 162 unsigned int in = 0, out = 0;
Chris@148 163 BZ2_bzWriteClose(&bzError, m_bzFile, 0, &in, &out);
Chris@843 164 // cerr << "Wrote bzip2 stream (in=" << in << ", out=" << out << ")" << endl;
Chris@148 165 if (bzError != BZ_OK) {
Chris@148 166 setErrorString(tr("bzip2 stream write close error"));
Chris@148 167 }
Chris@148 168 fclose(m_file);
Chris@1348 169 m_qfile.close();
Chris@148 170 m_bzFile = 0;
Chris@148 171 m_file = 0;
Chris@207 172 m_ok = false;
Chris@148 173 return;
Chris@148 174 }
Chris@148 175
Chris@148 176 if (openMode() & ReadOnly) {
Chris@148 177 BZ2_bzReadClose(&bzError, m_bzFile);
Chris@148 178 if (bzError != BZ_OK) {
Chris@148 179 setErrorString(tr("bzip2 stream read close error"));
Chris@148 180 }
Chris@148 181 fclose(m_file);
Chris@1348 182 m_qfile.close();
Chris@148 183 m_bzFile = 0;
Chris@148 184 m_file = 0;
Chris@207 185 m_ok = false;
Chris@148 186 return;
Chris@148 187 }
Chris@148 188
Chris@148 189 setErrorString(tr("Internal error (close for neither read nor write)"));
Chris@148 190 return;
Chris@148 191 }
Chris@148 192
Chris@148 193 qint64
Chris@148 194 BZipFileDevice::readData(char *data, qint64 maxSize)
Chris@148 195 {
Chris@148 196 if (m_atEnd) return 0;
Chris@148 197
Chris@148 198 int bzError = BZ_OK;
Chris@1038 199 int read = BZ2_bzRead(&bzError, m_bzFile, data, int(maxSize));
Chris@148 200
Chris@690 201 // SVDEBUG << "BZipFileDevice::readData: requested " << maxSize << ", read " << read << endl;
Chris@148 202
Chris@148 203 if (bzError != BZ_OK) {
Chris@148 204 if (bzError != BZ_STREAM_END) {
Chris@843 205 cerr << "BZipFileDevice::readData: error condition" << endl;
Chris@148 206 setErrorString(tr("bzip2 stream read error"));
Chris@207 207 m_ok = false;
Chris@148 208 return -1;
Chris@148 209 } else {
Chris@690 210 // SVDEBUG << "BZipFileDevice::readData: reached end of file" << endl;
Chris@148 211 m_atEnd = true;
Chris@148 212 }
Chris@148 213 }
Chris@148 214
Chris@148 215 return read;
Chris@148 216 }
Chris@148 217
Chris@148 218 qint64
Chris@148 219 BZipFileDevice::writeData(const char *data, qint64 maxSize)
Chris@148 220 {
Chris@148 221 int bzError = BZ_OK;
Chris@1038 222 BZ2_bzWrite(&bzError, m_bzFile, (void *)data, int(maxSize));
Chris@148 223
Chris@690 224 // SVDEBUG << "BZipFileDevice::writeData: " << maxSize << " to write" << endl;
Chris@148 225
Chris@148 226 if (bzError != BZ_OK) {
Chris@843 227 cerr << "BZipFileDevice::writeData: error condition" << endl;
Chris@148 228 setErrorString("bzip2 stream write error");
Chris@207 229 m_ok = false;
Chris@148 230 return -1;
Chris@148 231 }
Chris@148 232
Chris@690 233 // SVDEBUG << "BZipFileDevice::writeData: wrote " << maxSize << endl;
Chris@148 234
Chris@148 235 return maxSize;
Chris@148 236 }
Chris@148 237