]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/mmedia/sndaiff.cpp
added protection against corrupted GIFs in ReadGIF
[wxWidgets.git] / contrib / src / mmedia / sndaiff.cpp
CommitLineData
e8482f24
GL
1// --------------------------------------------------------------------------
2// Name: sndaiff.cpp
3// Purpose:
4// Date: 08/11/1999
5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
6// CVSID: $Id$
58b9c9ba 7// wxWindows licence
e8482f24 8// --------------------------------------------------------------------------
e8482f24
GL
9
10#include "wx/wxprec.h"
11
12#ifndef WX_PRECOMP
13 #include "wx/defs.h"
14#endif
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#include "wx/stream.h"
21#include "wx/datstrm.h"
22#include "wx/filefn.h"
23
24#include "wx/mmedia/sndbase.h"
25#include "wx/mmedia/sndcodec.h"
26#include "wx/mmedia/sndfile.h"
27#include "wx/mmedia/sndpcm.h"
28#include "wx/mmedia/sndaiff.h"
29
30#define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
31
32#define FORM_SIGNATURE BUILD_SIGNATURE('F','O','R','M')
33#define AIFF_SIGNATURE BUILD_SIGNATURE('A','I','F','F')
34#define AIFC_SIGNATURE BUILD_SIGNATURE('A','I','F','C')
35#define COMM_SIGNATURE BUILD_SIGNATURE('C','O','M','M')
36#define SSND_SIGNATURE BUILD_SIGNATURE('S','S','N','D')
37
38wxSoundAiff::wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound)
39 : wxSoundFileStream(stream, io_sound)
40{
41 m_base_offset = wxInvalidOffset;
42}
43
44wxSoundAiff::wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound)
45 : wxSoundFileStream(stream, io_sound)
46{
47 m_base_offset = wxInvalidOffset;
48}
49
50wxSoundAiff::~wxSoundAiff()
51{
52}
53
54wxString wxSoundAiff::GetCodecName() const
55{
f815011f 56 return wxT("wxSoundAiff codec");
e8482f24
GL
57}
58
59bool wxSoundAiff::CanRead()
60{
61 wxUint32 signature1, signature2, len;
62
63 if (m_input->Read(&signature1, 4).LastRead() != 4)
dea7e44a 64 return false;
e8482f24
GL
65
66 if (wxUINT32_SWAP_ON_BE(signature1) != FORM_SIGNATURE) {
67 m_input->Ungetch(&signature1, 4);
dea7e44a 68 return false;
e8482f24
GL
69 }
70
71 m_input->Read(&len, 4);
72 if (m_input->LastRead() != 4) {
73 m_input->Ungetch(&len, m_input->LastRead());
74 m_input->Ungetch(&signature1, 4);
dea7e44a 75 return false;
e8482f24
GL
76 }
77
78 if (m_input->Read(&signature2, 4).LastRead() != 4) {
79 m_input->Ungetch(&signature2, m_input->LastRead());
80 m_input->Ungetch(&len, 4);
81 m_input->Ungetch(&signature1, 4);
dea7e44a 82 return false;
e8482f24
GL
83 }
84
85 m_input->Ungetch(&signature2, 4);
86 m_input->Ungetch(&len, 4);
87 m_input->Ungetch(&signature1, 4);
88
89 if (
90 wxUINT32_SWAP_ON_BE(signature2) != AIFF_SIGNATURE &&
91 wxUINT32_SWAP_ON_BE(signature2) != AIFC_SIGNATURE)
dea7e44a 92 return false;
e8482f24 93
dea7e44a 94 return true;
e8482f24
GL
95}
96
dea7e44a 97#define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return false; }
e8482f24
GL
98
99bool wxSoundAiff::PrepareToPlay()
100{
101 wxDataInputStream data(*m_input);
102 wxUint32 signature, len, ssnd;
103 bool end_headers;
104
105 if (!m_input) {
106 m_snderror = wxSOUND_INVSTRM;
dea7e44a 107 return false;
e8482f24
GL
108 }
109 m_snderror = wxSOUND_NOERROR;
110
dea7e44a 111 data.BigEndianOrdered(true);
e8482f24
GL
112
113 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
114 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != FORM_SIGNATURE, wxSOUND_INVSTRM);
115 // "FORM"
116
117 len = data.Read32();
2b3644c7 118 wxUnusedVar(len);
e8482f24
GL
119 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
120 // dummy len
121
122 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
123 FAIL_WITH(
124 wxUINT32_SWAP_ON_BE(signature) != AIFF_SIGNATURE &&
125 wxUINT32_SWAP_ON_BE(signature) != AIFC_SIGNATURE, wxSOUND_INVSTRM);
126 // "AIFF" / "AIFC"
127
dea7e44a 128 end_headers = false;
e8482f24
GL
129 while (!end_headers) {
130 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
131
132 len = data.Read32();
133 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
134
135 switch (wxUINT32_SWAP_ON_BE(signature)) {
136 case COMM_SIGNATURE: { // "COMM"
137 wxUint16 channels, bps;
138 wxUint32 num_samples;
139 double srate;
140 wxSoundFormatPcm sndformat;
141
142 // Get sound data informations
143 data >> channels >> num_samples >> bps >> srate;
144
145 // Convert them in a wxSoundFormat object
146 sndformat.SetSampleRate((wxUint32) srate);
147 sndformat.SetBPS(bps);
148 sndformat.SetChannels(channels);
dea7e44a 149 sndformat.Signed(false);
e8482f24
GL
150 sndformat.SetOrder(wxBIG_ENDIAN);
151
152 if (!SetSoundFormat(sndformat))
dea7e44a 153 return false;
e8482f24
GL
154 // We pass all data left
155 m_input->SeekI(len-18, wxFromCurrent);
156 break;
157 }
158 case SSND_SIGNATURE: { // "SSND"
159 data >> ssnd;
160 // m_input->SeekI(4, wxFromCurrent); // Pass an INT32
161 // m_input->SeekI(len-4, wxFromCurrent); // Pass the rest
162 m_input->SeekI(ssnd + 4, wxFromCurrent);
163 m_base_offset = m_input->TellI();
164 // len-8 bytes of samples
165 FinishPreparation(len - 8);
dea7e44a 166 end_headers = true;
e8482f24
GL
167 break;
168 }
169 default:
170 m_input->SeekI(len, wxFromCurrent);
171 break;
172 }
173 }
dea7e44a 174 return true;
e8482f24
GL
175}
176
42c37dec 177bool wxSoundAiff::PrepareToRecord(wxUint32 WXUNUSED(time))
e8482f24
GL
178{
179 // TODO
dea7e44a 180 return false;
e8482f24
GL
181}
182
183bool wxSoundAiff::FinishRecording()
184{
185 // TODO
dea7e44a 186 return false;
e8482f24
GL
187}
188
42c37dec 189bool wxSoundAiff::RepositionStream(wxUint32 WXUNUSED(position))
e8482f24
GL
190{
191 // If the stream is not seekable "TellI() returns wxInvalidOffset" we cannot reposition stream
192 if (m_base_offset == wxInvalidOffset)
dea7e44a 193 return false;
e8482f24 194 m_input->SeekI(m_base_offset, wxFromStart);
dea7e44a 195 return true;
e8482f24
GL
196}
197
198wxUint32 wxSoundAiff::GetData(void *buffer, wxUint32 len)
199{
200 return m_input->Read(buffer, len).LastRead();
201}
202
203wxUint32 wxSoundAiff::PutData(const void *buffer, wxUint32 len)
204{
205 return m_output->Write(buffer, len).LastWrite();
206}