Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / patch.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * Copyright (C) 2003-2016 Cinelerra CV contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "filexml.h"
24 #include "mwindow.h"
25 #include "module.h"
26 #include "modules.h"
27 #include "mwindowgui.h"
28 #include "patch.h"
29 #include "patchbay.h"
30 #include "mainsession.h"
31 #include "theme.h"
32 #include <string.h>
33
34 Patch::Patch(MWindow *mwindow, PatchBay *patchbay, int data_type) : ListItem<Patch>()
35 {
36         this->mwindow = mwindow;
37         this->patches = patchbay;
38         this->data_type = data_type;
39         record = play = automate = draw = 1;
40         title[0] = 0;
41 }
42
43 Patch::~Patch()
44 {
45         if(mwindow->gui)
46         {
47                 delete recordpatch;
48                 delete playpatch;
49                 delete autopatch;
50                 delete drawpatch;
51                 delete title_text;
52         }
53 }
54
55 void Patch::create_objects(char *text, int pixel)
56 {
57         int x, y;
58         this->pixel = pixel;
59         strcpy(title, text);
60
61         if(mwindow->gui)
62         {
63                 if(mwindow->session->tracks_vertical)
64                 {
65                         //x = patches->gui->w - pixel - mwindow->zoom_track;
66                         x = pixel + 3;
67                         y = 0;
68                 }
69                 else
70                 {
71                         x = 3;
72                         y = pixel;
73                 }
74
75                 patches->add_subwindow(recordpatch = new RecordPatchOld(mwindow, this, x, y));
76                 patches->add_subwindow(playpatch = new PlayPatchOld(mwindow, this, x, y));
77                 patches->add_subwindow(title_text = new TitlePatchOld(mwindow, this, text, x, y));
78                 //patches->add_subwindow(autotitle = new BC_Title(x + PATCH_AUTO_TITLE, y + PATCH_ROW2, "A", SMALLFONT));
79                 //patches->add_subwindow(autopatch = new AutoPatchOld(mwindow, this, x, y));
80                 //patches->add_subwindow(drawtitle = new BC_Title(x + PATCH_DRAW_TITLE, y + PATCH_ROW2, "D", SMALLFONT));
81                 patches->add_subwindow(drawpatch = new DrawPatchOld(mwindow, this, x, y));
82         }
83 }
84
85 int Patch::save(FileXML *xml)
86 {
87         xml->tag.set_title("PATCH");
88         xml->append_tag();
89
90         if(play)
91         {
92                 xml->tag.set_title("PLAY");
93                 xml->append_tag();
94                 xml->tag.set_title("/PLAY");
95                 xml->append_tag();
96         }
97
98         if(record)
99         {
100                 xml->tag.set_title("RECORD");
101                 xml->append_tag();
102                 xml->tag.set_title("/RECORD");
103                 xml->append_tag();
104         }
105
106         if(automate)
107         {
108                 xml->tag.set_title("AUTO");
109                 xml->append_tag();
110                 xml->tag.set_title("/AUTO");
111                 xml->append_tag();
112         }
113
114         if(draw)
115         {
116                 xml->tag.set_title("DRAW");
117                 xml->append_tag();
118                 xml->tag.set_title("/DRAW");
119                 xml->append_tag();
120         }
121
122         xml->tag.set_title("TITLE");
123         xml->append_tag();
124         xml->append_text(title);
125         xml->tag.set_title("/TITLE");
126         xml->append_tag();
127
128
129         xml->tag.set_title("/PATCH");
130         xml->append_tag();
131         xml->append_newline();
132         return 0;
133 }
134
135 int Patch::load(FileXML *xml)
136 {
137         int result = 0;
138         play = record = automate = draw = 0;    // defaults
139
140         do{
141                 result = xml->read_tag();
142
143                 if(!result)
144                 {
145                         if(xml->tag.title_is("/PATCH"))
146                         {
147                                 result = 1;
148                         }
149                         else
150                         if(xml->tag.title_is("PLAY"))
151                         {
152                                 play = 1;
153                         }
154                         else
155                         if(xml->tag.title_is("RECORD"))
156                         {
157                                 record = 1;
158                         }
159                         else
160                         if(xml->tag.title_is("AUTO"))
161                         {
162                                 automate = 1;
163                         }
164                         else
165                         if(xml->tag.title_is("DRAW"))
166                         {
167                                 draw = 1;
168                         }
169                         else
170                         if(xml->tag.title_is("TITLE"))
171                         {
172                                 strcpy(title, xml->read_text());
173                         }
174                 }
175         }while(!result);
176
177         if(mwindow->gui)
178         {
179                 playpatch->update(play);
180                 recordpatch->update(record);
181                 autopatch->update(automate);
182                 drawpatch->update(draw);
183                 title_text->update(title);
184         }
185         return 0;
186 }
187
188 int Patch::set_pixel(int pixel)
189 {         // must be top of track for track zoom
190         this->pixel = pixel;
191         if(mwindow->gui)
192         {
193                 if(mwindow->session->tracks_vertical)
194                 {
195                         pixel += 3;
196                         playpatch->reposition_window(pixel + PATCH_PLAY, playpatch->get_y());
197                         recordpatch->reposition_window(pixel + PATCH_REC, recordpatch->get_y());
198                         autopatch->reposition_window(pixel + PATCH_AUTO, autopatch->get_y());
199                         title_text->reposition_window(pixel, title_text->get_y());
200                         drawpatch->reposition_window(pixel + PATCH_DRAW, drawpatch->get_y());
201                 }
202                 else
203                 {
204                         playpatch->reposition_window(playpatch->get_x(), pixel + PATCH_ROW2);
205                         recordpatch->reposition_window(recordpatch->get_x(), pixel + PATCH_ROW2);
206                         autopatch->reposition_window(autopatch->get_x(), pixel + PATCH_ROW2);
207                         drawpatch->reposition_window(drawpatch->get_x(), pixel + PATCH_ROW2);
208                         title_text->reposition_window(title_text->get_x(), pixel + 3);
209                 }
210         }
211         return 0;
212 }
213
214 int Patch::set_title(char *new_title)
215 {
216         strcpy(title, new_title);
217         title_text->update(new_title);
218         return 0;
219 }
220
221 int Patch::flip_vertical()
222 {
223         if(mwindow->gui)
224         {
225                 if(mwindow->session->tracks_vertical)
226                 {
227                         playpatch->reposition_window(playpatch->get_x(), PATCH_ROW2);
228                         recordpatch->reposition_window(recordpatch->get_x(), PATCH_ROW2);
229                         autopatch->reposition_window(autopatch->get_x(), PATCH_ROW2);
230                         drawpatch->reposition_window(drawpatch->get_x(), PATCH_ROW2);
231                         title_text->reposition_window(title_text->get_x(), 3);
232                 }
233                 else
234                 {
235                         playpatch->reposition_window(PATCH_PLAY, playpatch->get_y());
236                         recordpatch->reposition_window(PATCH_REC, recordpatch->get_y());
237                         autopatch->reposition_window(PATCH_AUTO, autopatch->get_y());
238                         drawpatch->reposition_window(PATCH_DRAW, drawpatch->get_y());
239                         title_text->reposition_window(PATCH_TITLE, title_text->get_y());
240                 }
241                 set_pixel(pixel);
242         }
243         return 0;
244 }
245
246
247 int Patch::pixelmovement(int distance)
248 {
249         if(mwindow->gui)
250         {
251                 pixel -= distance;
252                 set_pixel(pixel);
253         }
254         return 0;
255 }
256
257 Module* Patch::get_module()    // return corresponding module from console
258 {
259 //      return mwindow->console->modules->module_number(patches->number_of(this));
260 }
261
262 PlayPatchOld::PlayPatchOld(MWindow *mwindow, Patch *patch, int x, int y)
263  : BC_Toggle(x + PATCH_PLAY,
264         y + PATCH_ROW2,
265         mwindow->theme->playpatch_data,
266         1,
267         "",
268         1,
269         0,
270         0)
271 {
272         this->patch = patch;
273         patches = patch->patches;
274 }
275
276
277 int PlayPatchOld::handle_event()
278 {
279 // get the total selected before this event
280         if(shift_down())
281         {
282                 int total_selected = patches->plays_selected();
283
284                 if(total_selected == 0)
285                 {
286 // nothing previously selected
287                         patches->select_all_play();
288                 }
289                 else
290                 if(total_selected == 1)
291                 {
292                         if(patch->play)
293                         {
294 // this patch was previously the only one on
295                                 patches->select_all_play();
296                         }
297                         else
298                         {
299 // another patch was previously the only one on
300                                 patches->deselect_all_play();
301                                 patch->play = 1;
302                         }
303                 }
304                 else
305                 if(total_selected > 1)
306                 {
307                         patches->deselect_all_play();
308                         patch->play = 1;
309                 }
310
311                 update(patch->play);
312         }
313         else
314         {
315                 patch->play = get_value();
316         }
317         patches->button_down = 1;
318         patches->reconfigure_trigger = 1;
319         patches->new_status = get_value();
320         return 1;
321 }
322
323 int PlayPatchOld::button_release()
324 {
325         return 0;
326 }
327
328 int PlayPatchOld::cursor_moved_over()
329 {
330         if(patches->button_down && patches->new_status != get_value())
331         {
332                 update(patches->new_status);
333                 patch->play = get_value();
334                 return 1;
335         }
336         return 0;
337 }
338
339 RecordPatchOld::RecordPatchOld(MWindow *mwindow, Patch *patch, int x, int y)
340  : BC_Toggle(x + PATCH_REC,
341         y + PATCH_ROW2,
342         mwindow->theme->recordpatch_data,
343         1,
344         "",
345         1,
346         0,
347         0)
348 {
349         this->patch = patch;
350         patches = patch->patches;
351 }
352
353 int RecordPatchOld::handle_event()
354 {
355 // get the total selected before this event
356         if(shift_down())
357         {
358                 int total_selected = patches->records_selected();
359
360                 if(total_selected == 0)
361                 {
362 // nothing previously selected
363                         patches->select_all_record();
364                 }
365                 else
366                 if(total_selected == 1)
367                 {
368                         if(patch->record)
369                         {
370 // this patch was previously the only one on
371                                 patches->select_all_record();
372                         }
373                         else
374                         {
375 // another patch was previously the only one on
376                                 patches->deselect_all_record();
377                                 patch->record = 1;
378                         }
379                 }
380                 else
381                 if(total_selected > 1)
382                 {
383                         patches->deselect_all_record();
384                         patch->record = 1;
385                 }
386
387                 update(patch->record);
388         }
389         else
390         {
391                 patch->record = get_value();
392         }
393         patches->button_down = 1;
394         patches->new_status = get_value();
395         return 1;
396 }
397
398 int RecordPatchOld::button_release()
399 {
400         //if(patches->button_down)
401         //{
402         //      patches->button_down = 0;
403 // restart the playback
404                 //patches->mwindow->start_reconfigure(1);
405                 //patches->mwindow->stop_reconfigure(1);
406         //}
407         return 0;
408 }
409
410 int RecordPatchOld::cursor_moved_over()
411 {
412         if(patches->button_down && patches->new_status != get_value())
413         {
414                 update(patches->new_status);
415                 patch->record = get_value();
416                 return 1;
417         }
418         return 0;
419 }
420
421 TitlePatchOld::TitlePatchOld(MWindow *mwindow, Patch *patch, char *text, int x, int y)
422  : BC_TextBox(x, y + PATCH_TITLE, 124, 1, text, 0)
423 {
424         this->patch = patch;
425         patches = patch->patches;
426         module = 0;
427 }
428
429 int TitlePatchOld::handle_event()
430 {
431         if(!module) module = patch->get_module();
432         module->set_title(get_text());
433         strcpy(patch->title, get_text());
434         return 1;
435 }
436
437 DrawPatchOld::DrawPatchOld(MWindow *mwindow, Patch *patch, int x, int y)
438  : BC_Toggle(x + PATCH_DRAW,
439         y + PATCH_ROW2,
440         mwindow->theme->drawpatch_data,
441         1,
442         "",
443         1,
444         0,
445         0)
446 {
447         this->patch = patch;
448         this->patches = patch->patches;
449 }
450
451 int DrawPatchOld::handle_event()
452 {
453 // get the total selected before this event
454         if(shift_down())
455         {
456                 int total_selected = patches->draws_selected();
457
458                 if(total_selected == 0)
459                 {
460 // nothing previously selected
461                         patches->select_all_draw();
462                 }
463                 else
464                 if(total_selected == 1)
465                 {
466                         if(patch->draw)
467                         {
468 // this patch was previously the only one on
469                                 patches->select_all_draw();
470                         }
471                         else
472                         {
473 // another patch was previously the only one on
474                                 patches->deselect_all_draw();
475                                 patch->draw = 1;
476                         }
477                 }
478                 else
479                 if(total_selected > 1)
480                 {
481                         patches->deselect_all_draw();
482                         patch->draw = 1;
483                 }
484
485                 update(patch->draw);
486         }
487         else
488         {
489                 patch->draw = get_value();
490         }
491         patches->button_down = 1;
492         patches->new_status = get_value();
493         return 1;
494 }
495
496 int DrawPatchOld::cursor_moved_over()
497 {
498         if(patches->button_down && patches->new_status != get_value())
499         {
500                 update(patches->new_status);
501                 patch->draw = get_value();
502         return 1;
503         }
504         return 0;
505 }