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