/* * AMwindow.c: Subtask für Parameterfenster * * Auto: make AMwindow.o * */ #include "AM.h" #include #include #include #include #include #include #include #if 0 # define D(debug) debug #else # define D(debug) #endif #define abbruch SIGBREAKF_CTRL_C #define MAX(a,b) ( ((a) > (b)) ? (a) : (b) ) /*------------------------- Daten anderer Module...*/ extern struct ExecBase *SysBase; extern struct Library *DOSBase; extern long channel, instr, freqmitte, freqabw, volmitte, volabw; extern double pausen, tonaus; extern char skala[13], cskala[12][13]; /*------------------------- Daten dieses Moduls...*/ static struct TextAttr Topaz80 = { "topaz.font", /* Name */ 8, /* YSize */ 0, /* Style */ 0, /* Flags */ }; struct GfxBase *GfxBase = NULL; struct IntuitionBase *IntuitionBase = NULL; struct Library *GadToolsBase = NULL; struct TextFont *font = NULL; struct Screen *mysc = NULL; struct Gadget *glist = NULL; struct Window *mywin = NULL; void *vi = NULL; static struct Task *windowtask = NULL, *maintask = NULL; static ULONG topborder = 0, bottomEdge = 0; enum { GAD_KANAL = 0, GAD_INSTR, GAD_FREQMITTE, GAD_FREQABW, GAD_VOLMITTE, GAD_VOLABW, GAD_PAUSEN, GAD_TONAUS, GAD_SKALA, GAD_CSKALA_LIST, GAD_CSKALA_STRING, GAD_ANZAHL }; struct Gadget *mgg[ GAD_ANZAHL ]; char lt_skala[12][16]; /* Texte für ListView */ struct List lh_skala; /* ListHeader */ struct Node nd_skala[12]; /* Knoten für Liste */ /*------------------------- Code-Deklarationen...*/ extern void ProgChange( int ); extern void AllNotesOff( void ); extern LONG Printf( UBYTE *, ... ); BOOL subinit( void ); void subclosedown( void ); void handlewindowmsg( void ); struct Gadget *CreateAllGadgets(struct Gadget **, void *, UWORD); void closewindow( void ); /*------------------------- Stub-Code...*/ struct Gadget *CreateGadget( unsigned long kind, struct Gadget *gad, struct NewGadget *ng, Tag tag1, ... ) { return CreateGadgetA( kind, gad, ng, (struct TagItem *)&tag1 ); } APTR GetVisualInfo( struct Screen *screen, Tag tag1, ... ) { return GetVisualInfoA( screen, (struct TagItem *)&tag1 ); } struct Window *OpenWindowTags( struct NewWindow *newWindow, unsigned long tag1Type, ... ) { return OpenWindowTagList( newWindow, (struct TagItem *)&tag1Type ); } void GT_SetGadgetAttrs( struct Gadget *gad, struct Window *win, struct Requester *req, Tag tag1, ... ) { GT_SetGadgetAttrsA( gad, win, req, (struct TagItem *)&tag1 ); } /*------------------------- Code-Definitionen...*/ static void windowtaskcode( void ) { long wmsg=0, sgns; geta4(); if( !subinit() ) return; wmsg = 1 << mywin->UserPort->mp_SigBit; while(1) { sgns = Wait( wmsg | abbruch ); if( sgns & wmsg ) { handlewindowmsg(); SetSignal( 0, wmsg ); } if( sgns & abbruch ) { subclosedown(); mywin = 0; return; } } } /* CreateAllGadgets() * * Diese Routine führt alle Gadget-Initialisierungen aus. * glistptr ist ein auf NULL initialisierter GadgetList-Zeiger * Rückgabe ist ein Zeiger auf das zuletzt erzeugte Gadget (also * NULL bei Fehler) * */ static struct Gadget *CreateAllGadgets( struct Gadget **glistptr, void *vi, UWORD topborder ) { struct NewGadget ng; struct Gadget *gad; int i; /* All the gadget creation calls accept a pointer to the previous gadget, and link the new gadget to that gadget's NextGadget field. Also, they exit gracefully, returning NULL, if any previous gadget was NULL. This limits the amount of checking for failure that is needed. You only need to check before you tweak any gadget structure or use any of its fields, and finally once at the end, before you add the gadgets. */ /* We obligingly perform the following operation, required of any program that uses the toolkit. It gives the toolkit a place to stuff context data: */ gad = CreateContext(glistptr); /* Since the NewGadget structure is unmodified by any of the CreateGadget() calls, we need only change those fields which are different. */ ng.ng_LeftEdge = 72; ng.ng_TextAttr = &Topaz80; ng.ng_VisualInfo = vi; ng.ng_Width = 120; ng.ng_Height = 12; ng.ng_Flags = 0; ng.ng_TopEdge = topborder + INTERHEIGHT; ng.ng_GadgetText = "Kanal:"; ng.ng_GadgetID = GAD_KANAL; mgg[GAD_KANAL] = gad = CreateGadget(SLIDER_KIND, gad, &ng, GTSL_Min, 1, GTSL_Max, 16, GTSL_Level, channel+1, GTSL_LevelFormat, "%2ld", GTSL_LevelPlace, PLACETEXT_RIGHT, GTSL_MaxLevelLen, 2, GA_IMMEDIATE, TRUE, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+INTERHEIGHT; ng.ng_GadgetText = "Instr:"; ng.ng_GadgetID = GAD_INSTR; mgg[GAD_INSTR] = gad = CreateGadget(SLIDER_KIND, gad, &ng, GTSL_Min, 0, GTSL_Max, 64, GTSL_Level, instr+1, GTSL_LevelFormat, "%2ld", GTSL_LevelPlace, PLACETEXT_RIGHT, GTSL_MaxLevelLen, 2, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+2*INTERHEIGHT; ng.ng_GadgetText = "F-Ber:"; ng.ng_GadgetID = GAD_FREQMITTE; mgg[GAD_FREQMITTE] = gad = CreateGadget(SCROLLER_KIND, gad, &ng, GTSC_Top, freqmitte-freqabw, GTSC_Total, 128, GTSC_Visible, freqabw*2, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+INTERHEIGHT; ng.ng_GadgetText = "F-Abw:"; ng.ng_GadgetID = GAD_FREQABW; mgg[GAD_FREQABW] = gad = CreateGadget(SLIDER_KIND, gad, &ng, GTSL_Min, 0, GTSL_Max, 63, GTSL_Level, freqabw, GTSL_LevelFormat, "±%3ld½", GTSL_LevelPlace, PLACETEXT_RIGHT, GTSL_MaxLevelLen, 5, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+2*INTERHEIGHT; ng.ng_GadgetText = "V-Ber:"; ng.ng_GadgetID = GAD_VOLMITTE; mgg[GAD_VOLMITTE] = gad = CreateGadget(SCROLLER_KIND, gad, &ng, GTSC_Top, volmitte-volabw, GTSC_Total, 128, GTSC_Visible, volabw*2, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+INTERHEIGHT; ng.ng_GadgetText = "V-Abw:"; ng.ng_GadgetID = GAD_VOLABW; mgg[GAD_VOLABW] = gad = CreateGadget(SLIDER_KIND, gad, &ng, GTSL_Min, 0, GTSL_Max, 63, GTSL_Level, volabw, GTSL_LevelFormat, "±%3ld½", GTSL_LevelPlace, PLACETEXT_RIGHT, GTSL_MaxLevelLen, 5, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+2*INTERHEIGHT; ng.ng_GadgetText = "Pausen:"; ng.ng_GadgetID = GAD_PAUSEN; mgg[GAD_PAUSEN] = gad = CreateGadget(SLIDER_KIND, gad, &ng, GTSL_Min, 0, GTSL_Max, 100, GTSL_Level, (long)(pausen*100), GTSL_LevelFormat, "%3ld %%", GTSL_LevelPlace, PLACETEXT_RIGHT, GTSL_MaxLevelLen, 5, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+INTERHEIGHT; ng.ng_GadgetText = "TonAus:"; ng.ng_GadgetID = GAD_TONAUS; mgg[GAD_PAUSEN] = gad = CreateGadget(SLIDER_KIND, gad, &ng, GTSL_Min, 0, GTSL_Max, 100, GTSL_Level, (long)(tonaus*100), GTSL_LevelFormat, "%3ld %%", GTSL_LevelPlace, PLACETEXT_RIGHT, GTSL_MaxLevelLen, 5, GA_RELVERIFY, TRUE, TAG_DONE); ng.ng_TopEdge += 12+INTERHEIGHT; ng.ng_GadgetText = "Skala:"; ng.ng_GadgetID = GAD_SKALA; ng.ng_Height = 14; mgg[GAD_SKALA] = gad = CreateGadget(STRING_KIND, gad, &ng, GTST_MaxChars, 12, GTST_String, skala, STRINGA_ReplaceMode, TRUE, TAG_DONE); /* String-Gadget für ListView: */ ng.ng_GadgetText = NULL; ng.ng_GadgetID = GAD_CSKALA_STRING; ng.ng_Height = 14; ng.ng_Width += 40; mgg[GAD_CSKALA_STRING] = gad = CreateGadget(STRING_KIND, gad, &ng, GTST_MaxChars, 15, STRINGA_ReplaceMode, TRUE, TAG_DONE); /* Liste der Continue-Skalen */ ng.ng_TopEdge += 12+2*INTERHEIGHT; ng.ng_GadgetText = "CSkala:"; ng.ng_Flags = PLACETEXT_LEFT; ng.ng_GadgetID = GAD_CSKALA_LIST; ng.ng_Height = 4 + 8 * 9 + 14; mgg[GAD_CSKALA_LIST] = gad = CreateGadget(LISTVIEW_KIND, gad, &ng, LAYOUTA_SPACING, 1, GTLV_Labels, &lh_skala, GTLV_ShowSelected, mgg[GAD_CSKALA_STRING], TAG_DONE); i = GAD_CSKALA_STRING; bottomEdge = mgg[i]->TopEdge + mgg[i]->Height + 2*INTERHEIGHT; return(gad); } static BOOL subinit( void ) // Fenster öffnen etc. { // zunächst mal probieren, ob wir ein Fenster kriegen können... mywin = OpenWindowTags(NULL, WA_Title, "AM Parameter", WA_Width, 250, WA_Height, bottomEdge, WA_MinWidth, 50, WA_MinHeight, 50, WA_MaxWidth, 250, WA_MaxHeight, bottomEdge, WA_Activate, TRUE, WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_CloseGadget, TRUE, WA_SimpleRefresh, TRUE, WA_IDCMP, CLOSEWINDOW | REFRESHWINDOW | \ SLIDERIDCMP | SCROLLERIDCMP | STRINGIDCMP | \ LISTVIEWIDCMP, TAG_DONE); // Na? Haben wir's? if( !mywin ) return FALSE; // Ja! Nun Gadgets anhängen und refreshen... AddGList( mywin, glist, 0, -1, NULL ); RefreshGList( glist, mywin, NULL, -1 ); GT_RefreshWindow( mywin, NULL ); return TRUE; } static void subclosedown( void ) { if(mywin) CloseWindow(mywin); mywin=0; } static BOOL HandleGadgetEvent( struct Gadget *gad, UWORD code ) { char *s; long i; switch (gad->GadgetID) { case GAD_KANAL: // unkritisch AllNotesOff(); channel = (WORD) code - 1; break; case GAD_INSTR: instr = (WORD) code - 1; if( instr>=0 ) ProgChange( instr ); break; case GAD_FREQMITTE: // unkritisch freqmitte = (WORD) code + freqabw; break; case GAD_FREQABW: freqabw = (WORD) code; // Grenzen neu checken if( freqmitte+freqabw > 127 ) freqmitte = 127 - freqabw; else if( freqmitte-freqabw < 0 ) freqmitte = freqabw; // Scroller ändern GT_SetGadgetAttrs( mgg[GAD_FREQMITTE], mywin, NULL, GTSC_Top, freqmitte-freqabw, GTSC_Visible, freqabw*2, TAG_DONE ); break; case GAD_VOLMITTE: // unkritisch volmitte = (WORD) code + volabw; break; case GAD_VOLABW: volabw = (WORD) code; // Grenzen neu checken if( volmitte+volabw > 127 ) volmitte = 127 - volabw; else if( volmitte-volabw < 0 ) volmitte = volabw; // Scroller ändern GT_SetGadgetAttrs( mgg[GAD_VOLMITTE], mywin, NULL, GTSC_Top, volmitte-volabw, GTSC_Visible, volabw*2, TAG_DONE ); break; case GAD_PAUSEN: // unkritisch pausen = (WORD) code / 100.0; break; case GAD_TONAUS: // unkritisch tonaus = (WORD) code / 100.0; break; case GAD_SKALA: s = ((struct StringInfo *)gad->SpecialInfo)->Buffer; // 12 Zeichen? if( strlen(s)==12 ) strcpy( skala, s ); else GT_SetGadgetAttrs( gad, mywin, NULL, GTST_String, skala, TAG_DONE ); break; case GAD_CSKALA_LIST: ActivateGadget( mgg[GAD_CSKALA_STRING], mywin, NULL ); break; case GAD_CSKALA_STRING: s = ((struct StringInfo *)gad->SpecialInfo)->Buffer; i = atol(s); if( s[2]==':' && i>=0 && i<=11 ) { if( strlen(s)==15 ) { // komplett -> einbauen bzw. ersetzen strcpy( cskala[i], s+3 ); strcpy( lt_skala[i], s ); GT_SetGadgetAttrs( mgg[GAD_CSKALA_LIST], mywin, NULL, GTLV_Labels, &lh_skala, TAG_DONE ); RefreshGList( mgg[GAD_CSKALA_LIST], mywin, NULL, 1 ); } else if( s[3] == 0 ) { // nur noch Index -> löschen cskala[i][0] = 0; lt_skala[i][3] = 0; GT_SetGadgetAttrs( mgg[GAD_CSKALA_LIST], mywin, NULL, GTLV_Labels, &lh_skala, TAG_DONE ); RefreshGList( mgg[GAD_CSKALA_LIST], mywin, NULL, 1 ); } } break; } } static void handlewindowmsg( void ) { struct IntuiMessage *imsg; struct Gadget *gad; ULONG imsgClass; UWORD imsgCode; while( imsg = GT_GetIMsg(mywin->UserPort) ) { imsgClass = imsg->Class; imsgCode = imsg->Code; gad = (struct Gadget *)imsg->IAddress; // ^^^ natürlich nur bei Gadgets gültig GT_ReplyIMsg(imsg); switch (imsgClass) { case MOUSEMOVE: case GADGETUP: HandleGadgetEvent(gad, imsgCode); break; case CLOSEWINDOW: // Nur HauptTask signalisieren Signal( maintask, SIGBREAKF_CTRL_C ); break; case REFRESHWINDOW: GT_BeginRefresh(mywin); GT_EndRefresh(mywin, TRUE); break; } } } //---------------------- Nach außen sichtbare Funktionen: BOOL startwindow( void ) // Libs öffnen, etc., Task starten { int i; if( !(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 36L))) return( FALSE ); if( !(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 36L))) { closewindow(); return( FALSE ); } if( !(GadToolsBase = OpenLibrary("gadtools.library", 36L))) { closewindow(); return( FALSE ); } if( !(font = OpenFont(&Topaz80))) { closewindow(); return( FALSE ); } if( !(mysc = LockPubScreen(NULL))) { closewindow(); return( FALSE ); } if( !(vi = GetVisualInfo(mysc,TAG_DONE))) { closewindow(); return( FALSE ); } topborder = mysc->WBorTop + (mysc->Font->ta_YSize + 1); NewList( &lh_skala ); for( i=0; i<=11; i++ ) { sprintf( lt_skala[i], "%02d:%s", i, cskala[i] ); nd_skala[i].ln_Name = lt_skala[i]; AddTail( &lh_skala, &nd_skala[i] ); } if( !CreateAllGadgets(&glist, vi, topborder)) { closewindow(); return( FALSE ); } maintask = SysBase->ThisTask; windowtask = CreateTask( "AMsub", 0, windowtaskcode, 4000 ); return( windowtask != 0 ); } void closewindow( void ) { // SubTask bescheid sagen if(windowtask) { Signal( windowtask, SIGBREAKF_CTRL_C ); while( mywin ) Delay(25); windowtask=0; } if(GadToolsBase) { FreeVisualInfo(vi); vi=0; FreeGadgets(glist); glist=0; CloseLibrary(GadToolsBase); GadToolsBase=0; } if(mysc) UnlockPubScreen(NULL, mysc); mysc=0; if(font) CloseFont(font); font=0; if(IntuitionBase) CloseLibrary(IntuitionBase); IntuitionBase=0; if(GfxBase) CloseLibrary(GfxBase); GfxBase=0; }