Copyright fixes and mpg321 support - Alex
[terminatorX.git] / src / tX_sequencer.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2002  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_sequencer.cc
20  
21     Description: Well, implements the sequencer as you might have
22                  guessed.
23 */ 
24
25 #include "tX_sequencer.h"
26 #include "tX_mastergui.h"
27 #include "tX_global.h"
28
29 tX_sequencer sequencer;
30
31 tX_sequencer :: tX_sequencer()
32 {
33         current_timestamp=0;
34         start_timestamp=0;
35         max_timestamp=0;
36         next_event=song_list.begin();
37         mode=TX_SEQMODE_PLAYONLY;
38         run=0;
39         pthread_mutex_init(&record_lock, NULL);
40 }
41
42 tX_sequencer :: ~tX_sequencer()
43 {
44 }
45
46 void tX_sequencer :: set_timestamp(u_int32_t timestamp)
47 {
48         current_timestamp=0;
49         start_timestamp=0;
50         next_event=song_list.begin();
51 }
52
53 void tX_sequencer :: step()
54 {
55         if (!run) return;
56                 
57         while ((next_event != song_list.end()) && ((*next_event)->get_timestamp()==current_timestamp))
58         {
59                 (*next_event)->playback();
60                 next_event++;
61         }
62
63         current_timestamp++;    
64 }
65
66 tX_event *tX_sequencer :: record_event (tX_seqpar *sp, float value)
67 {
68         tX_event *new_event;
69         
70         new_event=new tX_event(current_timestamp, value, sp);
71         
72         pthread_mutex_lock(&record_lock);
73         record_list.push_back(new_event);
74         pthread_mutex_unlock(&record_lock);
75         
76         return new_event;
77 }
78
79 int tX_sequencer :: trig_rec()
80 {
81         //set_timestamp(0);
82         record_start_timestamp=start_timestamp;
83
84         mode = TX_SEQMODE_PLAYREC;
85         return 1;
86 }
87
88 int tX_sequencer :: trig_play()
89 {
90 //      set_timestamp(0);
91         run=1;
92         return 1;
93 }
94
95
96 //#define SEQ_DEBUG 1
97 //#define SEQ_DEBUG_MAX 1
98
99 void tX_sequencer :: trig_stop()
100 {
101         list <tX_event *> :: iterator song_event;
102         list <tX_event *> :: iterator temp_song_event;
103         list <tX_event *> :: iterator record_event;
104         tX_seqpar *sp;
105
106         int oldmode=mode;
107
108         mode = TX_SEQMODE_PLAYONLY;
109         run=0;
110
111         record_stop_timestamp=current_timestamp;
112         
113         if (oldmode==TX_SEQMODE_PLAYREC)
114         {
115                 pthread_mutex_lock(&record_lock);
116 #ifdef SEQ_DEBUG                
117                 printf ("Recorded from %i to %i.\n", record_start_timestamp, record_stop_timestamp);
118                 printf ("* Song: %i events, Recorded: %i events, sum=%i\n", song_list.size(), record_list.size(), song_list.size() + record_list.size());
119 #endif          
120                 /* removing all events for touched parameters in song_list */
121                 
122                 song_event=song_list.begin();
123
124                 while ((song_event!=song_list.end()) && ((*song_event)->get_timestamp() < record_start_timestamp))
125                         song_event++;
126
127                 while ((song_event!=song_list.end()) && ((*song_event)->get_timestamp() <= record_stop_timestamp))
128                 {
129                         sp = (*song_event)->get_sp();
130 #ifdef SEQ_DEBUG_MAX                    
131                         printf("sp %08x (%i) touched at: %i - timestamp %i.\n", sp, sp->is_touched(), sp->get_touch_timestamp(), (*song_event)->get_timestamp());
132 #endif                  
133                         
134                         if (sp->is_touched() && (sp->get_touch_timestamp()<= (*song_event)->get_timestamp()))
135                         {
136                                 temp_song_event=song_event;
137                                 song_event++;
138                                 delete (*temp_song_event);
139                                 song_list.erase(temp_song_event);
140                         }
141                         else
142                         {
143                                 song_event++;
144                         }
145                 }
146
147                 /* inserting all recorded events into song_list */
148                                         
149                 for (record_event=record_list.begin(), song_event=song_list.begin(); record_event != record_list.end();)
150                 {
151                         if (song_event==song_list.end())
152                         {
153                                 song_list.insert(song_event, record_event, record_list.end());
154                                 break;
155                         }
156                         
157                         if ((*song_event)->get_timestamp() >= (*record_event)->get_timestamp())
158                         {
159 /*                              if (song_event==song_list.begin()) song_list.push_front((*record_event));
160                                 else */
161                                 song_list.insert(song_event, (*record_event));                          
162                                 record_event++;
163                         }
164                         else 
165                         {
166                                 song_event++;
167                         }
168                 }
169 //              swap(song_list, record_list);
170                 record_list.erase(record_list.begin(), record_list.end());      
171
172 #ifdef SEQ_DEBUG                
173                 printf ("- Song: %i events, Recorded: %i events, sum=%i\n", song_list.size(), record_list.size(), song_list.size() + record_list.size());
174 #endif          
175                 
176                 pthread_mutex_unlock(&record_lock);
177         }
178
179         tX_seqpar::untouch_all();
180         
181         song_event=song_list.end();
182         
183         if (song_event!=song_list.begin()) 
184         {
185                 song_event--;
186                 max_timestamp=(*song_event)->get_timestamp();
187         }
188         
189 #ifdef SEQ_DEBUG_MAX
190         /*dump song_list */
191         
192         for (song_event=song_list.begin(); song_event!=song_list.end(); song_event++)
193         {
194                 printf ("%-15s| %-27s| %8i | %10f\n", (*song_event)->get_vtt_name(), (*song_event)->get_seqpar_name(), (*song_event)->get_timestamp(), (*song_event)->get_value());
195         }
196 #endif  
197
198         current_timestamp=start_timestamp;
199         seq_update();
200 }
201
202 void tX_sequencer :: delete_all_events_for_sp(tX_seqpar *sp)
203 {
204         list <tX_event *> :: iterator song_event;
205         list <tX_event *> :: iterator temp_song_event;
206         
207 #ifdef SEQ_DEBUG
208         int ctr=0;
209 #endif          
210         
211         for (song_event=song_list.begin(); song_event!=song_list.end();)
212         {
213                 if (sp == (*song_event)->get_sp())
214                 {
215                         temp_song_event=song_event;
216                         song_event++;
217                         delete (*temp_song_event);
218                         song_list.erase(temp_song_event);
219 #ifdef SEQ_DEBUG
220                         ctr++;
221 #endif                  
222                 }
223                 else
224                 {
225                         song_event++;
226                 }
227         }
228 #ifdef SEQ_DEBUG
229         printf ("removed %i events for seqpar %08x.\n", ctr, sp);
230 #endif                          
231 }
232
233 void tX_sequencer :: save(FILE *out)
234 {
235         u_int32_t event_count;
236         list <tX_event *> :: iterator song_event;
237         
238         event_count=song_list.size();
239         
240         fwrite((void *) &event_count,  sizeof(event_count), 1, out);
241         
242         for (song_event=song_list.begin(); song_event!=song_list.end(); song_event++)
243         {
244                 (*song_event)->store(out);
245         }
246 }
247
248 void tX_sequencer :: load(FILE *in)
249 {
250         u_int32_t event_count=0;
251         u_int32_t i;
252         tX_event *new_event=NULL;
253         
254         clear();
255         
256         fread ((void *) &event_count, sizeof(event_count), 1, in);
257         
258         max_timestamp=0;
259         
260         for (i=0; i<event_count; i++)
261         {
262                 new_event=new tX_event(in);
263                 song_list.push_back(new_event);
264         }
265         
266         start_timestamp=0;
267         current_timestamp=0;
268         
269         if (new_event) max_timestamp=new_event->get_timestamp();
270 }
271
272 void tX_sequencer :: clear()
273 {
274         if (song_list.size()==0) return;
275         
276         song_list.erase(song_list.begin(), song_list.end());
277         
278         current_timestamp=0;
279         max_timestamp=0;
280         start_timestamp=0;
281 }
282
283
284 u_int32_t tX_sequencer :: set_start_timestamp(float pos)
285 {
286         u_int32_t timestamp;
287         
288         if (pos>99.999) pos=99.999;
289         
290         pos/=100;
291         
292         timestamp = (u_int32_t) (((float) max_timestamp) * pos);
293         
294         start_timestamp=timestamp;
295         
296         return start_timestamp;
297 }
298
299 void tX_sequencer :: forward_to_start_timestamp(int dont_fake)
300 {
301         int gui_update_max, gui_update;
302         int run_save=run;
303         
304         run=1;
305         //if (!run) return;
306         
307         gui_update_max=(globals.update_idle * (globals.update_delay+1) * globals.true_block_size) >> 1;
308 //      printf("%i\n", gui_update_max);
309         gui_update=gui_update_max;
310         
311         current_timestamp=0;
312         
313         next_event=song_list.begin();
314         
315         while (current_timestamp<start_timestamp)
316         {
317                 step();
318                 if (dont_fake)
319                 {
320                         vtt_class :: forward_all_turntables();
321                         
322                         gui_update--;           
323                         if (gui_update < 0)
324                         {
325                                 gui_update=gui_update_max;
326                                 seq_update();
327                                 while (gtk_events_pending()) gtk_main_iteration();
328                         }
329                 }
330         }
331         
332         run=run_save;
333         
334         tX_seqpar :: update_all_graphics();     
335         while (gtk_events_pending()) gtk_main_iteration();
336 }
337