Initial commit.
[amiga/xmodule.git] / SequenceWin.c
1 /*
2 **      SequenceWin.c
3 **
4 **      Copyright (C) 1993,94,95,96 Bernardo Innocenti
5 **
6 **      Sequence editor handling functions.
7 */
8
9 #include <intuition/intuition.h>
10 #include <intuition/gadgetclass.h>
11 #include <libraries/gadtools.h>
12
13 #include <proto/exec.h>
14 #include <proto/intuition.h>
15 #include <proto/gadtools.h>
16 #include <proto/xmodule.h>
17
18
19 #include "XModulePriv.h"
20 #include "Gui.h"
21
22
23
24 /* Gadget IDs */
25
26 enum
27 {
28         GD_SequenceGroup0,
29                 GD_SequenceGroup1,
30                         GD_SequenceGroup2,
31                                 GD_PattList,
32                                 GD_PattName,
33                         GD_SequenceGroup3,
34                                 GD_PattAdd,
35                                 GD_PattDel,
36                                 GD_PattUp,
37                                 GD_PattDown,
38                 GD_SequenceGroup4,
39                         GD_SeqList,
40                 GD_SequenceGroup5,
41                         GD_SeqInsert,
42                         GD_SeqDel,
43                         GD_SeqUp,
44                         GD_SeqDown,
45
46         Sequence_CNT
47 };
48
49
50
51 /* Local function prototypes */
52
53 static void SequencePostClose   (void);
54
55 static void SeqListClicked              (struct WinUserData *wud);
56 static void PattAddClicked              (struct WinUserData *wud);
57 static void PattDelClicked              (struct WinUserData *wud);
58 static void PattUpClicked               (struct WinUserData *wud);
59 static void PattDownClicked             (struct WinUserData *wud);
60 static void PattNameClicked             (struct WinUserData *wud);
61 static void PattListClicked             (struct WinUserData *wud);
62 static void SeqDelClicked               (struct WinUserData *wud);
63 static void SeqUpClicked                (struct WinUserData *wud);
64 static void SeqDownClicked              (struct WinUserData *wud);
65 static void SeqInsertClicked    (struct WinUserData *wud);
66
67
68 struct Gadget   *SequenceGadgets[Sequence_CNT];
69 struct List              SequenceList;
70 struct List              PatternsList;
71 static ULONG     SequenceSecs = 0, SequenceMicros = 0;
72 static ULONG     PatternSecs = 0, PatternMicros = 0;
73
74
75
76 static ULONG SequenceArgs[] =
77 {
78         HGROUP_KIND, BBFT_RIDGE,
79                 VGROUP_KIND, 0,
80                         LISTVIEW_KIND,  (ULONG)PattListClicked, MSG_PATTERNS_GAD,       (ULONG)&PatternsList,   TAG_DONE,
81                         STRING_KIND,    (ULONG)PattNameClicked, MSG_UNDERSCORE_NAME_GAD,        128, TAG_DONE,
82                         ENDGROUP_KIND,
83                 VGROUP_KIND, 0,
84                         BUTTON_KIND,    (ULONG)PattAddClicked,  MSG_UNDERSCORE_ADD_GAD, TAG_DONE,
85                         BUTTON_KIND,    (ULONG)PattDelClicked,  MSG_DEL_GAD,                    TAG_DONE,
86                         BUTTON_KIND,    (ULONG)PattUpClicked,   MSG_UP_GAD,                             TAG_DONE,
87                         BUTTON_KIND,    (ULONG)PattDownClicked, MSG_DOWN_GAD,                   TAG_DONE,
88                         ENDGROUP_KIND,
89                 ENDGROUP_KIND,
90         HGROUP_KIND, BBFT_RIDGE,
91                 LISTVIEW_KIND,  (ULONG)SeqListClicked,  MSG_SEQUENCE_GAD,       (ULONG)&SequenceList,   TAG_DONE,
92                 VGROUP_KIND, 0,
93                         BUTTON_KIND,    (ULONG)SeqInsertClicked,        MSG_UNDERSCORE_INS_GAD,         TAG_DONE,
94                         BUTTON_KIND,    (ULONG)SeqDelClicked,           MSG_DEL_GAD,                            TAG_DONE,
95                         BUTTON_KIND,    (ULONG)SeqUpClicked,            MSG_UNDERSCORE_UP_GAD,          TAG_DONE,
96                         BUTTON_KIND,    (ULONG)SeqDownClicked,          MSG_UNDERSCORE_DOWN_GAD,        TAG_DONE,
97                         ENDGROUP_KIND,
98                 ENDGROUP_KIND,
99         ENDGROUP_KIND
100 };
101
102
103
104 XDEF LONG SequenceWinTags[] =
105 {
106         XMWIN_LayoutArgs,       (LONG)SequenceArgs,
107         XMWIN_GCount,           Sequence_CNT,
108         XMWIN_Title,            MSG_SEQUENCE_TITLE,
109         XMWIN_WindowFlags,      WFLG_CLOSEGADGET,
110         XMWIN_IDCMPFlags,       BUTTONIDCMP|LISTVIEWIDCMP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW,
111         XMWIN_PostOpenFunc,     (LONG)UpdatePatternList,
112         XMWIN_PostCloseFunc,(LONG)SequencePostClose,
113         XMWIN_HelpNode,         (LONG)"Sequence",
114         TAG_DONE
115 };
116
117
118
119 static void SequencePostClose (void)
120 {
121         while (!IsListEmpty (&SequenceList))
122                 RemListViewNode (SequenceList.lh_Head);
123
124         while (!IsListEmpty (&PatternsList))
125                 RemListViewNode (PatternsList.lh_Head);
126 }
127
128
129
130 /**********************/
131 /* Sequence Functions */
132 /**********************/
133
134 GLOBALCALL void UpdateSequenceList (void)
135 {
136         struct WinUserData *wud = WDescr[WID_SEQUENCE].Wud;
137         struct SongInfo *si;
138         ULONG i;
139         UWORD pos;
140
141         if (wud && wud->Win)
142         {
143                 GT_SetGadgetAttrs (wud->Gadgets[GD_SeqList], wud->Win, NULL,
144                         GTLV_Labels, ~0,
145                         TAG_DONE);
146
147                 while (!IsListEmpty (&SequenceList))
148                         RemListViewNode (SequenceList.lh_Head);
149
150                 if (si = xmLockActiveSong (SM_SHARED))
151                 {
152                         for (i = 0 ; i < si->Length; i++)
153                         {
154                                 pos = si->Sequence[i];
155                                 AddListViewNode (&SequenceList, "%03lu - %03ld %s", i, pos,
156                                         (pos >= si->NumPatterns) ? (STRPTR)"--none--" : si->Patt[pos]->Name);
157                         }
158
159                         GT_SetGadgetAttrs (wud->Gadgets[GD_SeqList], wud->Win, NULL,
160                                 GTLV_Labels, &SequenceList,
161                                 GTLV_Selected, si->CurrentPos,
162                                 GTLV_MakeVisible, si->CurrentPos,
163                                 TAG_DONE);
164
165                         ReleaseSemaphore (&si->Lock);
166                 }
167         }
168 }
169
170
171
172 GLOBALCALL void UpdatePatternList (void)
173 {
174         struct WinUserData *wud = WDescr[WID_SEQUENCE].Wud;
175         struct SongInfo *si;
176         struct Pattern *patt;
177         ULONG i;
178
179         if (wud && wud->Win)
180         {
181                 GT_SetGadgetAttrs (wud->Gadgets[GD_PattList], wud->Win, NULL,
182                         GTLV_Labels, ~0,
183                         TAG_DONE);
184
185                 while (!IsListEmpty (&PatternsList))
186                         RemListViewNode (PatternsList.lh_Head);
187
188
189                 if (si = xmLockActiveSong (SM_SHARED))
190                 {
191                         for (i = 0 ; i < si->NumPatterns; i++)
192                         {
193                                 if (patt = si->Patt[i])
194                                 {
195                                         AddListViewNode (&PatternsList, "%03lu (%lu,%lu) %s",
196                                                 i, patt->Tracks, patt->Lines,
197                                                 patt->Name ? patt->Name : (STRPTR) STR(MSG_UNNAMED));
198                                 }
199                                 else AddListViewNode (&PatternsList, STR(MSG_EMPTY));
200                         }
201
202                         GT_SetGadgetAttrs (wud->Gadgets[GD_PattName], wud->Win, NULL,
203                                 GTST_String, si->NumPatterns ? si->Patt[si->CurrentPatt]->Name : NULL,
204                                 TAG_DONE);
205
206                         GT_SetGadgetAttrs (wud->Gadgets[GD_PattList], wud->Win, NULL,
207                                 GTLV_Labels,            &PatternsList,
208                                 GTLV_Selected,          si->CurrentPatt,
209                                 GTLV_MakeVisible,       si->CurrentPatt,
210                                 TAG_DONE);
211
212                         ReleaseSemaphore (&si->Lock);
213                 }
214
215                 UpdateSequenceList();
216         }
217
218         UpdatePattern();
219 }
220
221
222
223 /********************/
224 /* Sequence Gadgets */
225 /********************/
226
227 static void SeqListClicked (struct WinUserData *wud)
228 {
229         struct SongInfo *si;
230
231         if (si = xmLockActiveSong (SM_EXCLUSIVE))
232         {
233                 if (IntuiMsg.Code == si->CurrentPos)
234                 {
235                         /* Check Double Click */
236                         if (DoubleClick (SequenceSecs, SequenceMicros, IntuiMsg.Seconds, IntuiMsg.Micros))
237                         {
238                                 si->Sequence[si->CurrentPos] = si->CurrentPatt;
239                                 UpdateSequenceList();
240                         }
241                 }
242
243                 si->CurrentPos = IntuiMsg.Code;
244
245                 ReleaseSemaphore (&si->Lock);
246         }
247
248         SequenceSecs    = IntuiMsg.Seconds;
249         SequenceMicros  = IntuiMsg.Micros;
250 }
251
252
253
254 static void PattAddClicked (struct WinUserData *wud)
255 {
256         struct SongInfo *si;
257
258         if (si = xmLockActiveSong (SM_EXCLUSIVE))
259         {
260                 if (si->NumPatterns >= MAXPATTERNS)
261                         DisplayBeep (Scr);
262                 else
263                 {
264                         xmAddPatternA (si, NULL);
265                         UpdateSongInfo();       /* this also calls UpdatePatternList() */
266                 }
267
268                 ReleaseSemaphore (&si->Lock);
269         }
270 }
271
272
273
274 static void PattDelClicked (struct WinUserData *wud)
275 {
276         struct SongInfo *si;
277
278         if (si = xmLockActiveSong (SM_EXCLUSIVE))
279         {
280                 if (si->NumPatterns <= 1)
281                         DisplayBeep (Scr);
282                 else
283                         xmRemPattern (si, si->CurrentPatt, 0);
284
285                 ReleaseSemaphore (&si->Lock);
286         }
287
288         UpdateSongInfo();
289 }
290
291
292
293 static void PattUpClicked (struct WinUserData *wud)
294 {
295         struct SongInfo *si;
296
297         if (si = xmLockActiveSong (SM_EXCLUSIVE))
298         {
299                 if (si->CurrentPatt == 0)
300                         DisplayBeep (Scr);
301                 else
302                 {
303                         struct Pattern *tmp_patt;
304
305                         /* Swap pattern with its predecessor */
306                         tmp_patt = si->Patt[si->CurrentPatt];
307                         si->Patt[si->CurrentPatt] = si->Patt[si->CurrentPatt - 1];
308                         si->Patt[si->CurrentPatt - 1] = tmp_patt;
309
310                         SetAttrs (si,
311                                 SNGA_CurrentPatt, si->CurrentPatt - 1,
312                                 TAG_DONE);
313
314                         UpdatePatternList();
315                 }
316
317                 ReleaseSemaphore (&si->Lock);
318         }
319 }
320
321
322
323 static void PattDownClicked (struct WinUserData *wud)
324 {
325         struct SongInfo *si;
326
327         if (si = xmLockActiveSong (SM_EXCLUSIVE))
328         {
329                 if (si->CurrentPatt >= si->NumPatterns - 1)
330                         DisplayBeep (Scr);
331                 else
332                 {
333                         struct Pattern *tmp_patt;
334
335                         /* Swap pattern with its successor */
336                         tmp_patt = si->Patt[si->CurrentPatt];
337                         si->Patt[si->CurrentPatt] = si->Patt[si->CurrentPatt + 1];
338                         si->Patt[si->CurrentPatt + 1] = tmp_patt;
339
340                         SetAttrs (si,
341                                 SNGA_CurrentPatt, si->CurrentPatt + 1,
342                                 TAG_DONE);
343
344                         UpdatePatternList();
345                 }
346
347                 ReleaseSemaphore (&si->Lock);
348         }
349 }
350
351
352
353 static void PattNameClicked (struct WinUserData *wud)
354 {
355         struct SongInfo *si;
356
357         if (si = xmLockActiveSong (SM_EXCLUSIVE))
358         {
359                 xmSetPattern (si, si->CurrentPatt,
360                         PATTA_Name,     GetString (wud->Gadgets[GD_PattName]),
361                         TAG_DONE);
362
363                 UpdatePatternList();
364                 ReleaseSemaphore (&si->Lock);
365         }
366 }
367
368
369
370 static void PattListClicked (struct WinUserData *wud)
371 {
372         struct SongInfo *si;
373
374         if (si = xmLockActiveSong (SM_SHARED))
375         {
376                 if (IntuiMsg.Code == si->CurrentPatt)
377                 {
378                         /* Check Double Click */
379                         if (DoubleClick (PatternSecs, PatternMicros, IntuiMsg.Seconds, IntuiMsg.Micros))
380                                 NewWindow(WID_PATTERN);
381                 }
382                 else
383                 {
384                         si->CurrentPatt = IntuiMsg.Code;
385
386                         GT_SetGadgetAttrs (wud->Gadgets[GD_PattName], wud->Win, NULL,
387                                 GTST_String, si->Patt[si->CurrentPatt]->Name,
388                                 TAG_DONE);
389
390                         UpdatePattern();
391                 }
392
393                 ReleaseSemaphore (&si->Lock);
394         }
395
396         PatternSecs = IntuiMsg.Seconds;
397         PatternMicros = IntuiMsg.Micros;
398 }
399
400
401
402 static void SeqDelClicked (struct WinUserData *wud)
403 {
404         struct SongInfo *si;
405
406         if (si = xmLockActiveSong (SM_EXCLUSIVE))
407         {
408                 ULONG i;
409
410                 /* You can't have an empty sequence */
411                 if (si->Length == 1)
412                         DisplayBeep (Scr);
413                 else
414                 {
415                         /* Shift positions back */
416                         for (i = si->CurrentPos ; i < si->Length; i++)
417                                 si->Sequence[i] = si->Sequence[i+1];
418
419                         xmSetSongLen (si, si->Length - 1);
420
421                         UpdateSongInfo();       /* Will call also UpdateSequenceList() */
422                 }
423
424                 ReleaseSemaphore (&si->Lock);
425         }
426 }
427
428
429
430 static void SeqUpClicked (struct WinUserData *wud)
431 {
432         struct SongInfo *si;
433
434         if (si = xmLockActiveSong (SM_EXCLUSIVE))
435         {
436                 UWORD temp;
437
438                 if (si->CurrentPos < 1)
439                         DisplayBeep (Scr);
440                 else
441                 {
442                         temp = si->Sequence[si->CurrentPos];
443                         si->Sequence[si->CurrentPos] = si->Sequence[si->CurrentPos - 1];
444                         si->Sequence[si->CurrentPos - 1] = temp;
445
446                         si->CurrentPos--;
447                         UpdateSequenceList();
448                 }
449
450                 ReleaseSemaphore (&si->Lock);
451         }
452 }
453
454
455
456 static void SeqDownClicked (struct WinUserData *wud)
457 {
458         struct SongInfo *si;
459
460         if (si = xmLockActiveSong (SM_EXCLUSIVE))
461         {
462                 UWORD temp;
463
464                 if (si->CurrentPos >= si->Length - 1)
465                         DisplayBeep (Scr);
466                 else
467                 {
468                         temp = si->Sequence[si->CurrentPos];
469                         si->Sequence[si->CurrentPos] = si->Sequence[si->CurrentPos + 1];
470                         si->Sequence[si->CurrentPos + 1] = temp;
471
472                         si->CurrentPos++;
473                         UpdateSequenceList();
474                 }
475
476                 ReleaseSemaphore (&si->Lock);
477         }
478 }
479
480
481
482 static void SeqInsertClicked (struct WinUserData *wud)
483 {
484         struct SongInfo *si;
485
486         if (si = xmLockActiveSong (SM_EXCLUSIVE))
487         {
488                 if (!(xmSetSongLen (si, si->Length + 1)))
489                         DisplayBeep (Scr);
490                 else
491                 {
492                         ULONG i;
493
494                         for (i = si->Length - 1; i > si->CurrentPos; i--)
495                                 si->Sequence[i] = si->Sequence[i-1];
496
497                         si->Sequence[si->CurrentPos] = si->CurrentPatt;
498                 }
499
500                 ReleaseSemaphore (&si->Lock);
501
502                 UpdateSongInfo();       /* This will also update the sequence list */
503         }
504 }