/* ** SequenceWin.c ** ** Copyright (C) 1993,94,95,96 Bernardo Innocenti ** ** Sequence editor handling functions. */ #include #include #include #include #include #include #include #include "XModulePriv.h" #include "Gui.h" /* Gadget IDs */ enum { GD_SequenceGroup0, GD_SequenceGroup1, GD_SequenceGroup2, GD_PattList, GD_PattName, GD_SequenceGroup3, GD_PattAdd, GD_PattDel, GD_PattUp, GD_PattDown, GD_SequenceGroup4, GD_SeqList, GD_SequenceGroup5, GD_SeqInsert, GD_SeqDel, GD_SeqUp, GD_SeqDown, Sequence_CNT }; /* Local function prototypes */ static void SequencePostClose (void); static void SeqListClicked (struct WinUserData *wud); static void PattAddClicked (struct WinUserData *wud); static void PattDelClicked (struct WinUserData *wud); static void PattUpClicked (struct WinUserData *wud); static void PattDownClicked (struct WinUserData *wud); static void PattNameClicked (struct WinUserData *wud); static void PattListClicked (struct WinUserData *wud); static void SeqDelClicked (struct WinUserData *wud); static void SeqUpClicked (struct WinUserData *wud); static void SeqDownClicked (struct WinUserData *wud); static void SeqInsertClicked (struct WinUserData *wud); struct Gadget *SequenceGadgets[Sequence_CNT]; struct List SequenceList; struct List PatternsList; static ULONG SequenceSecs = 0, SequenceMicros = 0; static ULONG PatternSecs = 0, PatternMicros = 0; static ULONG SequenceArgs[] = { HGROUP_KIND, BBFT_RIDGE, VGROUP_KIND, 0, LISTVIEW_KIND, (ULONG)PattListClicked, MSG_PATTERNS_GAD, (ULONG)&PatternsList, TAG_DONE, STRING_KIND, (ULONG)PattNameClicked, MSG_UNDERSCORE_NAME_GAD, 128, TAG_DONE, ENDGROUP_KIND, VGROUP_KIND, 0, BUTTON_KIND, (ULONG)PattAddClicked, MSG_UNDERSCORE_ADD_GAD, TAG_DONE, BUTTON_KIND, (ULONG)PattDelClicked, MSG_DEL_GAD, TAG_DONE, BUTTON_KIND, (ULONG)PattUpClicked, MSG_UP_GAD, TAG_DONE, BUTTON_KIND, (ULONG)PattDownClicked, MSG_DOWN_GAD, TAG_DONE, ENDGROUP_KIND, ENDGROUP_KIND, HGROUP_KIND, BBFT_RIDGE, LISTVIEW_KIND, (ULONG)SeqListClicked, MSG_SEQUENCE_GAD, (ULONG)&SequenceList, TAG_DONE, VGROUP_KIND, 0, BUTTON_KIND, (ULONG)SeqInsertClicked, MSG_UNDERSCORE_INS_GAD, TAG_DONE, BUTTON_KIND, (ULONG)SeqDelClicked, MSG_DEL_GAD, TAG_DONE, BUTTON_KIND, (ULONG)SeqUpClicked, MSG_UNDERSCORE_UP_GAD, TAG_DONE, BUTTON_KIND, (ULONG)SeqDownClicked, MSG_UNDERSCORE_DOWN_GAD, TAG_DONE, ENDGROUP_KIND, ENDGROUP_KIND, ENDGROUP_KIND }; XDEF LONG SequenceWinTags[] = { XMWIN_LayoutArgs, (LONG)SequenceArgs, XMWIN_GCount, Sequence_CNT, XMWIN_Title, MSG_SEQUENCE_TITLE, XMWIN_WindowFlags, WFLG_CLOSEGADGET, XMWIN_IDCMPFlags, BUTTONIDCMP|LISTVIEWIDCMP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW, XMWIN_PostOpenFunc, (LONG)UpdatePatternList, XMWIN_PostCloseFunc,(LONG)SequencePostClose, XMWIN_HelpNode, (LONG)"Sequence", TAG_DONE }; static void SequencePostClose (void) { while (!IsListEmpty (&SequenceList)) RemListViewNode (SequenceList.lh_Head); while (!IsListEmpty (&PatternsList)) RemListViewNode (PatternsList.lh_Head); } /**********************/ /* Sequence Functions */ /**********************/ GLOBALCALL void UpdateSequenceList (void) { struct WinUserData *wud = WDescr[WID_SEQUENCE].Wud; struct SongInfo *si; ULONG i; UWORD pos; if (wud && wud->Win) { GT_SetGadgetAttrs (wud->Gadgets[GD_SeqList], wud->Win, NULL, GTLV_Labels, ~0, TAG_DONE); while (!IsListEmpty (&SequenceList)) RemListViewNode (SequenceList.lh_Head); if (si = xmLockActiveSong (SM_SHARED)) { for (i = 0 ; i < si->Length; i++) { pos = si->Sequence[i]; AddListViewNode (&SequenceList, "%03lu - %03ld %s", i, pos, (pos >= si->NumPatterns) ? (STRPTR)"--none--" : si->Patt[pos]->Name); } GT_SetGadgetAttrs (wud->Gadgets[GD_SeqList], wud->Win, NULL, GTLV_Labels, &SequenceList, GTLV_Selected, si->CurrentPos, GTLV_MakeVisible, si->CurrentPos, TAG_DONE); ReleaseSemaphore (&si->Lock); } } } GLOBALCALL void UpdatePatternList (void) { struct WinUserData *wud = WDescr[WID_SEQUENCE].Wud; struct SongInfo *si; struct Pattern *patt; ULONG i; if (wud && wud->Win) { GT_SetGadgetAttrs (wud->Gadgets[GD_PattList], wud->Win, NULL, GTLV_Labels, ~0, TAG_DONE); while (!IsListEmpty (&PatternsList)) RemListViewNode (PatternsList.lh_Head); if (si = xmLockActiveSong (SM_SHARED)) { for (i = 0 ; i < si->NumPatterns; i++) { if (patt = si->Patt[i]) { AddListViewNode (&PatternsList, "%03lu (%lu,%lu) %s", i, patt->Tracks, patt->Lines, patt->Name ? patt->Name : (STRPTR) STR(MSG_UNNAMED)); } else AddListViewNode (&PatternsList, STR(MSG_EMPTY)); } GT_SetGadgetAttrs (wud->Gadgets[GD_PattName], wud->Win, NULL, GTST_String, si->NumPatterns ? si->Patt[si->CurrentPatt]->Name : NULL, TAG_DONE); GT_SetGadgetAttrs (wud->Gadgets[GD_PattList], wud->Win, NULL, GTLV_Labels, &PatternsList, GTLV_Selected, si->CurrentPatt, GTLV_MakeVisible, si->CurrentPatt, TAG_DONE); ReleaseSemaphore (&si->Lock); } UpdateSequenceList(); } UpdatePattern(); } /********************/ /* Sequence Gadgets */ /********************/ static void SeqListClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { if (IntuiMsg.Code == si->CurrentPos) { /* Check Double Click */ if (DoubleClick (SequenceSecs, SequenceMicros, IntuiMsg.Seconds, IntuiMsg.Micros)) { si->Sequence[si->CurrentPos] = si->CurrentPatt; UpdateSequenceList(); } } si->CurrentPos = IntuiMsg.Code; ReleaseSemaphore (&si->Lock); } SequenceSecs = IntuiMsg.Seconds; SequenceMicros = IntuiMsg.Micros; } static void PattAddClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { if (si->NumPatterns >= MAXPATTERNS) DisplayBeep (Scr); else { xmAddPatternA (si, NULL); UpdateSongInfo(); /* this also calls UpdatePatternList() */ } ReleaseSemaphore (&si->Lock); } } static void PattDelClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { if (si->NumPatterns <= 1) DisplayBeep (Scr); else xmRemPattern (si, si->CurrentPatt, 0); ReleaseSemaphore (&si->Lock); } UpdateSongInfo(); } static void PattUpClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { if (si->CurrentPatt == 0) DisplayBeep (Scr); else { struct Pattern *tmp_patt; /* Swap pattern with its predecessor */ tmp_patt = si->Patt[si->CurrentPatt]; si->Patt[si->CurrentPatt] = si->Patt[si->CurrentPatt - 1]; si->Patt[si->CurrentPatt - 1] = tmp_patt; SetAttrs (si, SNGA_CurrentPatt, si->CurrentPatt - 1, TAG_DONE); UpdatePatternList(); } ReleaseSemaphore (&si->Lock); } } static void PattDownClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { if (si->CurrentPatt >= si->NumPatterns - 1) DisplayBeep (Scr); else { struct Pattern *tmp_patt; /* Swap pattern with its successor */ tmp_patt = si->Patt[si->CurrentPatt]; si->Patt[si->CurrentPatt] = si->Patt[si->CurrentPatt + 1]; si->Patt[si->CurrentPatt + 1] = tmp_patt; SetAttrs (si, SNGA_CurrentPatt, si->CurrentPatt + 1, TAG_DONE); UpdatePatternList(); } ReleaseSemaphore (&si->Lock); } } static void PattNameClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { xmSetPattern (si, si->CurrentPatt, PATTA_Name, GetString (wud->Gadgets[GD_PattName]), TAG_DONE); UpdatePatternList(); ReleaseSemaphore (&si->Lock); } } static void PattListClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_SHARED)) { if (IntuiMsg.Code == si->CurrentPatt) { /* Check Double Click */ if (DoubleClick (PatternSecs, PatternMicros, IntuiMsg.Seconds, IntuiMsg.Micros)) NewWindow(WID_PATTERN); } else { si->CurrentPatt = IntuiMsg.Code; GT_SetGadgetAttrs (wud->Gadgets[GD_PattName], wud->Win, NULL, GTST_String, si->Patt[si->CurrentPatt]->Name, TAG_DONE); UpdatePattern(); } ReleaseSemaphore (&si->Lock); } PatternSecs = IntuiMsg.Seconds; PatternMicros = IntuiMsg.Micros; } static void SeqDelClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { ULONG i; /* You can't have an empty sequence */ if (si->Length == 1) DisplayBeep (Scr); else { /* Shift positions back */ for (i = si->CurrentPos ; i < si->Length; i++) si->Sequence[i] = si->Sequence[i+1]; xmSetSongLen (si, si->Length - 1); UpdateSongInfo(); /* Will call also UpdateSequenceList() */ } ReleaseSemaphore (&si->Lock); } } static void SeqUpClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { UWORD temp; if (si->CurrentPos < 1) DisplayBeep (Scr); else { temp = si->Sequence[si->CurrentPos]; si->Sequence[si->CurrentPos] = si->Sequence[si->CurrentPos - 1]; si->Sequence[si->CurrentPos - 1] = temp; si->CurrentPos--; UpdateSequenceList(); } ReleaseSemaphore (&si->Lock); } } static void SeqDownClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { UWORD temp; if (si->CurrentPos >= si->Length - 1) DisplayBeep (Scr); else { temp = si->Sequence[si->CurrentPos]; si->Sequence[si->CurrentPos] = si->Sequence[si->CurrentPos + 1]; si->Sequence[si->CurrentPos + 1] = temp; si->CurrentPos++; UpdateSequenceList(); } ReleaseSemaphore (&si->Lock); } } static void SeqInsertClicked (struct WinUserData *wud) { struct SongInfo *si; if (si = xmLockActiveSong (SM_EXCLUSIVE)) { if (!(xmSetSongLen (si, si->Length + 1))) DisplayBeep (Scr); else { ULONG i; for (i = si->Length - 1; i > si->CurrentPos; i--) si->Sequence[i] = si->Sequence[i-1]; si->Sequence[si->CurrentPos] = si->CurrentPatt; } ReleaseSemaphore (&si->Lock); UpdateSongInfo(); /* This will also update the sequence list */ } }