1 /*
2 * tracker/TrackerUpdate.cpp
3 *
4 * Copyright 2009 Peter Barth
5 *
6 * This file is part of Milkytracker.
7 *
8 * Milkytracker 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 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Milkytracker 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 Milkytracker. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include "Tracker.h"
24 #include "TabManager.h"
25 #include "TrackerConfig.h"
26 #include "PlayerController.h"
27 #include "PlayerMaster.h"
28 #include "ModuleEditor.h"
29 #include "ModuleServices.h"
30 #include "TabTitleProvider.h"
31 #include "EnvelopeEditor.h"
32 #include "PatternTools.h"
33 #include "PPUIConfig.h"
34 #include "Container.h"
35 #include "ListBox.h"
36 #include "StaticText.h"
37 #include "PatternEditorControl.h"
38 #include "EnvelopeEditorControl.h"
39 #include "PianoControl.h"
40 #include "PeakLevelControl.h"
41 #include "ScopesControl.h"
42 #include "SampleEditorControl.h"
43 #include "TrackerSettingsDatabase.h"
44 #include "SectionInstruments.h"
45 #include "SectionSamples.h"
46 #include "SectionHDRecorder.h"
47 #include "SectionQuickOptions.h"
48 #include "TabHeaderControl.h"
49 #include "PPOpenPanel.h"
50 #include "TitlePageManager.h"
51
52 #include "ControlIDs.h"
53
updateAboutToggleButton(pp_int32 id,bool b,bool repaint)54 void Tracker::updateAboutToggleButton(pp_int32 id, bool b, bool repaint/* = true*/)
55 {
56 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_ABOUT));
57 ASSERT(container);
58 PPButton* button = static_cast<PPButton*>(container->getControlByID(id));
59 if (button == NULL)
60 return;
61 button->setPressed(b);
62
63 if (repaint)
64 screen->paintControl(button);
65 }
66
updatePianoControl(PianoControl * pianoControl)67 bool Tracker::updatePianoControl(PianoControl* pianoControl)
68 {
69 if (!pianoControl)
70 return false;
71
72 if (!pianoControl->isVisible())
73 return false;
74
75 pp_int32 ins = listBoxInstruments->getSelectedIndex() + 1;
76
77 pp_int32 i;
78
79 bool tab[ModuleEditor::MAX_NOTE];
80
81 for (i = 0; i < ModuleEditor::MAX_NOTE; i++)
82 {
83 tab[i] = pianoControl->getNoteState(i);
84 pianoControl->pressNote(i, false);
85 }
86
87 for (i = 0; i < playerController->getPlayerNumPlayingChannels(); i++)
88 {
89 pp_int32 note;
90 bool muted = false;
91 if (playerController->isNotePlaying(ins, i, note, muted))
92 pianoControl->pressNote(note - 1, true, muted);
93 }
94
95 bool update = false;
96 for (i = 0; i < ModuleEditor::MAX_NOTE; i++)
97 {
98 if (pianoControl->getNoteState(i) != tab[i])
99 {
100 update = true;
101 break;
102 }
103 }
104
105 if (update)
106 screen->paintControl(pianoControl, false);
107
108 return update;
109 }
110
updatePeakLevelControl()111 bool Tracker::updatePeakLevelControl()
112 {
113 const pp_int32 maxPeakThreshold = 32700*2;
114
115 if (!peakLevelControl)
116 return false;
117
118 if (!peakLevelControl->isVisible())
119 return false;
120
121 bool bUpdateL = false;
122 bool bUpdateR = false;
123
124 bool bUpdateEntire = false;
125
126 pp_int32 left, right;
127 playerMaster->getCurrentSamplePeak(left, right);
128
129 // Left channel
130 pp_int32 oldPeak = peakLevelControl->getPeak(0);
131 pp_int32 newPeak = left << 1;
132 if (newPeak >= maxPeakThreshold)
133 {
134 TitlePageManager titlePageManager(*screen);
135 titlePageManager.setPeakControlHeadingColor(TrackerConfig::colorPeakClipIndicator, false);
136 bUpdateEntire = true;
137 }
138 if (newPeak < oldPeak)
139 {
140 newPeak = oldPeak;
141 newPeak -= 2048;
142 if (newPeak < 0)
143 newPeak = 0;
144 }
145 if (oldPeak != newPeak)
146 {
147 peakLevelControl->setPeak(0, newPeak);
148 bUpdateL = true;
149 }
150
151 // Right channel
152 oldPeak = peakLevelControl->getPeak(1);
153 newPeak = right << 1;
154 if (newPeak >= maxPeakThreshold)
155 {
156 TitlePageManager titlePageManager(*screen);
157 titlePageManager.setPeakControlHeadingColor(TrackerConfig::colorRecordModeButtonText, false);
158 bUpdateEntire = true;
159 }
160 if (newPeak < oldPeak)
161 {
162 newPeak = oldPeak;
163 newPeak -= 2048;
164 if (newPeak < 0)
165 newPeak = 0;
166 }
167 if (oldPeak != newPeak)
168 {
169 peakLevelControl->setPeak(1, newPeak);
170 bUpdateR = true;
171 }
172
173 if (bUpdateEntire)
174 {
175 screen->paintControl(screen->getControlByID(CONTAINER_ABOUT), false);
176 return true;
177 }
178 else if (bUpdateL || bUpdateR)
179 {
180 screen->paintControl(peakLevelControl, false);
181 return true;
182 }
183
184 return false;
185 }
186
updatePlayTime()187 bool Tracker::updatePlayTime()
188 {
189 if (!playTimeText)
190 return false;
191
192 if (!playTimeText->isVisible())
193 return false;
194
195 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_ABOUT));
196
197 char buffer[100], buffer2[100];
198
199 pp_int32 playtime = (pp_int32)playerController->getPlayTime();
200
201 if (!playerController->isPlaying())
202 playtime = 0;
203
204 pp_int32 seconds = playtime % 60;
205 pp_int32 minutes = (playtime / 60) % 60;
206 pp_int32 hours = (playtime / 3600) % 100;
207
208 sprintf(buffer,"%02i:%02i:%02i", hours, minutes, seconds);
209
210 playtime = moduleEditor->getModuleServices()->getEstimatedSongLength();
211 if (playtime == -1)
212 {
213 // strcpy(buffer2,"(--:--:--)");
214 // believe it or not, the VC 6.0 compiler
215 // fucks up the above strcpy, now providing some awesome workaround ;)
216 buffer2[0] = '(';
217 buffer2[1] = '-';
218 buffer2[2] = '-';
219 buffer2[3] = ':';
220 buffer2[4] = '-';
221 buffer2[5] = '-';
222 buffer2[6] = ':';
223 buffer2[7] = '-';
224 buffer2[8] = '-';
225 buffer2[9] = ')';
226 buffer2[10] = 0;
227 }
228 else
229 {
230 pp_int32 seconds = playtime % 60;
231 pp_int32 minutes = (playtime / 60) % 60;
232 pp_int32 hours = (playtime / 3600) % 100;
233 sprintf(buffer2,"(%02i:%02i:%02i)", hours, minutes, seconds);
234 }
235
236 strcat(buffer, buffer2);
237
238 if (strcmp(playTimeText->getText(), buffer) != 0)
239 {
240 playTimeText->setText(buffer);
241 screen->paintControl(container, false);
242 return true;
243 }
244
245 return false;
246 }
247
248 ///////////////////////////////////////////
249 // update song title
250 ///////////////////////////////////////////
updateSongTitle(bool repaint)251 void Tracker::updateSongTitle(bool repaint)
252 {
253 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_ABOUT));
254
255 PPListBox* listBox = static_cast<PPListBox*>(container->getControlByID(LISTBOX_SONGTITLE));
256
257 listBox->clear();
258 char str[MP_MAXTEXT+1];
259 moduleEditor->getTitle(str, ModuleEditor::MAX_TITLETEXT);
260
261 listBox->addItem(str);
262 listBox->setMaxEditSize(ModuleEditor::MAX_TITLETEXT);
263
264 screen->paintControl(container, repaint);
265 }
266
267 #ifdef __LOWRES__
updateJamMenuOrder(bool repaint)268 void Tracker::updateJamMenuOrder(bool repaint/* = true*/)
269 {
270 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_LOWRES_JAMMENU));
271 PPStaticText* staticText = static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_JAMMENU_CURORDER));
272 staticText->setHexValue(getOrderListBoxIndex(), 2);
273 if (container->isVisible())
274 screen->paintControl(container, repaint);
275 }
276 #endif
277
updateOrderlist(bool repaint)278 void Tracker::updateOrderlist(bool repaint/* = true*/)
279 {
280 // First of all: update orderlist (something might have been removed/added)
281 updateSongLength(false);
282 // Now update patterns
283 moduleEditor->setCurrentPatternIndex(moduleEditor->getOrderPosition(getOrderListBoxIndex()));
284 moduleEditor->setCurrentOrderIndex(getOrderListBoxIndex());
285
286 updatePattern(false);
287
288 if (repaint)
289 screen->update();
290 }
291
292 ///////////////////////////////////////////
293 // update song length field + orderlist
294 ///////////////////////////////////////////
updateSongLength(bool repaint)295 void Tracker::updateSongLength(bool repaint)
296 {
297 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_ORDERLIST));
298
299 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_ORDERLIST_SONGLENGTH))->setHexValue(moduleEditor->getNumOrders(), 2);
300
301 listBoxOrderList->setShowIndex(true);
302 listBoxOrderList->setIndexBaseCount(0);
303
304 listBoxOrderList->saveState();
305
306 bool update = true;
307 if (listBoxOrderList->getNumItems() != moduleEditor->getNumOrders())
308 {
309 listBoxOrderList->clear();
310 update = false;
311 }
312
313 for (pp_int32 i = 0; i < moduleEditor->getNumOrders(); i++)
314 {
315 char orderlistEntry[4];
316
317 PatternTools::convertToHex(orderlistEntry, moduleEditor->getOrderPosition(i), 2);
318
319 if (update)
320 listBoxOrderList->updateItem(i, orderlistEntry);
321 else
322 listBoxOrderList->addItem(orderlistEntry);
323 }
324
325 if (!update)
326 {
327 listBoxOrderList->restoreState();
328 listBoxOrderList->setSelectedIndex(moduleEditor->getCurrentOrderIndex());
329 }
330
331 screen->paintControl(container, repaint);
332 }
333
334 ///////////////////////////////////////////
335 // update song restart position field
336 ///////////////////////////////////////////
updateSongRepeat(bool repaint)337 void Tracker::updateSongRepeat(bool repaint)
338 {
339 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_ORDERLIST));
340 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_ORDERLIST_REPEAT))->setHexValue(moduleEditor->getRepeatPos(), 2);
341
342 screen->paintControl(container, repaint);
343 }
344
345 ///////////////////////////////////////////
346 // update speed field
347 ///////////////////////////////////////////
updateSpeed(bool repaint)348 bool Tracker::updateSpeed(bool repaint)
349 {
350 mp_sint32 speed, bpm, mainvol;
351
352 playerController->getSpeed(bpm, speed);
353 mainvol = playerController->getSongMainVolume();
354
355 if (bpm != lastBPM ||
356 lastSpeed != speed ||
357 lastMainVol != mainvol)
358 {
359 lastBPM = bpm;
360 lastSpeed = speed;
361 lastMainVol = mainvol;
362 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SPEED));
363 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_SPEED_SPEED))->setIntValue(speed, 2);
364 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_SPEED_BPM))->setIntValue(bpm, 3);
365 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_SPEED_MAINVOL))->setHexValue((mainvol*64)/255, 2);
366
367 screen->paintControl(container, repaint);
368 return true;
369 }
370 return false;
371 }
372
373 ///////////////////////////////////////////
374 // update pattern add field
375 ///////////////////////////////////////////
updatePatternAddAndOctave(bool repaint)376 void Tracker::updatePatternAddAndOctave(bool repaint)
377 {
378 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SPEED));
379
380 pp_int32 currentPatternAdd = getPatternEditorControl()->getRowInsertAdd();
381 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_SPEED_PATTERNADD))->setIntValue(currentPatternAdd, 2);
382 pp_int32 currentOctave = getPatternEditor()->getCurrentOctave();
383 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_SPEED_OCTAVE))->setIntValue(currentOctave-1, 2);
384
385 screen->paintControl(container, repaint);
386 }
387
388
389 ///////////////////////////////////////////
390 // update current pattern index
391 ///////////////////////////////////////////
updatePatternIndex(bool repaint)392 void Tracker::updatePatternIndex(bool repaint)
393 {
394 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_PATTERN));
395 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_PATTERN_INDEX))->setHexValue(moduleEditor->getCurrentPatternIndex(), 2);
396
397 #ifdef __LOWRES__
398 {
399 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_LOWRES_JAMMENU));
400 PPStaticText* staticText = static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_JAMMENU_CURPATTERN));
401 staticText->setHexValue(moduleEditor->getCurrentPatternIndex(), 2);
402 if (container->isVisible())
403 screen->paintControl(container, repaint);
404 }
405 #endif
406 screen->paintControl(container, repaint);
407 }
408
409 ///////////////////////////////////////////
410 // update current pattern's length
411 ///////////////////////////////////////////
updatePatternLength(bool repaint)412 void Tracker::updatePatternLength(bool repaint)
413 {
414 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_PATTERN));
415 static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_PATTERN_LENGTH))->setHexValue(getPatternEditor()->getNumRows(),3);
416
417 screen->paintControl(container, repaint);
418 }
419
420 ///////////////////////////////////////////
421 // update pattern and it's length and index
422 ///////////////////////////////////////////
updatePattern(bool repaint)423 void Tracker::updatePattern(bool repaint)
424 {
425 updatePatternEditorControl(false);
426 updatePatternIndex(false);
427 updatePatternLength(false);
428
429 if (repaint)
430 screen->update();
431 }
432
433 ///////////////////////////////////////////
434 // update samples listbox
435 ///////////////////////////////////////////
updateSamplesListBox(bool repaint)436 void Tracker::updateSamplesListBox(bool repaint)
437 {
438 listBoxSamples->saveState();
439
440 listBoxSamples->clear();
441
442 fillSampleListBox(listBoxSamples, listBoxInstruments->getSelectedIndex());
443
444 listBoxSamples->restoreState();
445
446 // check for visibility of parent container before updating
447 if (static_cast<PPContainer*>(screen->getControlByID(CONTAINER_INSTRUMENTLIST))->isVisible())
448 screen->paintControl(listBoxSamples, repaint);
449
450 #ifdef __LOWRES__
451 {
452 pp_int32 i = listBoxInstruments->getSelectedIndex();
453
454 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_LOWRES_JAMMENU));
455 PPStaticText* staticText = static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_JAMMENU_CURINSTRUMENT));
456 staticText->setHexValue(i+1, 2);
457 if (container->isVisible())
458 screen->paintControl(container, repaint);
459
460 container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_INSTRUMENTLIST));
461 staticText = static_cast<PPStaticText*>(container->getControlByID(STATICTEXT_INSTRUMENTS_ALTERNATIVEHEADER2));
462 staticText->setHexValue(i+1, 2);
463 if (container->isVisible())
464 screen->paintControl(container, repaint);
465 }
466 #endif
467 }
468
469 ///////////////////////////////////////////
470 // update instruments listbox
471 ///////////////////////////////////////////
updateInstrumentsListBox(bool repaint)472 void Tracker::updateInstrumentsListBox(bool repaint)
473 {
474 listBoxInstruments->saveState();
475
476 listBoxInstruments->clear();
477
478 fillInstrumentListBox(listBoxInstruments);
479
480 listBoxInstruments->restoreState();
481
482 // check for visibility of parent container before updating
483 if (!static_cast<PPContainer*>(screen->getControlByID(CONTAINER_INSTRUMENTLIST))->isVisible())
484 return;
485
486 screen->paintControl(listBoxInstruments, repaint);
487 }
488
489 ///////////////////////////////////////////
490 // update pattern editor
491 ///////////////////////////////////////////
updatePatternEditorControl(bool repaint,bool fast)492 void Tracker::updatePatternEditorControl(/*TXMPattern* pattern, */bool repaint/* = true*/, bool fast/* = false*/)
493 {
494 PatternEditorControl* patternEditorCtrl = getPatternEditorControl();
495
496 moduleEditor->reloadCurrentPattern();
497
498 TXMPattern* pattern = getPatternEditor()->getPattern();
499
500 if (pattern)
501 {
502 if (isEditingCurrentOrderlistPattern())
503 patternEditorCtrl->setOrderlistIndex(getOrderListBoxIndex());
504 else
505 patternEditorCtrl->setOrderlistIndex(-1);
506
507 //patternEditorCtrl->attachPattern(pattern, moduleEditor->getModule());
508 }
509
510 if (!fast)
511 screen->paintControl(patternEditorCtrl, repaint);
512 }
513
514 ///////////////////////////////////////////
515 // update instrument editor
516 ///////////////////////////////////////////
updateSampleEditor(bool repaint,bool force)517 void Tracker::updateSampleEditor(bool repaint, bool force)
518 {
519 sectionSamples->realUpdate(repaint, force, true);
520 }
521
updateSampleEditorAndInstrumentSection(bool repaint)522 void Tracker::updateSampleEditorAndInstrumentSection(bool repaint/* = true*/)
523 {
524 // update instrument/sample editor
525 // important: sample editor first => will reload sample into sample editor
526 updateSampleEditor(repaint);
527 sectionInstruments->update(repaint);
528 }
529
updateSongInfo(bool repaint)530 void Tracker::updateSongInfo(bool repaint/* = true*/)
531 {
532 updateSongTitle(repaint);
533
534 updateSongLength(repaint);
535 updateSongRepeat(repaint);
536
537 //updateBPM(repaint);
538 updateSpeed(repaint);
539 updatePatternAddAndOctave(repaint);
540
541 updatePatternIndex(repaint);
542 updatePatternLength(repaint);
543
544 updateInstrumentsListBox(repaint);
545 updateSamplesListBox(repaint);
546
547 getPatternEditorControl()->reset();
548 getPatternEditorControl()->unmuteAll();
549 sectionInstruments->resetEnvelopeEditor();
550 sectionInstruments->updateEnvelopeEditor(false, true);
551 sectionInstruments->resetPianoAssignment();
552 sectionSamples->resetSampleEditor();
553
554 setNumChannels(moduleEditor->getNumChannels(), false);
555
556 updatePatternEditorControl(repaint);
557
558 updateSampleEditorAndInstrumentSection(repaint);
559
560 updateWindowTitle(moduleEditor->getModuleFileName());
561
562 if (repaint)
563 screen->update();
564 }
565
updateInstrumentChooser(bool repaint)566 void Tracker::updateInstrumentChooser(bool repaint/* = true*/)
567 {
568 PPContainer* container = static_cast<PPContainer*>(screen->getModalControl());
569
570 PPListBox* listBoxSrc = static_cast<PPListBox*>(container->getControlByID(INSTRUMENT_CHOOSER_LIST_SRC));
571 PPListBox* listBoxSrcModule = static_cast<PPListBox*>(container->getControlByID(INSTRUMENT_CHOOSER_LIST_SRC3));
572 PPListBox* listBoxDst = static_cast<PPListBox*>(container->getControlByID(INSTRUMENT_CHOOSER_LIST_DST));
573 PPListBox* listBoxDstModule = static_cast<PPListBox*>(container->getControlByID(INSTRUMENT_CHOOSER_LIST_DST3));
574
575 ModuleEditor* src = listBoxSrcModule ? tabManager->getModuleEditorFromTabIndex(listBoxSrcModule->getSelectedIndex()) : this->moduleEditor;
576 ModuleEditor* dst = listBoxDstModule ? tabManager->getModuleEditorFromTabIndex(listBoxDstModule->getSelectedIndex()) : this->moduleEditor;
577
578 listBoxSrc->saveState();
579 listBoxSrc->clear();
580 fillInstrumentListBox(listBoxSrc, src);
581 listBoxSrc->restoreState();
582
583 listBoxDst->saveState();
584 listBoxDst->clear();
585 fillInstrumentListBox(listBoxDst, dst);
586 listBoxDst->restoreState();
587
588 mp_sint32 srcInsIndex = listBoxSrc->getSelectedIndex();
589 mp_sint32 dstInsIndex = listBoxDst->getSelectedIndex();
590
591 listBoxSrc = static_cast<PPListBox*>(container->getControlByID(INSTRUMENT_CHOOSER_LIST_SRC2));
592 listBoxDst = static_cast<PPListBox*>(container->getControlByID(INSTRUMENT_CHOOSER_LIST_DST2));
593
594 listBoxSrc->saveState();
595 listBoxSrc->clear();
596
597 fillSampleListBox(listBoxSrc, srcInsIndex, src);
598
599 listBoxSrc->restoreState();
600
601 listBoxDst->saveState();
602 listBoxDst->clear();
603
604 fillSampleListBox(listBoxDst, dstInsIndex, dst);
605
606 listBoxDst->restoreState();
607
608 if (repaint)
609 screen->update();
610 }
611
updateTabTitle()612 void Tracker::updateTabTitle()
613 {
614 TabHeaderControl* tabHeader = static_cast<TabHeaderControl*>(screen->getControlByID(TABHEADER_CONTROL));
615
616 if (tabHeader != NULL)
617 {
618 TabTitleProvider tabTitleProvider(*moduleEditor);
619 PPString tabTitle = tabTitleProvider.getTabTitle();
620 if (moduleEditor->hasChanged())
621 tabTitle.append("*");
622
623 bool refresh = false;
624
625 for (pp_int32 i = 0; i < (signed)tabHeader->getNumTabs(); i++)
626 {
627 if (tabManager->getModuleEditorFromTabIndex(i) == this->moduleEditor)
628 {
629 if (tabHeader->getTab(i)->text.compareTo(tabTitle) != 0)
630 {
631 tabHeader->setTabHeaderText(i, tabTitle);
632 refresh = true;
633 }
634 }
635 }
636
637 if (refresh)
638 screen->paintControl(tabHeader);
639 }
640 }
641
updateWindowTitle()642 void Tracker::updateWindowTitle()
643 {
644 if (moduleEditor->hasChanged() != lastState)
645 {
646 PPSystemString title = "MilkyTracker - ";
647
648 title.append(currentFileName);
649
650 if (moduleEditor->hasChanged())
651 title.append(" (modified)");
652
653 screen->setTitle(title);
654
655 updateTabTitle();
656
657 lastState = moduleEditor->hasChanged();
658 }
659 }
660
updateWindowTitle(const PPSystemString & fileName)661 void Tracker::updateWindowTitle(const PPSystemString& fileName)
662 {
663 lastState = !moduleEditor->hasChanged();
664
665 currentFileName = fileName.stripPath();
666
667 updateWindowTitle();
668 }
669
updateSongPosition(pp_int32 pos,pp_int32 row,bool fast)670 bool Tracker::updateSongPosition(pp_int32 pos/* = -1*/, pp_int32 row/* = -1*/, bool fast/* = false*/)
671 {
672 mp_sint32 thePos, theRow;
673 playerController->getPosition(thePos, theRow);
674
675 #if 0
676 static int counter = 0;
677 if (thePos == 0 && theRow == 63 && (theRow != lastRow || thePos != lastPos))
678 counter++;
679
680 if (counter == 2)
681 {
682 int i = 0;
683 i++;
684 i--;
685 }
686 #endif
687
688 if (pos == -1)
689 pos = thePos;
690 if (row == -1)
691 row = theRow;
692
693 bool redraw = false;
694
695 // I'm now trying to understand what happens here ------>
696 // When the current row is different from the last row
697 // or the current order position is different from the last one
698 // we're doing some screen refreshing
699 if (row != lastRow || pos != lastPos)
700 {
701 // if we're not playing a single pattern, we're most likely playing the entire song
702 // and in that case if we're instructed to follow the song while playing we're doing some
703 // order list position updates and stuff ------>
704 if (!playerController->isPlayingPattern() && shouldFollowSong())
705 {
706 // if the current order list index is different from the current
707 // order list position from the player UPDATE ------>
708 if (getOrderListBoxIndex() != pos)
709 {
710 listBoxOrderList->setSelectedIndex(pos, false);
711 moduleEditor->setCurrentOrderIndex(pos);
712 // in low res mode we also need to update
713 // the order position in the "Jam"-section
714 #ifdef __LOWRES__
715 if (!fast)
716 updateJamMenuOrder(false);
717 #endif
718 // now tell the module editor that we're editing another pattern
719 moduleEditor->setCurrentPatternIndex(moduleEditor->getOrderPosition(pos));
720 // update pattern editor with current order list pattern
721 // but don't redraw/update, just get it from the module editor and attach it to the pattern editor
722 updatePatternEditorControl(false, true);
723 }
724
725 if (!fast)
726 {
727 // update pattern property fields
728 updateSongLength(false);
729 updatePatternIndex(false);
730 updatePatternLength(false);
731 }
732
733 // only follow song if the pattern index matches the one from the
734 // order list, otherwise the user has probably selected a different
735 // pattern while playing takes place
736 if (moduleEditor->getCurrentPatternIndex() == moduleEditor->getOrderPosition(pos))
737 {
738 // song positon is only used in non-follow mode
739 getPatternEditorControl()->setSongPosition(-1, -1);
740 // but we should probably update the current row in the pattern editor as well
741 // as long as the user is not currently dragging the scroll bars in the sample editor
742 getPatternEditorControl()->setRow(row, fast ? false : !getPatternEditorControl()->isDraggingVertical());
743 }
744 }
745 else if (playerController->isPlayingPattern() && !shouldFollowSong())
746 {
747 // we're playing the current pattern and don't follow the song
748 // just update the current playing row in the pattern editor
749 if (playerController->isPlayingPattern(moduleEditor->getCurrentPatternIndex()))
750 getPatternEditorControl()->setSongPosition(-1, row);
751 // we're playing a pattern different from the one in the editor
752 // don't show any positions
753 else
754 getPatternEditorControl()->setSongPosition(-1, -1);
755 }
756 else if (playerController->isPlayingPattern() && shouldFollowSong())
757 {
758 getPatternEditorControl()->setSongPosition(-1, -1);
759 getPatternEditorControl()->setRow(row, fast ? false : !getPatternEditorControl()->isDraggingVertical());
760 }
761 else
762 {
763 getPatternEditorControl()->setSongPosition(pos, row);
764 }
765
766 updatePatternEditorControl(false, fast);
767
768 redraw = true;
769
770 lastRow = row;
771 lastPos = pos;
772 }
773
774 if (!fast)
775 return updateSpeed(false) || redraw;
776 else
777 return redraw;
778 }
779
updateRecordButton(PPContainer * container,const PPColor & pColor)780 void Tracker::updateRecordButton(PPContainer* container, const PPColor& pColor)
781 {
782 ASSERT(container);
783
784 // now if the parent container is visible,
785 // we're going to update the record button
786 if (container->isVisible())
787 {
788 // get button from container
789 PPButton* button = static_cast<PPButton*>(container->getControlByID(MAINMENU_EDIT));
790 ASSERT(button);
791
792 // if it's visible and the color is not what we're going to set
793 // set new text color and repaint
794 if (button->isVisible() && (&pColor) != button->getTextColor())
795 {
796 button->setTextColor(pColor);
797 screen->paintControl(button);
798 }
799 }
800 }
801
doFollowSong()802 void Tracker::doFollowSong()
803 {
804 // check if we need to update the record button
805 // this is done periodically and only in MilkyTracker mode
806 if (editMode == EditModeMilkyTracker)
807 {
808 // If the pattern editor has got the focus
809 // we're in record mode, so get the record button text color
810 const PPColor& pColor = getPatternEditorControl()->gotFocus() ? TrackerConfig::colorRecordModeButtonText : PPUIConfig::getInstance()->getColor(PPUIConfig::ColorDefaultButtonText);
811
812 // we're going to update the record button
813 updateRecordButton(static_cast<PPContainer*>(screen->getControlByID(CONTAINER_MENU)), pColor);
814
815 #ifdef __LOWRES__
816 // in low-res mode, the record buttons appears
817 // also in some other containers (e.g. TINYMENU) ...
818 updateRecordButton(static_cast<PPContainer*>(screen->getControlByID(CONTAINER_LOWRES_TINYMENU)), pColor);
819
820 // ... also the JAMMENU
821 updateRecordButton(static_cast<PPContainer*>(screen->getControlByID(CONTAINER_LOWRES_JAMMENU)), pColor);
822 #endif
823 }
824
825 // check if the piano has been updated
826 bool updatePiano = updatePianoControl(sectionInstruments->getPianoControl());
827
828 // check if the play time has been updated
829 bool updatePlayTime = this->updatePlayTime();
830
831 #ifdef __LOWRES__
832 // in low-res mode a piano might be embedded into other containers as well
833 // => check for updates
834 if (inputContainerCurrent->isVisible())
835 {
836 PianoControl* pianoControl = static_cast<PianoControl*>(inputContainerCurrent->getControlByID(PIANO_CONTROL));
837 updatePiano |= updatePianoControl(pianoControl);
838 }
839 else if (screen->getControlByID(CONTAINER_LOWRES_JAMMENU)->isVisible())
840 {
841 PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_LOWRES_JAMMENU));
842 PianoControl* pianoControl = static_cast<PianoControl*>(container->getControlByID(PIANO_CONTROL));
843 updatePiano |= updatePianoControl(pianoControl);
844 }
845 #endif
846
847 bool importantRefresh = false;
848
849 // now for updating the sample editor control
850 SampleEditorControl* sampleEditorControl = sectionSamples->getSampleEditorControl(false);
851
852 if (sampleEditorControl)
853 {
854 bool showMarksVisibleOld = sampleEditorControl->isVisible() ? sampleEditorControl->showMarksVisible() : false;
855 bool updateSample = false;
856
857 TXMSample* smp = getSampleEditor()->getSample();
858
859 for (pp_int32 i = 0; i < playerController->getAllNumPlayingChannels(); i++)
860 {
861 pp_int32 pos, vol, pan;
862 if (playerController->isSamplePlaying(*smp, i, pos, vol, pan))
863 {
864 // it is there
865 // => set the position mark
866 sampleEditorControl->setShowMark(i, pos, vol, pan);
867 updateSample = true;
868 }
869 else
870 {
871 // it is not there
872 // => clear the position mark
873 if (sampleEditorControl->getShowMarkPos(i) != -1)
874 {
875 sampleEditorControl->setShowMark(i, -1, 0);
876 updateSample = true;
877 }
878 }
879 }
880
881 if (updateSample && sampleEditorControl->isVisible())
882 {
883 bool showMarksVisible = sampleEditorControl->showMarksVisible();
884
885 // if either show marks HAVE BEEN visible and they're no longer visble OR
886 // no show marks have been visible and now they're some visible
887 // => redraw
888 if (showMarksVisible || showMarksVisibleOld)
889 {
890 sectionSamples->updateSampleWindow(false);
891 importantRefresh = true;
892 }
893 }
894
895 }
896
897 if (sectionInstruments->isEnvelopeVisible())
898 {
899 EnvelopeEditorControl* eeCtrl = sectionInstruments->getEnvelopeEditorControl();
900
901 bool redrawEnvelopeEditor = false;
902
903 if (eeCtrl->hasShowMarks())
904 {
905 eeCtrl->clearShowMarks();
906 redrawEnvelopeEditor = true;
907 }
908
909 EnvelopeEditor* ee = getEnvelopeEditor();
910
911 for (pp_int32 i = 0; i < playerController->getPlayerNumPlayingChannels(); i++)
912 {
913 pp_int32 pos;
914 if (playerController->isEnvelopePlaying(*ee->getEnvelope(), sectionInstruments->getVisibleEnvelopeType(), i, pos))
915 {
916 eeCtrl->setShowMark(i, pos);
917
918 if (pos != -1)
919 redrawEnvelopeEditor = true;
920 }
921 }
922
923 if (redrawEnvelopeEditor)
924 {
925 sectionInstruments->updateEnvelopeWindow(false);
926 importantRefresh = true;
927 }
928
929 }
930
931 if (playerController->isPlaying() &&
932 !playerController->isPlayingRowOnly()/* && getFollowSong()*/)
933 {
934 importantRefresh |= updateSongPosition();
935 }
936
937 bool updatePeak = updatePeakLevelControl();
938
939 bool updateScopes = false;
940 if (scopesControl && scopesControl->isVisible())
941 {
942 updateScopes = scopesControl->needsUpdate();
943 if (updateScopes && !updatePiano && !importantRefresh && !updatePlayTime && !updatePeak)
944 {
945 screen->paintControl(scopesControl);
946 return;
947 }
948 else if (updateScopes)
949 screen->paintControl(scopesControl, false);
950 }
951
952 importantRefresh |= updatePiano;
953
954 if (!importantRefresh)
955 {
956 if (updatePeak || updatePlayTime)
957 {
958 screen->updateControl(screen->getControlByID(CONTAINER_ABOUT));
959 }
960
961 if (updateScopes)
962 {
963 screen->updateControl(scopesControl);
964 }
965 }
966 else
967 {
968 screen->update();
969 }
970 }
971
updateAfterLoad(bool loadResult,bool wasPlaying,bool wasPlayingPattern)972 void Tracker::updateAfterLoad(bool loadResult, bool wasPlaying, bool wasPlayingPattern)
973 {
974 ASSERT(settingsDatabase->restore("AUTOESTPLAYTIME"));
975 if (loadResult && settingsDatabase->restore("AUTOESTPLAYTIME")->getIntValue())
976 estimateSongLength();
977 else
978 moduleEditor->getModuleServices()->resetEstimatedSongLength();
979
980 // special updates
981 listBoxOrderList->setSelectedIndex(0);
982 moduleEditor->setCurrentOrderIndex(0);
983
984 moduleEditor->setCurrentPatternIndex(moduleEditor->getOrderPosition(0));
985
986 listBoxInstruments->setSelectedIndex(0);
987 moduleEditor->setCurrentInstrumentIndex(0);
988 listBoxSamples->setSelectedIndex(0);
989 moduleEditor->setCurrentSampleIndex(0);
990
991 updateSongInfo(false);
992
993 playerController->resetMainVolume();
994 getPatternEditorControl()->setChannel(0,0);
995 getPatternEditorControl()->setCurrentInstrument(1);
996
997 if (wasPlaying)
998 {
999 if (!wasPlayingPattern && shouldFollowSong())
1000 {
1001 getPatternEditorControl()->setSongPosition(-1, -1);
1002 getPatternEditorControl()->setRow(0);
1003 }
1004 else if (wasPlayingPattern && !shouldFollowSong())
1005 {
1006 getPatternEditorControl()->setSongPosition(-1, 0);
1007 }
1008 else if (wasPlayingPattern && shouldFollowSong())
1009 {
1010 getPatternEditorControl()->setSongPosition(-1, -1);
1011 getPatternEditorControl()->setRow(0);
1012 }
1013 }
1014 else
1015 {
1016 getPatternEditorControl()->setSongPosition(-1, -1);
1017 getPatternEditorControl()->setRow(0);
1018 }
1019
1020 if (loadResult)
1021 {
1022 playerController->resetPlayTimeCounter();
1023
1024 sectionHDRecorder->resetCurrentFileName();
1025 sectionHDRecorder->adjustOrders();
1026
1027 updateWindowTitle(moduleEditor->getModuleFileName());
1028
1029 // !!! Remember this !!!
1030 // It's important to apply new speed settings before the playmode is switched
1031 playerController->setSpeed(moduleEditor->getSongBPM(), moduleEditor->getSongTickSpeed());
1032
1033 if (!sectionQuickOptions->keepSettings())
1034 {
1035 switch (moduleEditor->getSaveType())
1036 {
1037 case ModuleEditor::ModSaveTypeMOD:
1038 if (moduleEditor->getNumChannels() == 4)
1039 playerController->switchPlayMode(PlayerController::PlayMode_ProTracker2);
1040 else
1041 playerController->switchPlayMode(PlayerController::PlayMode_ProTracker3);
1042 break;
1043 case ModuleEditor::ModSaveTypeXM:
1044 playerController->switchPlayMode(PlayerController::PlayMode_FastTracker2);
1045 break;
1046 default:
1047 ASSERT(false);
1048 }
1049 }
1050
1051 if (wasPlaying && !wasPlayingPattern)
1052 {
1053 playerController->restartPlaying();
1054 }
1055 else if (wasPlaying && wasPlayingPattern)
1056 {
1057 eventKeyDownBinding_Stop();
1058 eventKeyDownBinding_PlayPattern();
1059 }
1060 }
1061
1062 updateSongInfo(false);
1063 }
1064
updateAfterTabSwitch()1065 void Tracker::updateAfterTabSwitch()
1066 {
1067 pp_int32 i;
1068
1069 getPatternEditorControl()->attachPatternEditor(moduleEditor->getPatternEditor());
1070 sectionSamples->getSampleEditorControl(false)->attachSampleEditor(moduleEditor->getSampleEditor());
1071 sectionInstruments->getEnvelopeEditorControl()->attachEnvelopeEditor(moduleEditor->getEnvelopeEditor());
1072 // -----------------------------------------------------------------------
1073 sectionHDRecorder->resetCurrentFileName();
1074 sectionHDRecorder->adjustOrders();
1075
1076 updateSongTitle(false);
1077
1078 updateSongLength(false);
1079 updateSongRepeat(false);
1080
1081 updateSpeed(false);
1082 updatePatternAddAndOctave(false);
1083
1084 updatePatternIndex(false);
1085 updatePatternLength(false);
1086
1087 updateInstrumentsListBox(false);
1088 updateSamplesListBox(false);
1089
1090 // -----------------------------------------------------------------------
1091 // restore old positions
1092 listBoxInstruments->setSelectedIndex(moduleEditor->getCurrentInstrumentIndex(), false);
1093 listBoxSamples->setSelectedIndex(moduleEditor->getCurrentSampleIndex(), false);
1094
1095 if (!playerController->isPlaying())
1096 {
1097 listBoxOrderList->setSelectedIndex(moduleEditor->getCurrentOrderIndex());
1098 updatePatternEditorControl(false, true);
1099 getPatternEditor()->setCursor(moduleEditor->getCurrentCursorPosition());
1100 }
1101
1102 getPatternEditorControl()->setSize(PPSize(screen->getWidth(),MAXEDITORHEIGHT()-UPPERSECTIONDEFAULTHEIGHT()));
1103
1104 // let tabs handle their own update
1105 for (i = 0; i < sections->size(); i++)
1106 sections->get(i)->notifyTabSwitch();
1107
1108 setNumChannels(moduleEditor->getNumChannels(), false);
1109 scopesControl->attachSource(playerController);
1110 updateSampleEditorAndInstrumentSection(false);
1111 updateWindowTitle(moduleEditor->getModuleFileName());
1112
1113 // apply muting from playercontroller
1114 const pp_int32 numChannels = TrackerConfig::numPlayerChannels;
1115 for (i = 0; i < numChannels; i++)
1116 {
1117 bool b = playerController->isChannelMuted(i);
1118 muteChannels[i] = b ? 1 : 0;
1119 getPatternEditorControl()->muteChannel(i, b);
1120 scopesControl->muteChannel(i, b);
1121
1122 b = playerController->isChannelRecording(i);
1123 scopesControl->recordChannel(i, b);
1124 }
1125
1126 if (playerController->isPlaying())
1127 {
1128 screen->pauseUpdate(true);
1129 doFollowSong();
1130 screen->pauseUpdate(false);
1131 }
1132 screen->paint(true);
1133 }
1134
1135