annotate data/fileio/BZipFileDevice.cpp @ 674:920e3880f7b4

* Add TempWriteFile abstraction, use it when exporting audio to avoid clobbering existing file before export is complete
author Chris Cannam
date Tue, 29 Mar 2011 17:30:23 +0100
parents 8ee6cf529c4e
children b4a8d8221eaf
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@148 22 BZipFileDevice::BZipFileDevice(QString fileName) :
Chris@148 23 m_fileName(fileName),
Chris@148 24 m_file(0),
Chris@148 25 m_bzFile(0),
Chris@207 26 m_atEnd(true),
Chris@207 27 m_ok(true)
Chris@148 28 {
Chris@148 29 }
Chris@148 30
Chris@148 31 BZipFileDevice::~BZipFileDevice()
Chris@148 32 {
Chris@148 33 // std::cerr << "BZipFileDevice::~BZipFileDevice(" << m_fileName.toStdString() << ")" << std::endl;
Chris@148 34 if (m_bzFile) close();
Chris@148 35 }
Chris@148 36
Chris@148 37 bool
Chris@207 38 BZipFileDevice::isOK() const
Chris@207 39 {
Chris@207 40 return m_ok;
Chris@207 41 }
Chris@207 42
Chris@207 43 bool
Chris@148 44 BZipFileDevice::open(OpenMode mode)
Chris@148 45 {
Chris@203 46 setErrorString("");
Chris@203 47
Chris@148 48 if (m_bzFile) {
Chris@148 49 setErrorString(tr("File is already open"));
Chris@148 50 return false;
Chris@148 51 }
Chris@148 52
Chris@148 53 if (mode & Append) {
Chris@148 54 setErrorString(tr("Append mode not supported"));
Chris@207 55 m_ok = false;
Chris@148 56 return false;
Chris@148 57 }
Chris@148 58
Chris@148 59 if ((mode & (ReadOnly | WriteOnly)) == 0) {
Chris@148 60 setErrorString(tr("File access mode not specified"));
Chris@207 61 m_ok = false;
Chris@148 62 return false;
Chris@148 63 }
Chris@148 64
Chris@148 65 if ((mode & ReadOnly) && (mode & WriteOnly)) {
Chris@148 66 setErrorString(tr("Read and write modes both specified"));
Chris@207 67 m_ok = false;
Chris@148 68 return false;
Chris@148 69 }
Chris@148 70
Chris@148 71 if (mode & WriteOnly) {
Chris@148 72
Chris@148 73 m_file = fopen(m_fileName.toLocal8Bit().data(), "wb");
Chris@148 74 if (!m_file) {
Chris@148 75 setErrorString(tr("Failed to open file for writing"));
Chris@207 76 m_ok = false;
Chris@148 77 return false;
Chris@148 78 }
Chris@148 79
Chris@148 80 int bzError = BZ_OK;
Chris@148 81 m_bzFile = BZ2_bzWriteOpen(&bzError, m_file, 9, 0, 0);
Chris@148 82
Chris@148 83 if (!m_bzFile) {
Chris@148 84 fclose(m_file);
Chris@148 85 m_file = 0;
Chris@148 86 setErrorString(tr("Failed to open bzip2 stream for writing"));
Chris@207 87 m_ok = false;
Chris@148 88 return false;
Chris@148 89 }
Chris@148 90
Chris@148 91 // std::cerr << "BZipFileDevice: opened \"" << m_fileName.toStdString() << "\" for writing" << std::endl;
Chris@148 92
Chris@148 93 setErrorString(QString());
Chris@148 94 setOpenMode(mode);
Chris@148 95 return true;
Chris@148 96 }
Chris@148 97
Chris@148 98 if (mode & ReadOnly) {
Chris@148 99
Chris@148 100 m_file = fopen(m_fileName.toLocal8Bit().data(), "rb");
Chris@148 101 if (!m_file) {
Chris@148 102 setErrorString(tr("Failed to open file for reading"));
Chris@207 103 m_ok = false;
Chris@148 104 return false;
Chris@148 105 }
Chris@148 106
Chris@148 107 int bzError = BZ_OK;
Chris@148 108 m_bzFile = BZ2_bzReadOpen(&bzError, m_file, 0, 0, NULL, 0);
Chris@148 109
Chris@148 110 if (!m_bzFile) {
Chris@148 111 fclose(m_file);
Chris@148 112 m_file = 0;
Chris@148 113 setErrorString(tr("Failed to open bzip2 stream for reading"));
Chris@207 114 m_ok = false;
Chris@148 115 return false;
Chris@148 116 }
Chris@148 117
Chris@148 118 // std::cerr << "BZipFileDevice: opened \"" << m_fileName.toStdString() << "\" for reading" << std::endl;
Chris@148 119
Chris@148 120 m_atEnd = false;
Chris@148 121
Chris@148 122 setErrorString(QString());
Chris@148 123 setOpenMode(mode);
Chris@148 124 return true;
Chris@148 125 }
Chris@148 126
Chris@148 127 setErrorString(tr("Internal error (open for neither read nor write)"));
Chris@207 128 m_ok = false;
Chris@148 129 return false;
Chris@148 130 }
Chris@148 131
Chris@148 132 void
Chris@148 133 BZipFileDevice::close()
Chris@148 134 {
Chris@148 135 if (!m_bzFile) {
Chris@148 136 setErrorString(tr("File not open"));
Chris@207 137 m_ok = false;
Chris@148 138 return;
Chris@148 139 }
Chris@148 140
Chris@148 141 int bzError = BZ_OK;
Chris@148 142
Chris@148 143 if (openMode() & WriteOnly) {
Chris@148 144 unsigned int in = 0, out = 0;
Chris@148 145 BZ2_bzWriteClose(&bzError, m_bzFile, 0, &in, &out);
Chris@148 146 // std::cerr << "Wrote bzip2 stream (in=" << in << ", out=" << out << ")" << std::endl;
Chris@148 147 if (bzError != BZ_OK) {
Chris@148 148 setErrorString(tr("bzip2 stream write close error"));
Chris@148 149 }
Chris@148 150 fclose(m_file);
Chris@148 151 m_bzFile = 0;
Chris@148 152 m_file = 0;
Chris@207 153 m_ok = false;
Chris@148 154 return;
Chris@148 155 }
Chris@148 156
Chris@148 157 if (openMode() & ReadOnly) {
Chris@148 158 BZ2_bzReadClose(&bzError, m_bzFile);
Chris@148 159 if (bzError != BZ_OK) {
Chris@148 160 setErrorString(tr("bzip2 stream read close error"));
Chris@148 161 }
Chris@148 162 fclose(m_file);
Chris@148 163 m_bzFile = 0;
Chris@148 164 m_file = 0;
Chris@207 165 m_ok = false;
Chris@148 166 return;
Chris@148 167 }
Chris@148 168
Chris@148 169 setErrorString(tr("Internal error (close for neither read nor write)"));
Chris@148 170 return;
Chris@148 171 }
Chris@148 172
Chris@148 173 qint64
Chris@148 174 BZipFileDevice::readData(char *data, qint64 maxSize)
Chris@148 175 {
Chris@148 176 if (m_atEnd) return 0;
Chris@148 177
Chris@148 178 int bzError = BZ_OK;
Chris@148 179 int read = BZ2_bzRead(&bzError, m_bzFile, data, maxSize);
Chris@148 180
Chris@148 181 // std::cerr << "BZipFileDevice::readData: requested " << maxSize << ", read " << read << std::endl;
Chris@148 182
Chris@148 183 if (bzError != BZ_OK) {
Chris@148 184 if (bzError != BZ_STREAM_END) {
Chris@148 185 std::cerr << "BZipFileDevice::readData: error condition" << std::endl;
Chris@148 186 setErrorString(tr("bzip2 stream read error"));
Chris@207 187 m_ok = false;
Chris@148 188 return -1;
Chris@148 189 } else {
Chris@148 190 // std::cerr << "BZipFileDevice::readData: reached end of file" << std::endl;
Chris@148 191 m_atEnd = true;
Chris@148 192 }
Chris@148 193 }
Chris@148 194
Chris@148 195 return read;
Chris@148 196 }
Chris@148 197
Chris@148 198 qint64
Chris@148 199 BZipFileDevice::writeData(const char *data, qint64 maxSize)
Chris@148 200 {
Chris@148 201 int bzError = BZ_OK;
Chris@148 202 BZ2_bzWrite(&bzError, m_bzFile, (void *)data, maxSize);
Chris@148 203
Chris@148 204 // std::cerr << "BZipFileDevice::writeData: " << maxSize << " to write" << std::endl;
Chris@148 205
Chris@148 206 if (bzError != BZ_OK) {
Chris@148 207 std::cerr << "BZipFileDevice::writeData: error condition" << std::endl;
Chris@148 208 setErrorString("bzip2 stream write error");
Chris@207 209 m_ok = false;
Chris@148 210 return -1;
Chris@148 211 }
Chris@148 212
Chris@148 213 // std::cerr << "BZipFileDevice::writeData: wrote " << maxSize << std::endl;
Chris@148 214
Chris@148 215 return maxSize;
Chris@148 216 }
Chris@148 217