revert between 56095 -> 55830 in arch
[AROS.git] / rom / usb / classes / simplemidi / simplemidi.class.c
blob7b954d7e578a56b566cda45af7765ada750acc35
1 /*
2 *----------------------------------------------------------------------------
3 * simplemidi class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "simplemidi.class.h"
12 /* /// "Lib Stuff" */
13 static const STRPTR libname = MOD_NAME_STRING;
15 static int libInit(LIBBASETYPEPTR nh)
17 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh, SysBase));
19 nh->nh_UtilityBase = OpenLibrary("utility.library", 39);
21 #define UtilityBase nh->nh_UtilityBase
23 if(UtilityBase)
25 /* Create default config */
26 nh->nh_CurrentCGC.cgc_ChunkID = AROS_LONG2BE(MAKE_ID('M','I','D','I'));
27 nh->nh_CurrentCGC.cgc_Length = AROS_LONG2BE(sizeof(struct ClsGlobalCfg)-8);
28 nh->nh_CurrentCGC.cgc_MidiMinOctave = 2;
29 nh->nh_CurrentCGC.cgc_KeyMaxOctave = 5;
30 nh->nh_CurrentCGC.cgc_AutoKeyUp = TRUE;
31 } else {
32 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
33 nh = NULL;
36 KPRINTF(10, ("libInit: Ok\n"));
37 return(nh ? TRUE : FALSE);
40 static int libOpen(LIBBASETYPEPTR nh)
42 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh));
43 nLoadClassConfig(nh);
44 return(TRUE);
47 static int libExpunge(LIBBASETYPEPTR nh)
49 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh));
50 CloseLibrary((struct Library *) UtilityBase);
51 return(TRUE);
54 ADD2INITLIB(libInit, 0)
55 ADD2OPENLIB(libOpen, 0)
56 ADD2EXPUNGELIB(libExpunge, 0)
57 /* \\\ */
60 * ***********************************************************************
61 * * Library functions *
62 * ***********************************************************************
65 #define ps ps
67 /* /// "usbAttemptInterfaceBinding()" */
68 struct NepClassHid * usbAttemptInterfaceBinding(struct NepHidBase *nh, struct PsdInterface *pif)
70 struct Library *ps;
71 IPTR ifclass;
72 IPTR subclass;
73 IPTR proto;
75 KPRINTF(1, ("nepHidAttemptInterfaceBinding(%08lx)\n", pif));
76 if((ps = OpenLibrary("poseidon.library", 4)))
78 psdGetAttrs(PGA_INTERFACE, pif,
79 IFA_Class, &ifclass,
80 IFA_SubClass, &subclass,
81 IFA_Protocol, &proto,
82 TAG_DONE);
83 CloseLibrary(ps);
84 if((ifclass == AUDIO_CLASSCODE) && (subclass == AUDIO_MIDI_SUBCLASS))
86 return(usbForceInterfaceBinding(nh, pif));
89 return(NULL);
91 /* \\\ */
93 /* /// "usbForceInterfaceBinding()" */
94 struct NepClassHid * usbForceInterfaceBinding(struct NepHidBase *nh, struct PsdInterface *pif)
96 struct Library *ps;
97 struct NepClassHid *nch;
98 struct PsdConfig *pc;
99 struct PsdDevice *pd;
100 STRPTR devname;
101 UBYTE buf[64];
102 struct Task *tmptask;
104 KPRINTF(1, ("nepHidAttemptInterfaceBinding(%08lx)\n", pif));
105 if((ps = OpenLibrary("poseidon.library", 4)))
107 if((nch = psdAllocVec(sizeof(struct NepClassHid))))
109 nch->nch_ClsBase = nh;
110 nch->nch_Device = NULL;
111 nch->nch_Interface = pif;
113 nLoadClassConfig(nh);
115 psdSafeRawDoFmt(buf, 64, "simplemidi.class<%08lx>", nch);
116 nch->nch_ReadySignal = SIGB_SINGLE;
117 nch->nch_ReadySigTask = FindTask(NULL);
118 SetSignal(0, SIGF_SINGLE);
119 if((tmptask = psdSpawnSubTask(buf, nHidTask, nch)))
121 psdBorrowLocksWait(tmptask, 1UL<<nch->nch_ReadySignal);
122 if(nch->nch_Task)
124 nch->nch_ReadySigTask = NULL;
125 //FreeSignal(nch->nch_ReadySignal);
126 psdGetAttrs(PGA_INTERFACE, pif, IFA_Config, &pc, TAG_END);
127 psdGetAttrs(PGA_CONFIG, pc, CA_Device, &pd, TAG_END);
128 psdGetAttrs(PGA_DEVICE, pd, DA_ProductName, &devname, TAG_END);
129 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
130 "Play it again, '%s'!",
131 devname);
133 CloseLibrary(ps);
134 return(nch);
137 nch->nch_ReadySigTask = NULL;
138 //FreeSignal(nch->nch_ReadySignal);
139 psdFreeVec(nch);
141 CloseLibrary(ps);
143 return(NULL);
145 /* \\\ */
147 /* /// "usbReleaseInterfaceBinding()" */
148 void usbReleaseInterfaceBinding(struct NepHidBase *nh, struct NepClassHid *nch)
150 struct Library *ps;
151 struct PsdConfig *pc;
152 struct PsdDevice *pd;
153 STRPTR devname;
155 KPRINTF(1, ("nepHidReleaseInterfaceBinding(%08lx)\n", nch));
156 if((ps = OpenLibrary("poseidon.library", 4)))
158 Forbid();
159 nch->nch_ReadySignal = SIGB_SINGLE;
160 nch->nch_ReadySigTask = FindTask(NULL);
161 if(nch->nch_Task)
163 Signal(nch->nch_Task, SIGBREAKF_CTRL_C);
165 Permit();
166 while(nch->nch_Task)
168 Wait(1L<<nch->nch_ReadySignal);
170 //FreeSignal(nch->nch_ReadySignal);
171 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface, IFA_Config, &pc, TAG_END);
172 psdGetAttrs(PGA_CONFIG, pc, CA_Device, &pd, TAG_END);
173 psdGetAttrs(PGA_DEVICE, pd, DA_ProductName, &devname, TAG_END);
174 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
175 "'%s' fell silent!",
176 devname);
177 psdFreeVec(nch);
178 CloseLibrary(ps);
181 /* \\\ */
183 /* /// "usbGetAttrsA()" */
184 AROS_LH3(LONG, usbGetAttrsA,
185 AROS_LHA(ULONG, type, D0),
186 AROS_LHA(APTR, usbstruct, A0),
187 AROS_LHA(struct TagItem *, tags, A1),
188 LIBBASETYPEPTR, nh, 5, nep)
190 AROS_LIBFUNC_INIT
192 struct TagItem *ti;
193 LONG count = 0;
195 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
196 switch(type)
198 case UGA_CLASS:
199 if((ti = FindTagItem(UCCA_Priority, tags)))
201 *((SIPTR *) ti->ti_Data) = -100;
202 count++;
204 if((ti = FindTagItem(UCCA_Description, tags)))
206 *((STRPTR *) ti->ti_Data) = "Simple MIDI-IN Stream class mapping to keyboard";
207 count++;
209 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
211 *((IPTR *) ti->ti_Data) = TRUE;
212 count++;
214 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
216 *((IPTR *) ti->ti_Data) = FALSE;
217 count++;
219 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
221 *((IPTR *) ti->ti_Data) = TRUE;
222 count++;
224 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
226 *((IPTR *) ti->ti_Data) = nh->nh_UsingDefaultCfg;
227 count++;
229 break;
231 case UGA_BINDING:
232 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
234 *((IPTR *) ti->ti_Data) = FALSE;
235 count++;
237 break;
239 return(count);
240 AROS_LIBFUNC_EXIT
242 /* \\\ */
244 /* /// "usbSetAttrsA()" */
245 AROS_LH3(LONG, usbSetAttrsA,
246 AROS_LHA(ULONG, type, D0),
247 AROS_LHA(APTR, usbstruct, A0),
248 AROS_LHA(struct TagItem *, tags, A1),
249 LIBBASETYPEPTR, nh, 6, nep)
251 AROS_LIBFUNC_INIT
252 return(0);
253 AROS_LIBFUNC_EXIT
255 /* \\\ */
257 /* /// "usbDoMethodA()" */
258 AROS_LH2(IPTR, usbDoMethodA,
259 AROS_LHA(ULONG, methodid, D0),
260 AROS_LHA(IPTR *, methoddata, A1),
261 LIBBASETYPEPTR, nh, 7, nep)
263 AROS_LIBFUNC_INIT
265 KPRINTF(10, ("Do Method %ld\n", methodid));
266 switch(methodid)
268 case UCM_AttemptInterfaceBinding:
269 return((IPTR) usbAttemptInterfaceBinding(nh, (struct PsdInterface *) methoddata[0]));
271 case UCM_ForceInterfaceBinding:
272 return((IPTR) usbForceInterfaceBinding(nh, (struct PsdInterface *) methoddata[0]));
274 case UCM_ReleaseInterfaceBinding:
275 usbReleaseInterfaceBinding(nh, (struct NepClassHid *) methoddata[0]);
276 return(TRUE);
278 case UCM_OpenCfgWindow:
279 return(nOpenCfgWindow(nh));
281 case UCM_ConfigChangedEvent:
282 nLoadClassConfig(nh);
283 return(TRUE);
285 default:
286 break;
288 return(0);
289 AROS_LIBFUNC_EXIT
291 /* \\\ */
293 /**************************************************************************/
295 static const UBYTE lowoctave[] =
297 0x31, 0x21, 0x32, 0x22, 0x33, 0x34, 0x24, 0x35, 0x25, 0x36, 0x26, 0x37, /* C-1 - B-1 */
298 0x38, 0x28, 0x39, 0x29, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* C-2 - E-2 */
301 static const UBYTE highoctave[] =
303 0x10, 0x02, 0x11, 0x03, 0x12, 0x13, 0x05, 0x14, 0x06, 0x15, 0x07, 0x16, /* C-2 - B-2 */
304 0x17, 0x09, 0x18, 0x0a, 0x19, 0x1a, 0x0b, 0x1b, 0xff, 0xff, 0xff, 0xff /* C-3 - F-3 */
307 #undef ps
308 #define ps nch->nch_Base
310 /* /// "nHidTask()" */
311 AROS_UFH0(void, nHidTask)
313 AROS_USERFUNC_INIT
315 struct NepClassHid *nch;
316 struct PsdPipe *pp;
317 ULONG sigmask;
318 ULONG sigs;
319 UBYTE *buf;
320 LONG ioerr;
321 ULONG len;
323 if((nch = nAllocHid()))
325 Forbid();
326 if(nch->nch_ReadySigTask)
328 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
330 Permit();
331 sigmask = (1L<<nch->nch_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
332 buf = nch->nch_EPInBuf;
333 psdSendPipe(nch->nch_EPInPipe, buf, 512);
336 sigs = Wait(sigmask);
337 while((pp = (struct PsdPipe *) GetMsg(nch->nch_TaskMsgPort)))
339 if(pp == nch->nch_EPInPipe)
341 if(!(ioerr = psdGetPipeError(pp)))
343 len = psdGetPipeActual(pp);
344 nParseMidi(nch, buf, len);
345 } else {
346 KPRINTF(1, ("Int Pipe failed %ld\n", ioerr));
347 psdDelayMS(200);
349 psdSendPipe(nch->nch_EPInPipe, buf, 512);
350 break;
353 } while(!(sigs & SIGBREAKF_CTRL_C));
354 KPRINTF(20, ("Going down the river!\n"));
355 psdAbortPipe(nch->nch_EPInPipe);
356 psdWaitPipe(nch->nch_EPInPipe);
357 nFreeHid(nch);
360 AROS_USERFUNC_EXIT
362 /* \\\ */
364 /* /// "nSendKey()" */
365 void nSendKey(struct NepClassHid *nch, UWORD code)
367 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
368 nch->nch_FakeEvent.ie_SubClass = 0;
369 nch->nch_FakeEvent.ie_Code = code;
370 nch->nch_FakeEvent.ie_NextEvent = NULL;
371 nch->nch_FakeEvent.ie_Qualifier = 0;
372 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
373 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
374 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
375 DoIO((struct IORequest *) nch->nch_InpIOReq);
377 /* \\\ */
379 /* /// "nParseMidi()" */
380 void nParseMidi(struct NepClassHid *nch, UBYTE *buf, ULONG len)
382 UWORD iecode = 0xff;
383 UWORD chan;
384 UWORD note;
385 UWORD velocity;
386 UWORD octave;
387 UWORD cmd;
389 struct ClsGlobalCfg *cgc = &nch->nch_ClsBase->nh_CurrentCGC;
391 while(len > 3)
393 KPRINTF(1, ("Msg: %02lx %02lx %02lx %02lx\n", buf[0], buf[1], buf[2], buf[3]));
394 chan = buf[0] >> 4;
395 (void)chan; /* FIXME: Why is 'chan' ignored? */
396 cmd = buf[0] & 0x0f;
397 switch(cmd)
399 case 0x0: // Miscellaneous function codes. Reserved for future extensions.
400 case 0x1: // Cable events. Reserved for future expansion.
401 case 0x2: // Two-byte System Common messages like MTC, SongSelect, etc.
402 case 0x3: // Three-byte System Common messages like SPP, etc.
403 case 0x4: // SysEx starts or continues
404 case 0x5: // Single-byte System Common Message or SysEx ends with following single byte.
405 case 0x6: // SysEx ends with following two bytes.
406 case 0x7: // SysEx ends with following three bytes.
407 break;
409 case 0x8: // Note-off
410 KPRINTF(1, ("Note %ld up with speed %ld\n", note, velocity));
411 // fall through
413 case 0x9: // Note-on
414 note = buf[2];
415 if(cmd == 0x9)
417 KPRINTF(1, ("Note %ld down with speed %ld\n", note, velocity));
418 velocity = buf[3];
419 } else {
420 velocity = 0;
422 if(note < 12 * cgc->cgc_MidiMinOctave)
424 octave = 0;
425 } else {
426 octave = (note - (12 * cgc->cgc_MidiMinOctave)) / 12;
428 if(octave > cgc->cgc_KeyMaxOctave)
430 octave = cgc->cgc_KeyMaxOctave;
432 if((octave != nch->nch_LastOctave) && (octave != nch->nch_LastOctave+1))
434 nch->nch_LastOctave = octave; /* go to right octave */
435 if(nch->nch_LastOctave > 0)
437 nch->nch_LastOctave--; // stay at low octave
439 /* Send F-key */
440 nSendKey(nch, 0x50+nch->nch_LastOctave);
441 nSendKey(nch, (IECODE_UP_PREFIX|0x50)+nch->nch_LastOctave);
443 if(octave == nch->nch_LastOctave)
445 iecode = lowoctave[note % 12];
447 if(octave > nch->nch_LastOctave)
449 iecode = highoctave[note % 12];
451 if(iecode != 0xff)
453 if(!velocity)
455 iecode |= IECODE_UP_PREFIX;
457 nSendKey(nch, iecode);
458 if(cgc->cgc_AutoKeyUp && (!(iecode & IECODE_UP_PREFIX)))
460 iecode |= IECODE_UP_PREFIX;
461 nSendKey(nch, iecode);
464 break;
466 case 0xA: // Poly-KeyPress
467 case 0xB: // Control Change
468 case 0xC: // Program Change
469 case 0xD: // Channel Pressure
470 case 0xE: // PitchBend Change
471 case 0xF: // Single Byte
472 break;
475 /*if(keyup)
477 KPRINTF(1, ("Key up: %08lx\n", keycode));
478 iecode = usbkeymap[keycode];
479 oldqual = qualifier;
480 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
481 nch->nch_FakeEvent.ie_SubClass = 0;
482 nch->nch_FakeEvent.ie_Code = iecode|IECODE_UP_PREFIX;
483 nch->nch_FakeEvent.ie_NextEvent = NULL;
484 nch->nch_FakeEvent.ie_Qualifier = qualifier;
485 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
486 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
487 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
488 DoIO((struct IORequest *) nch->nch_InpIOReq);
490 buf += 4;
491 len -= 4;
494 /* \\\ */
496 /* /// "nAllocHid()" */
497 struct NepClassHid * nAllocHid(void)
499 struct Task *thistask;
500 struct NepClassHid *nch;
502 thistask = FindTask(NULL);
503 nch = thistask->tc_UserData;
506 if(!(nch->nch_Base = OpenLibrary("poseidon.library", 4)))
508 Alert(AG_OpenLib);
509 break;
511 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface,
512 IFA_Config, &nch->nch_Config,
513 IFA_InterfaceNum, &nch->nch_IfNum,
514 TAG_END);
515 psdGetAttrs(PGA_CONFIG, nch->nch_Config,
516 CA_Device, &nch->nch_Device,
517 TAG_END);
519 nch->nch_EPIn = psdFindEndpoint(nch->nch_Interface, NULL,
520 EA_IsIn, TRUE,
521 EA_TransferType, USEAF_BULK,
522 TAG_END);
523 if(!nch->nch_EPIn)
525 KPRINTF(1, ("Ooops!?! No Endpoints defined?\n"));
526 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname,
527 "No Bulk-In Endpoint!");
528 break;
530 if((nch->nch_InpMsgPort = CreateMsgPort()))
532 if((nch->nch_InpIOReq = (struct IOStdReq *) CreateIORequest(nch->nch_InpMsgPort, sizeof(struct IOStdReq))))
534 if(!OpenDevice("input.device", 0, (struct IORequest *) nch->nch_InpIOReq, 0))
536 nch->nch_InputBase = (struct Library *) nch->nch_InpIOReq->io_Device;
537 if((nch->nch_TaskMsgPort = CreateMsgPort()))
539 if((nch->nch_EP0Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, NULL)))
541 if((nch->nch_EPInPipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EPIn)))
543 psdSetAttrs(PGA_PIPE, nch->nch_EPInPipe,
544 PPA_NakTimeout, FALSE,
545 PPA_AllowRuntPackets, TRUE,
546 TAG_END);
548 if((nch->nch_EPInBuf = psdAllocVec(1024)))
550 nch->nch_Task = thistask;
551 return(nch);
553 psdFreePipe(nch->nch_EPInPipe);
555 psdFreePipe(nch->nch_EP0Pipe);
557 DeleteMsgPort(nch->nch_TaskMsgPort);
559 CloseDevice((struct IORequest *) nch->nch_InpIOReq);
561 DeleteIORequest((struct IORequest *) nch->nch_InpIOReq);
563 DeleteMsgPort(nch->nch_InpMsgPort);
565 } while(FALSE);
566 CloseLibrary(nch->nch_Base);
567 Forbid();
568 nch->nch_Task = NULL;
569 if(nch->nch_ReadySigTask)
571 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
573 return(NULL);
575 /* \\\ */
577 /* /// "nFreeHid()" */
578 void nFreeHid(struct NepClassHid *nch)
580 psdFreeVec(nch->nch_EPInBuf);
581 psdFreePipe(nch->nch_EPInPipe);
582 psdFreePipe(nch->nch_EP0Pipe);
583 DeleteMsgPort(nch->nch_TaskMsgPort);
584 CloseDevice((struct IORequest *) nch->nch_InpIOReq);
585 DeleteIORequest((struct IORequest *) nch->nch_InpIOReq);
586 DeleteMsgPort(nch->nch_InpMsgPort);
587 CloseLibrary(nch->nch_Base);
588 Forbid();
589 nch->nch_Task = NULL;
590 if(nch->nch_ReadySigTask)
592 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
595 /* \\\ */
597 /**************************************************************************/
599 #undef ps
601 /* /// "nLoadClassConfig()" */
602 BOOL nLoadClassConfig(struct NepHidBase *nh)
604 struct Library *ps;
605 struct ClsGlobalCfg *cgc;
606 struct PsdIFFContext *pic;
608 KPRINTF(10, ("Loading Class Config...\n"));
609 if(!(ps = OpenLibrary("poseidon.library", 4)))
611 return(FALSE);
613 Forbid();
614 nh->nh_UsingDefaultCfg = TRUE;
615 pic = psdGetClsCfg(libname);
616 if(pic)
618 if((cgc = psdGetCfgChunk(pic, AROS_LONG2BE(nh->nh_CurrentCGC.cgc_ChunkID))))
620 CopyMem(((UBYTE *) cgc) + 8, ((UBYTE *) &nh->nh_CurrentCGC) + 8, min(AROS_LONG2BE(cgc->cgc_Length), AROS_LONG2BE(nh->nh_CurrentCGC.cgc_Length)));
621 psdFreeVec(cgc);
622 nh->nh_UsingDefaultCfg = FALSE;
625 Permit();
626 CloseLibrary(ps);
627 return(FALSE);
629 /* \\\ */
631 /* /// "nOpenCfgWindow()" */
632 LONG nOpenCfgWindow(struct NepHidBase *nh)
634 struct Library *ps;
635 KPRINTF(10, ("Opening GUI...\n"));
636 if(!(ps = OpenLibrary("poseidon.library", 4)))
638 return(FALSE);
640 Forbid();
641 if(!nh->nh_GUITask)
643 if((nh->nh_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, nh)))
645 Permit();
646 CloseLibrary(ps);
647 return(TRUE);
650 Permit();
651 CloseLibrary(ps);
652 return(FALSE);
654 /* \\\ */
656 /* /// "nGUITask()" */
657 AROS_UFH0(void, nGUITask)
659 AROS_USERFUNC_INIT
661 struct Task *thistask;
662 struct NepHidBase *nh;
663 APTR pic;
665 thistask = FindTask(NULL);
666 #undef ps
667 #define ps nh->nh_PsdBase
668 #undef IntuitionBase
669 #define IntuitionBase nh->nh_IntBase
670 #undef MUIMasterBase
671 #define MUIMasterBase nh->nh_MUIBase
673 nh = thistask->tc_UserData;
674 ++nh->nh_Library.lib_OpenCnt;
675 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
677 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
678 nGUITaskCleanup(nh);
679 return;
682 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
684 KPRINTF(10, ("Couldn't open intuition.library.\n"));
685 nGUITaskCleanup(nh);
686 return;
688 if(!(ps = OpenLibrary("poseidon.library", 4)))
690 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
691 nGUITaskCleanup(nh);
692 return;
695 nh->nh_App = ApplicationObject,
696 MUIA_Application_Title , (IPTR)libname,
697 MUIA_Application_Version , (IPTR)VERSION_STRING,
698 MUIA_Application_Copyright , (IPTR)"©2005-2009 Chris Hodges",
699 MUIA_Application_Author , (IPTR)"Chris Hodges <chrisly@platon42.de>",
700 MUIA_Application_Description, (IPTR)"Settings for the simplemidi.class",
701 MUIA_Application_Base , (IPTR)"SIMPLEMIDI",
702 MUIA_Application_HelpFile , (IPTR)"HELP:Poseidon.guide",
703 MUIA_Application_Menustrip , (IPTR)MenustripObject,
704 Child, (IPTR)MenuObjectT((IPTR)"Project"),
705 Child, (IPTR)(nh->nh_AboutMI = MenuitemObject,
706 MUIA_Menuitem_Title, (IPTR)"About...",
707 MUIA_Menuitem_Shortcut, (IPTR)"?",
708 End),
709 End,
710 Child, (IPTR)MenuObjectT((IPTR)"Settings"),
711 Child, (IPTR)(nh->nh_UseMI = MenuitemObject,
712 MUIA_Menuitem_Title, (IPTR)"Save",
713 MUIA_Menuitem_Shortcut, (IPTR)"S",
714 End),
715 Child, (IPTR)MenuitemObject,
716 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
717 End,
718 Child, (IPTR)(nh->nh_MUIPrefsMI = MenuitemObject,
719 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
720 MUIA_Menuitem_Shortcut, (IPTR)"M",
721 End),
722 End,
723 End,
725 SubWindow, (IPTR)(nh->nh_MainWindow = WindowObject,
726 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
727 MUIA_Window_Title, (IPTR)libname,
728 MUIA_HelpNode, (IPTR)libname,
730 WindowContents, (IPTR)VGroup,
731 /* Child, actionobj = NewObject(ActionClass->mcc_Class, 0,
732 MUIA_ShowMe, FALSE,
733 End, */
734 Child, (IPTR)ColGroup(2), GroupFrameT("Global Settings"),
735 Child, (IPTR)Label((IPTR) "Midi Minimum Octave:"),
736 Child, (IPTR)(nh->nh_MidiMinOctaveObj = SliderObject, SliderFrame,
737 MUIA_CycleChain, 1,
738 MUIA_Numeric_Min, 0,
739 MUIA_Numeric_Max, 10,
740 MUIA_Numeric_Value, nh->nh_CurrentCGC.cgc_MidiMinOctave,
741 End),
742 Child, (IPTR)Label((IPTR) "Maximum Octaves on Keyboard:"),
743 Child, (IPTR)(nh->nh_KeyMaxOctaveObj = SliderObject, SliderFrame,
744 MUIA_CycleChain, 1,
745 MUIA_Numeric_Min, 2,
746 MUIA_Numeric_Max, 10,
747 MUIA_Numeric_Value, nh->nh_CurrentCGC.cgc_KeyMaxOctave,
748 End),
749 Child, (IPTR)Label((IPTR) "Automatic KeyUp Event:"),
750 Child, (IPTR)HGroup,
751 Child, (IPTR)(nh->nh_AutoKeyUpObj = ImageObject, ImageButtonFrame,
752 MUIA_Background, MUII_ButtonBack,
753 MUIA_CycleChain, 1,
754 MUIA_InputMode, MUIV_InputMode_Toggle,
755 MUIA_Image_Spec, MUII_CheckMark,
756 MUIA_Image_FreeVert, TRUE,
757 MUIA_Selected, nh->nh_CurrentCGC.cgc_AutoKeyUp,
758 MUIA_ShowSelState, FALSE,
759 End),
760 Child, (IPTR)HSpace(0),
761 End,
762 End,
763 Child, (IPTR)VSpace(0),
764 Child, (IPTR)HGroup,
765 MUIA_Group_SameWidth, TRUE,
766 Child, (IPTR)(nh->nh_UseObj = TextObject, ButtonFrame,
767 MUIA_Background, MUII_ButtonBack,
768 MUIA_CycleChain, 1,
769 MUIA_InputMode, MUIV_InputMode_RelVerify,
770 MUIA_Text_Contents, (IPTR)"\33c Save ",
771 End),
772 Child, (IPTR)(nh->nh_CloseObj = TextObject, ButtonFrame,
773 MUIA_Background, MUII_ButtonBack,
774 MUIA_CycleChain, 1,
775 MUIA_InputMode, MUIV_InputMode_RelVerify,
776 MUIA_Text_Contents, (IPTR)"\33c Use ",
777 End),
778 End,
779 End,
780 End),
781 End;
783 if(!nh->nh_App)
785 KPRINTF(10, ("Couldn't create application\n"));
786 nGUITaskCleanup(nh);
787 return;
789 DoMethod(nh->nh_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
790 nh->nh_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
791 DoMethod(nh->nh_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
792 nh->nh_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
793 DoMethod(nh->nh_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
794 nh->nh_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
796 DoMethod(nh->nh_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
797 nh->nh_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
798 DoMethod(nh->nh_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
799 nh->nh_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
800 DoMethod(nh->nh_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
801 nh->nh_App, 2, MUIM_Application_OpenConfigWindow, 0);
804 IPTR isopen = 0;
805 IPTR iconify = 0;
806 ULONG sigs;
807 ULONG sigmask;
808 LONG retid;
810 get(nh->nh_App, MUIA_Application_Iconified, &iconify);
811 set(nh->nh_MainWindow, MUIA_Window_Open, TRUE);
812 get(nh->nh_MainWindow, MUIA_Window_Open, &isopen);
813 if(!(isopen || iconify))
815 nGUITaskCleanup(nh);
816 return;
818 sigmask = 0;
821 retid = DoMethod(nh->nh_App, MUIM_Application_NewInput, &sigs);
822 switch(retid)
824 case ID_STORE_CONFIG:
825 case MUIV_Application_ReturnID_Quit:
826 get(nh->nh_MidiMinOctaveObj, MUIA_Numeric_Value, &nh->nh_CurrentCGC.cgc_MidiMinOctave);
827 get(nh->nh_KeyMaxOctaveObj, MUIA_Numeric_Value, &nh->nh_CurrentCGC.cgc_KeyMaxOctave);
828 get(nh->nh_AutoKeyUpObj, MUIA_Selected, &nh->nh_CurrentCGC.cgc_AutoKeyUp);
830 pic = psdGetClsCfg(libname);
831 if(!pic)
833 psdSetClsCfg(libname, NULL);
834 pic = psdGetClsCfg(libname);
836 if(pic)
838 if(psdAddCfgEntry(pic, &nh->nh_CurrentCGC))
840 if(retid != MUIV_Application_ReturnID_Quit)
842 psdSaveCfgToDisk(NULL, FALSE);
844 retid = MUIV_Application_ReturnID_Quit;
847 break;
849 case ID_ABOUT:
850 MUI_RequestA(nh->nh_App, nh->nh_MainWindow, 0, NULL, "Fabulous!", VERSION_STRING, NULL);
851 break;
853 if(retid == MUIV_Application_ReturnID_Quit)
855 break;
857 if(sigs)
859 sigs = Wait(sigs | sigmask | SIGBREAKF_CTRL_C);
860 if(sigs & SIGBREAKF_CTRL_C)
862 break;
865 } while(TRUE);
866 set(nh->nh_MainWindow, MUIA_Window_Open, FALSE);
868 nGUITaskCleanup(nh);
870 AROS_USERFUNC_EXIT
872 /* \\\ */
874 /* /// "nGUITaskCleanup()" */
875 void nGUITaskCleanup(struct NepHidBase *nh)
877 if(nh->nh_App)
879 MUI_DisposeObject(nh->nh_App);
880 nh->nh_App = NULL;
882 if(MUIMasterBase)
884 CloseLibrary(MUIMasterBase);
885 MUIMasterBase = NULL;
887 if(IntuitionBase)
889 CloseLibrary(IntuitionBase);
890 IntuitionBase = NULL;
892 if(ps)
894 CloseLibrary(ps);
895 ps = NULL;
897 Forbid();
898 nh->nh_GUITask = NULL;
899 --nh->nh_Library.lib_OpenCnt;
901 /* \\\ */