Fix for [#30499] video sequencer crashes when moving around within a sequence.
[blender.git] / intern / audaspace / intern / AUD_SequencerReader.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * Copyright 2009-2011 Jörg Hermann Müller
5  *
6  * This file is part of AudaSpace.
7  *
8  * Audaspace is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * AudaSpace is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Audaspace; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file audaspace/intern/AUD_SequencerReader.cpp
26  *  \ingroup audaspaceintern
27  */
28
29
30 #include "AUD_SequencerReader.h"
31
32 typedef std::list<AUD_Reference<AUD_SequencerHandle> >::iterator AUD_HandleIterator;
33 typedef std::list<AUD_Reference<AUD_SequencerEntry> >::iterator AUD_EntryIterator;
34
35 AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, bool quality) :
36         m_position(0), m_device(factory->m_specs), m_factory(factory), m_status(0), m_entry_status(0)
37 {
38         m_device.setQuality(quality);
39 }
40
41 AUD_SequencerReader::~AUD_SequencerReader()
42 {
43 }
44
45 bool AUD_SequencerReader::isSeekable() const
46 {
47         return true;
48 }
49
50 void AUD_SequencerReader::seek(int position)
51 {
52         if(position < 0)
53                 return;
54
55         m_position = position;
56
57         for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++)
58         {
59                 (*it)->seek(position / m_factory->m_specs.rate);
60         }
61 }
62
63 int AUD_SequencerReader::getLength() const
64 {
65         return -1;
66 }
67
68 int AUD_SequencerReader::getPosition() const
69 {
70         return m_position;
71 }
72
73 AUD_Specs AUD_SequencerReader::getSpecs() const
74 {
75         return m_factory->m_specs;
76 }
77
78 void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
79 {
80         m_factory->lock();
81
82         if(m_factory->m_status != m_status)
83         {
84                 m_device.changeSpecs(m_factory->m_specs);
85                 m_device.setSpeedOfSound(m_factory->m_speed_of_sound);
86                 m_device.setDistanceModel(m_factory->m_distance_model);
87                 m_device.setDopplerFactor(m_factory->m_doppler_factor);
88
89                 m_status = m_factory->m_status;
90         }
91
92         if(m_factory->m_entry_status != m_entry_status)
93         {
94                 std::list<AUD_Reference<AUD_SequencerHandle> > handles;
95
96                 AUD_HandleIterator hit = m_handles.begin();
97                 AUD_EntryIterator  eit = m_factory->m_entries.begin();
98
99                 int result;
100                 AUD_Reference<AUD_SequencerHandle> handle;
101
102                 while(hit != m_handles.end() && eit != m_factory->m_entries.end())
103                 {
104                         handle = *hit;
105                         AUD_Reference<AUD_SequencerEntry> entry = *eit;
106
107                         result = handle->compare(entry);
108
109                         if(result < 0)
110                         {
111                                 try
112                                 {
113                                         handle = new AUD_SequencerHandle(entry, m_device);
114                                         handles.push_front(handle);
115                                 }
116                                 catch(AUD_Exception&)
117                                 {
118                                 }
119                                 eit++;
120                         }
121                         else if(result == 0)
122                         {
123                                 handles.push_back(handle);
124                                 hit++;
125                                 eit++;
126                         }
127                         else
128                         {
129                                 handle->stop();
130                                 hit++;
131                         }
132                 }
133
134                 while(hit != m_handles.end())
135                 {
136                         (*hit)->stop();
137                         hit++;
138                 }
139
140                 while(eit != m_factory->m_entries.end())
141                 {
142                         try
143                         {
144                                 handle = new AUD_SequencerHandle(*eit, m_device);
145                                 handles.push_front(handle);
146                         }
147                         catch(AUD_Exception&)
148                         {
149                         }
150                         eit++;
151                 }
152
153                 m_handles = handles;
154
155                 m_entry_status = m_factory->m_entry_status;
156         }
157
158         AUD_Specs specs = m_factory->m_specs;
159         int pos = 0;
160         float time = float(m_position) / float(specs.rate);
161         float volume, frame;
162         int len, cfra;
163         AUD_Vector3 v, v2;
164         AUD_Quaternion q;
165
166
167         while(pos < length)
168         {
169                 frame = time * m_factory->m_fps;
170                 cfra = int(floor(frame));
171
172                 len = int(ceil((cfra + 1) / m_factory->m_fps * specs.rate)) - m_position;
173                 len = AUD_MIN(length - pos, len);
174                 len = AUD_MAX(len, 1);
175
176                 for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++)
177                 {
178                         (*it)->update(time, frame, m_factory->m_fps);
179                 }
180
181                 m_factory->m_volume.read(frame, &volume);
182                 if(m_factory->m_muted)
183                         volume = 0.0f;
184                 m_device.setVolume(volume);
185
186                 m_factory->m_orientation.read(frame, q.get());
187                 m_device.setListenerOrientation(q);
188                 m_factory->m_location.read(frame, v.get());
189                 m_device.setListenerLocation(v);
190                 m_factory->m_location.read(frame + 1, v2.get());
191                 v2 -= v;
192                 m_device.setListenerVelocity(v2 * m_factory->m_fps);
193
194                 m_device.read(reinterpret_cast<data_t*>(buffer + specs.channels * pos), len);
195
196                 pos += len;
197                 time += float(len) / float(specs.rate);
198         }
199
200         m_factory->unlock();
201
202         m_position += length;
203
204         eos = false;
205 }