home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / datatypes / mididt / source / dispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-04  |  20.8 KB  |  825 lines

  1. /*
  2. ** $PROJECT: midi.datatype
  3. **
  4. ** $VER: dispatch.c 40.0 (11.09.97)
  5. **
  6. ** This file holds the datatypes class dispatcher and handles the
  7. ** BOOPSI gadget (control panel).
  8. **
  9. ** Copyright 1997 by Martin Gierich.
  10. ** All Rights Reserved !
  11. **
  12. ** Based on binary.datatype created by Stefan Ruppert.
  13. **
  14. ** $HISTORY:
  15. ** 11.09.97 : 40.00 : Initial BETA release
  16. **
  17. ** $TABSIZE: 3
  18. */
  19.  
  20.  
  21. /* ------------------------------- autodoc -------------------------------- */
  22.  
  23. /*FS*/ /*"AutoDoc"*/
  24. /****** midi.datatype/midi.datatype **************************************
  25. *
  26. *    NAME
  27. *        midi.datatype -- data type for midi stream files with timestamps
  28. *
  29. *    FUNCTION
  30. *        The midi data type, a base-class of all midi data, is used to
  31. *        load, save and play standard midi files and similar music files
  32. *        (using datatypes subclasses). A control panel can be applied to a
  33. *        window.
  34. *        The control panel currently is very simple and triggers one of
  35. *        STM_PLAY and STM_PAUSE, depending on the playing state.
  36. *        The midi player makes use of camd.library and realtime.library.
  37. *
  38. *    PREFS
  39. *        The data type tries to load the prefs file from
  40. *        "ENV:DataTypes/midi.prefs" and parses it using ReadArgs() on each
  41. *        OM_NEW method to set up the attributes. The template is:
  42. *
  43. *        CLUSTER/K,VOLUME/N/K
  44. *
  45. *        CLUSTER   - sets MDTA_Cluster to the given name, default is "out.0".
  46. *        VOLUME    - sets SDTA_Volume to the given value, default is 64.
  47. *
  48. *        The options can be on several lines. The prefs file must end with
  49. *        a line feed, so you cannot use SETENV.
  50. *
  51. *    METHODS
  52. *        OM_NEW -- Create a new object from a SMF file
  53. *
  54. *        OM_DISPOSE -- dispose the object (triggers STM_STOP)
  55. *
  56. *        OM_GET -- get a attribute of the object
  57. *
  58. *        OM_SET -- set attributes of the object
  59. *
  60. *        OM_UPDATE -- update some attributes of the object
  61. *
  62. *        GM_HITTEST -- check if gadget has been hit
  63. *
  64. *        GM_GOACTIVE -- gadget pressed
  65. *
  66. *        GM_GOINACTIVE -- gadget released
  67. *
  68. *        GM_HANDLEINPUT -- handle intuition input events
  69. *
  70. *        GM_LAYOUT -- layout the control panel (calculate sizes)
  71. *
  72. *        GM_RENDER -- attach the control panel to a window
  73. *
  74. *        DTM_REMOVEDTOBJECT -- remove control panel from window
  75. *
  76. *        DTM_WRITE
  77. *            DTWM_RAW writes a SMF file
  78. *            DTWM_IFF is unsupported, since there is no IFF-MIDI format yet
  79. *
  80. *        DTM_TRIGGER
  81. *            STM_PLAY starts playing (a separate process will be launched)
  82. *                     or continues playing after pause
  83. *            STM_PAUSE pauses playing (might start playing first)
  84. *            STM_STOP stops playing and removes the player process
  85. *
  86. *    TAGS
  87. *        MDTA_Cluster -- (UBYTE *) name of the CAMD cluster to play midi
  88. *            data to. Default: "out.0". Applicability is (ISG).
  89. *
  90. *        Tags defined in datatypes/soundclass.h:
  91. *        SDTA_Cycles
  92. *        SDTA_Volume -- volume does not get used yet
  93. *        SDTA_SignalTask
  94. *        SDTA_SignalBit
  95. *
  96. *        Tags defined in datatypes/datatypesclass.h
  97. *        DTA_Methods
  98. *        DTA_TriggerMethods
  99. *        DTA_NominalVert
  100. *        DTA_NominalHoriz
  101. *        DTA_Title
  102. *        DTA_ObjName
  103. *        DTA_Name
  104. *        DTA_Immediate
  105. *        DTA_Repeat
  106. *
  107. *        Tags that will change in future, do not use !
  108. *        MDTA_Buffer -- (UBYTE *) pointer to buffer with SMF file contents
  109. *        MDTA_BufferLen -- (ULONG) size of this buffer
  110. *
  111. *    LIMITATIONS
  112. *        It is not very useful for loading/saving yet.
  113. *        No reset gets send before starting playing.
  114. *        No use is made of volume setting.
  115. *
  116. *    BUGS
  117. *        None known.
  118. *
  119. *    SEE ALSO
  120. *        datatypesclass (have a look at datatypes.library V45),
  121. *        sound_dtc
  122. *
  123. ******************************************************************************
  124. */
  125. /*FE*/
  126.  
  127.  
  128. /* ------------------------------- includes ------------------------------- */
  129.  
  130. #include <string.h>
  131.  
  132. #include <exec/types.h>
  133. #include <exec/ports.h>
  134. #include <exec/memory.h>
  135. #include <exec/lists.h>
  136. #include <exec/semaphores.h>
  137. #include <exec/execbase.h>
  138. #include <dos/dos.h>
  139. #include <dos/dostags.h>
  140. #include <dos/dosextens.h>
  141. #include <intuition/intuition.h>
  142. #include <intuition/classes.h>
  143. #include <intuition/classusr.h>
  144. #include <intuition/cghooks.h>
  145. #include <intuition/gadgetclass.h>
  146. #include <intuition/imageclass.h>
  147. #include <graphics/gfxbase.h>
  148. #include <graphics/gfx.h>
  149. #include <utility/tagitem.h>
  150. #include <libraries/gadtools.h>
  151. #include <datatypes/datatypes.h>
  152. #include <datatypes/datatypesclass.h>
  153. #include <datatypes/soundclass.h>
  154.  
  155. #include <clib/alib_protos.h>
  156. #include <clib/alib_stdio_protos.h>
  157. #include <proto/dos.h>
  158. #include <proto/exec.h>
  159. #include <proto/intuition.h>
  160. #include <proto/iffparse.h>
  161. #include <proto/graphics.h>
  162. #include <proto/utility.h>
  163. #include <proto/datatypes.h>
  164. #include <proto/dtclass.h>
  165.  
  166. #include "debug.h"
  167. #include "register.h"
  168. #include "midiclass.h"
  169.  
  170.  
  171. /* ------------------------------ prototypes ------------------------------ */
  172.  
  173. ClassCall ULONG dispatch ( REGA0 Class *cl , REGA2 Object *obj , REGA1 Msg msg );
  174. ULONG RenderPlayButton(Object *obj, struct GadgetInfo *gi, struct MidiDTData *mdt);
  175. void drawFrame(struct RastPort *rp, UWORD pen1, UWORD pen2, UWORD pen3, WORD x, WORD y, WORD w, WORD h);
  176. BOOL readPrefs(struct MidiDTData *bd, STRPTR file);
  177. ULONG getattr(Class *cl, Object *obj, struct opGet *msg);
  178. ULONG setattrs(Class *cl, Object *obj, struct opSet *msg);
  179. ULONG notifyAttrChanges(Object *obj, void *ginfo, ULONG flags, ULONG tag1,...);
  180. ULONG setSuperAttrs(Class *cl,Object *obj, void *ginfo, ULONG tag1,...);
  181. ULONG TriggerPlayMidi(struct MidiDTData *mdt, ULONG Function, APTR Data);
  182. ClassCall void PlayMidi(void);
  183.  
  184.  
  185. /* ------------------------------- defines -------------------------------- */
  186.  
  187. #define GOBJ(o)            ((struct Gadget *) (o))
  188. #define GPRMSG(msg)        ((struct gpRender *) (msg))
  189. #define GPIMSG(msg)        ((struct gpInput *) (msg))
  190. #define SETMSG(msg)        ((struct opSet *) (msg))
  191. #define WRMSG(msg)        ((struct dtWrite *) (msg))
  192. #define TRMSG(msg)        ((struct dtTrigger *) (msg))
  193.  
  194. #define ISBITSET(x,y) ((x)&(y))
  195. #define ISBITCLEARED(x,y) (!((x)&(y)))
  196. #define SETBIT(x,y) ((x)|=(y))
  197. #define CLEARBIT(x,y) ((x)&=~(y))
  198.  
  199. #define prefstemplate      "CLUSTER/K,VOLUME/N/K"
  200. enum
  201. {
  202.     ARG_CLUSTER,
  203.     ARG_VOLUME,
  204.     ARG_MAX
  205. };
  206.  
  207.  
  208. /* ---------------------------- constant data ----------------------------- */
  209.  
  210. const ULONG methods[] = {
  211.     OM_NEW,
  212.     OM_DISPOSE,
  213.     OM_GET,
  214.     OM_SET,
  215.     OM_UPDATE,
  216.     GM_HITTEST,
  217.     GM_GOACTIVE,
  218.     GM_GOINACTIVE,
  219.     GM_HANDLEINPUT,
  220.     GM_LAYOUT,
  221.     GM_RENDER,
  222.     DTM_REMOVEDTOBJECT,
  223.     DTM_WRITE,
  224.     DTM_TRIGGER,
  225.     ~0};
  226.  
  227. const struct DTMethod triggers[] = {
  228.     {"PLAY","PLAY",STM_PLAY},
  229.     {"PAUSE","PAUSE",STM_PAUSE},
  230.     {"STOP","STOP",STM_STOP},
  231.     {NULL,NULL,0L}
  232.     };
  233.  
  234. extern char ExLibName[];
  235.  
  236.  
  237. /* --------------------------- class dispatcher --------------------------- */
  238.  
  239. /*FS*/ Class *initClass (struct ClassBase * cb)
  240. {
  241.  Class *cl;
  242.  
  243.  if (cl = MakeClass (&ExLibName[0], "datatypesclass", NULL, sizeof(struct MidiDTData), 0L))
  244.   {
  245.    cl->cl_Dispatcher.h_Entry = (HOOKFUNC) dispatch;
  246.    cl->cl_UserData = (ULONG) cb;
  247.    AddClass (cl);
  248.   }
  249.  
  250.  return (cl);
  251. }
  252. /*FE*/
  253.  
  254.  
  255. /*FS*/ ClassCall ULONG dispatch(REGA0 Class *cl,REGA2 Object *obj,REGA1 Msg msg)
  256. {
  257.     //struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
  258.     struct MidiDTData *mdt = INST_DATA(cl,obj);
  259.     ULONG retval = 0;
  260.  
  261.     //D(bug("ID: 0x%lx TaskPri: %ld  ",msg->MethodID,FindTask(NULL)->tc_Node.ln_Pri));
  262.     switch(msg->MethodID)
  263.     {
  264.  
  265.     case OM_NEW:
  266.         {
  267.             Object    *newobj;
  268.             ULONG        filesize;
  269.  
  270.             if((newobj = (Object *) DoSuperMethodA(cl,obj,msg)))
  271.             {
  272.                 mdt = INST_DATA(cl,newobj);
  273.  
  274.                 D(bug("Method: OM_NEW cl=%lx obj=%lx msg=%lx mdt=%lx\n",cl,obj,msg,mdt));
  275.                 mdt->mdt_Flags=0;
  276.                 mdt->mdt_Cycles=1;
  277.                 mdt->mdt_Volume=64;
  278.                 mdt->mdt_Playing=STM_STOP;
  279.                 strcpy(mdt->mdt_Cluster, "out.0");
  280.                 readPrefs(mdt, "ENV:DataTypes/midi.prefs");
  281.                 setattrs(cl,newobj,(struct opSet *) msg);
  282.  
  283.                 /* if no buffer is provided , get the handle from the superclass
  284.                     and load the file in the buffer */
  285.                 if(!mdt->mdt_Buffer)
  286.                 {
  287.                     BPTR fh;
  288.                     ULONG type;
  289.                     LONG num;
  290.  
  291.                     if(((num = GetDTAttrs((Object *) newobj,DTA_Handle        , &fh,
  292.                                                                          DTA_SourceType, &type,
  293.                                                                          TAG_DONE)) == 2) && fh)
  294.                     {
  295.                         switch(type)
  296.                         {
  297.                         case DTST_FILE:
  298.                             if( Seek(fh,0L,OFFSET_END) != -1 )
  299.                             {
  300.                                 if( (filesize=Seek(fh,0L,OFFSET_BEGINNING)) != -1 )
  301.                                 {
  302.                                     if((mdt->mdt_Buffer = AllocMem(filesize, MEMF_ANY|MEMF_PUBLIC)))
  303.                                     {
  304.                                         SETBIT(mdt->mdt_Flags, MDTF_ALLOCATED);
  305.                                         mdt->mdt_BufferLen = filesize;
  306.                                         mdt->mdt_BufferEnd = &mdt->mdt_Buffer[filesize];
  307.                                         Read(fh,mdt->mdt_Buffer,filesize);
  308.                                     }
  309.                                 }
  310.                             }
  311.                             if(!NameFromFH(fh,mdt->mdt_FileName,sizeof(mdt->mdt_FileName)))
  312.                                 strcpy(mdt->mdt_FileName,"unknown");
  313.                             break;
  314.                         case DTST_RAM:
  315.                             strcpy(mdt->mdt_FileName,"RAM");
  316.                             break;
  317.                         default:
  318.                             D(bug("not supported SourceType : %ld\n",type));
  319.                         }
  320.  
  321.                     }
  322.                 }
  323.  
  324.                 if(mdt->mdt_Buffer)
  325.                 {
  326.                     retval = (ULONG) newobj;
  327.                     setSuperAttrs(cl,newobj,NULL,GA_RelSpecial,TRUE,TAG_DONE);
  328.                     if (mdt->mdt_Immediate)
  329.                         DoMethod(newobj,DTM_TRIGGER,NULL,STM_PLAY,NULL);
  330.                     D(bug("Buffer=0x%lx Size=%ld\n",mdt->mdt_Buffer,mdt->mdt_BufferLen));
  331.                 } else  /* something was going wrong, thus dispose myself */
  332.                 {
  333.                     D(bug("midi.datatype IO error : %ld\n",IoErr()));
  334.                     CoerceMethod(cl,(Object *) retval,OM_DISPOSE);
  335.                 }
  336.             }
  337.             else
  338.                 D(bug("Error during OM_NEW !\n"));
  339.         }
  340.         break;
  341.  
  342.     case OM_DISPOSE:
  343.         D(bug("Method: OM_DISPOSE\n"));
  344.         TriggerPlayMidi(mdt, STM_STOP, NULL);
  345.         while(mdt->mdt_PlayProc)
  346.             Delay(10);
  347.         if(mdt->mdt_Buffer && ISBITSET(mdt->mdt_Flags, MDTF_ALLOCATED))
  348.         {
  349.             FreeMem(mdt->mdt_Buffer,mdt->mdt_BufferLen);
  350.             D(bug("Dispose OK\n"));
  351.         }
  352.         retval = DoSuperMethodA(cl,obj,msg);
  353.         break;
  354.  
  355.     case OM_UPDATE:
  356.         D(bug("Method: OM_UPDATE\n"));
  357.         goto OM_SETstart;
  358.     case OM_SET:
  359.         D(bug("Method: OM_SET\n"));
  360.         OM_SETstart:
  361.         if((retval = setattrs(cl,obj,SETMSG(msg))))
  362.             if( ISBITSET(mdt->mdt_Flags, MDTF_NEEDLAYOUT) && SETMSG(msg)->ops_GInfo )
  363.             {
  364.                 D(bug("SET/UPDATE calls GM_LAYOUT\n"));
  365.                 DoMethod(obj,GM_LAYOUT,SETMSG(msg)->ops_GInfo,TRUE);
  366.                 CLEARBIT(mdt->mdt_Flags, MDTF_NEEDLAYOUT);
  367.             }
  368.  
  369.         /* Pass the attributes to the super class and force a refresh if we need it */
  370.         if((retval += DoSuperMethodA (cl, obj, msg)) && (OCLASS (obj) == cl))
  371.         {
  372.             struct RastPort *rp;
  373.  
  374.             /* Get a pointer to the rastport */
  375.             if( SETMSG(msg)->ops_GInfo && (rp = ObtainGIRPort(SETMSG(msg)->ops_GInfo)))
  376.             {
  377.                 D(bug("SET/UPDATE calls GM_RENDER\n"));
  378.  
  379.                 /* Force a redraw */
  380.                 DoMethod(obj,GM_RENDER,SETMSG(msg)->ops_GInfo,rp,GREDRAW_REDRAW);
  381.  
  382.                 /* Release the temporary rastport */
  383.                 ReleaseGIRPort (rp);
  384.             }
  385.  
  386.             if(msg->MethodID == OM_UPDATE)
  387.                 DoMethod(obj,OM_NOTIFY,SETMSG(msg)->ops_AttrList,SETMSG(msg)->ops_GInfo,0);
  388.  
  389.             retval = 0;
  390.         }
  391.         break;
  392.  
  393.     case OM_GET:
  394.         if(!(retval = getattr(cl,obj,(struct opGet *) msg)))
  395.             retval = DoSuperMethodA(cl,obj,msg);
  396.         D(bug("Method: OM_GET %lx ret %lx %lx\n",((struct opGet *)msg)->opg_AttrID,retval,*((struct opGet *)msg)->opg_Storage));
  397.         break;
  398.  
  399.     case GM_HITTEST:
  400.         D(bug("Method: OM_HITTEST\n"));
  401.         retval=GMR_GADGETHIT;
  402.         break;
  403.  
  404.     case GM_GOACTIVE:
  405.         if(GPIMSG(msg)->gpi_IEvent && ISBITCLEARED(GOBJ(obj)->Flags, GFLG_DISABLED) )
  406.         {
  407.             SETBIT(GOBJ(obj)->Flags, GFLG_SELECTED);
  408.             RenderPlayButton(obj, GPIMSG(msg)->gpi_GInfo, mdt);
  409.             retval=GMR_MEACTIVE;
  410.         }
  411.         else
  412.             retval=GMR_NOREUSE;
  413.         D(bug("Method: OM_GOACTIVE ret %lx\n",retval));
  414.         break;
  415.  
  416.     case GM_GOINACTIVE:
  417.         D(bug("Method: OM_GOINACTIVE\n"));
  418.         CLEARBIT(GOBJ(obj)->Flags, GFLG_SELECTED);
  419.         retval=RenderPlayButton(obj, GPIMSG(msg)->gpi_GInfo, mdt);
  420.         break;
  421.  
  422.     case GM_LAYOUT:
  423.         D(bug("Method: OM_LAYOUT\n"));
  424.         /* Let the super-class partake */
  425.         DoSuperMethodA (cl, obj, msg);
  426.         retval=GetDTAttrs(obj, DTA_Domain, &(mdt->mdt_Domain), TAG_DONE);
  427.         if ( ((struct gpLayout *)msg)->gpl_Initial )
  428.         {
  429.             notifyAttrChanges (obj, ((struct gpLayout *) msg)->gpl_GInfo, NULL,
  430.                                  GA_ID,                    GOBJ(obj)->GadgetID,
  431.                                  DTA_NominalVert,        50,
  432.                                  DTA_NominalHoriz,    50,
  433.                                  DTA_Title,                mdt->mdt_Name,
  434.                                  DTA_Busy,                FALSE,
  435.                                  DTA_Sync,                TRUE,
  436.                                  TAG_DONE);
  437.         }
  438.         break;
  439.  
  440.     case GM_RENDER:
  441.         D(bug("Method: OM_RENDER\n"));
  442.         RenderPlayButton(obj, GPRMSG(msg)->gpr_GInfo, mdt);
  443.         retval=1;
  444.         break;
  445.  
  446.     case DTM_REMOVEDTOBJECT:
  447.         D(bug("Method: DTM_REMOVEDTOBJECT\n"));
  448.         retval = DoSuperMethodA(cl,obj,msg);
  449.       break;
  450.  
  451.     case GM_HANDLEINPUT:
  452.         {
  453.             struct Gadget        *g=GOBJ(obj);
  454.             struct gpInput        *gpi=GPIMSG(msg);
  455.             struct InputEvent    *ie=gpi->gpi_IEvent;
  456.  
  457.             D(bug("Method: OM_HANDLEINPUT Class %lx Code %lx\n",ie->ie_Class,ie->ie_Code));
  458.             retval=GMR_MEACTIVE;
  459.             if(ie->ie_Class==IECLASS_RAWMOUSE)
  460.                 switch (ie->ie_Code)
  461.                 {
  462.                     case SELECTUP:
  463.                         if(    (gpi->gpi_Mouse.X < 5)                                    ||
  464.                                 (gpi->gpi_Mouse.X > mdt->mdt_Domain->Width-5)    ||
  465.                                 (gpi->gpi_Mouse.Y < 5)                                    ||
  466.                                 (gpi->gpi_Mouse.Y > mdt->mdt_Domain->Height-5))
  467.                             {
  468.                                 D(bug("REUSE\n"));
  469.                                 retval=GMR_REUSE;
  470.                             }
  471.                         else
  472.                             {
  473.                                 D(bug("NOREUSE\n"));
  474.                                 retval=GMR_NOREUSE|GMR_VERIFY;
  475.                                 TriggerPlayMidi(mdt, mdt->mdt_Playing==STM_PLAY ?
  476.                                          STM_PAUSE : STM_PLAY, NULL);
  477.                             }
  478.                         break;
  479.  
  480.                     case MENUDOWN:
  481.                         D(bug("MENU\n"));
  482.                         retval=GMR_REUSE;
  483.                         break;
  484.  
  485.                     case IECODE_NOBUTTON:
  486.                         if(    (gpi->gpi_Mouse.X < 5)                                    ||
  487.                                 (gpi->gpi_Mouse.X > mdt->mdt_Domain->Width-5)    ||
  488.                                 (gpi->gpi_Mouse.Y < 5)                                    ||
  489.                                 (gpi->gpi_Mouse.Y > mdt->mdt_Domain->Height-5))
  490.                         {
  491.                             if(ISBITSET(g->Flags, GFLG_SELECTED))
  492.                             {
  493.                                 D(bug("CLEARBIT\n"));
  494.                                 CLEARBIT(g->Flags, GFLG_SELECTED);
  495.                                 RenderPlayButton(obj, gpi->gpi_GInfo, mdt);
  496.                             }
  497.                         }
  498.                         else if(ISBITCLEARED(g->Flags, GFLG_SELECTED))
  499.                             {
  500.                                 D(bug("SETBIT\n"));
  501.                                 SETBIT(g->Flags, GFLG_SELECTED);
  502.                                 RenderPlayButton(obj, gpi->gpi_GInfo, mdt);
  503.                             }
  504.                         break;
  505.                 }
  506.         }
  507.         break;
  508.  
  509.     case DTM_WRITE:
  510.         D(bug("Method: OM_WRITE\n"));
  511.         switch(WRMSG(msg)->dtw_Mode)
  512.         {
  513.         case DTWM_RAW:
  514.             D(bug("dtWrite Rawmode : filehandle %lx\n",WRMSG(msg)->dtw_FileHandle));
  515.             D(bug("attrs at : %lx\n",WRMSG(msg)->dtw_AttrList));
  516.             D({
  517.                     struct TagItem *tstate = WRMSG(msg)->dtw_AttrList;
  518.                     struct TagItem *tag;
  519.  
  520.                     while((tag = NextTagItem(&tstate)))
  521.                         bug("{%08lx,%ld}\n",tag->ti_Tag,tag->ti_Data);
  522.               });
  523.             if (WRMSG(msg)->dtw_FileHandle)
  524.                 Write(WRMSG(msg)->dtw_FileHandle,mdt->mdt_Buffer,mdt->mdt_BufferLen);
  525.             retval = 1;
  526.             break;
  527.         default:
  528.             retval = DoSuperMethodA(cl,obj,msg);
  529.         }
  530.         break;
  531.  
  532.     case DTM_TRIGGER:
  533.         D(bug("Method: OM_TRIGGER  trigger %ld\n",TRMSG(msg)->dtt_Function));
  534.         retval=TriggerPlayMidi(mdt, TRMSG(msg)->dtt_Function, TRMSG(msg)->dtt_Data);
  535.         break;
  536.  
  537.     default:
  538.         D(bug("Method: ID=0x%lx ret %lx\n", msg->MethodID,retval));
  539.         retval = DoSuperMethodA(cl,obj,msg);
  540.     }
  541.     return(retval);
  542. }
  543. /*FE*/
  544.  
  545.  
  546.  
  547.  
  548.  
  549. /*FS*/ ULONG notifyAttrChanges(Object *obj, void *ginfo, ULONG flags, ULONG tag1,...)
  550. {
  551.      return(DoMethod(obj, OM_NOTIFY, &tag1, ginfo, flags));
  552. }
  553. /*FE*/
  554.  
  555. /*FS*/ ULONG setSuperAttrs(Class *cl,Object *obj, void *ginfo,ULONG tag1,...)
  556. {
  557.      return(DoSuperMethod(cl,obj, OM_SET, &tag1, ginfo));
  558. }
  559. /*FE*/
  560.  
  561. /*FS*/ ULONG getattr(Class *cl,Object *obj,struct opGet *msg)
  562. {
  563.     struct MidiDTData *mdt = INST_DATA(cl,obj);
  564.     ULONG *storage = msg->opg_Storage;
  565.  
  566.     switch(msg->opg_AttrID)
  567.     {
  568.     case DTA_Methods:
  569.         *storage = (ULONG) methods;
  570.         break;
  571.     case DTA_TriggerMethods:
  572.         *storage = (ULONG) triggers;
  573.         break;
  574.     case DTA_NominalVert:
  575.         *storage = 50L;
  576.         break;
  577.     case DTA_NominalHoriz:
  578.         *storage = 50L;
  579.         break;
  580.     case DTA_Title:
  581.     case DTA_ObjName:
  582.     case DTA_Name:
  583.         *storage = (ULONG) mdt->mdt_Name;
  584.         break;
  585.     case SDTA_Cycles:
  586.         *storage = (ULONG) mdt->mdt_Cycles;
  587.         break;
  588.     case SDTA_Volume:
  589.         *storage = (ULONG) mdt->mdt_Volume;
  590.         break;
  591.     case SDTA_SignalTask:
  592.         *storage = (ULONG) mdt->mdt_SignalTask;
  593.         break;
  594.     case SDTA_SignalBit:
  595.         *storage = mdt->mdt_SignalBit;
  596.         break;
  597.     case MDTA_Buffer:
  598.         *storage = (ULONG) mdt->mdt_Buffer;
  599.         break;
  600.     case MDTA_BufferLen:
  601.         *storage = mdt->mdt_BufferLen;
  602.         break;
  603.     case MDTA_Cluster:
  604.         *storage = (ULONG) mdt->mdt_Cluster;
  605.         break;
  606.     default:
  607.         return(0);
  608.     }
  609.     return(1);
  610. }
  611. /*FE*/
  612.  
  613. /*FS*/ ULONG setattrs(Class *cl,Object *obj,struct opSet *msg)
  614. {
  615.     //struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
  616.     struct MidiDTData *mdt = INST_DATA(cl,obj);
  617.  
  618.     struct TagItem *tstate = msg->ops_AttrList;
  619.     struct TagItem *tag;
  620.  
  621.     ULONG retval = 0;
  622.     ULONG tidata;
  623.  
  624.     while((tag = NextTagItem(&tstate)))
  625.     {
  626.         tidata = tag->ti_Data;
  627.  
  628.         D(bug("setattr tag : {0x%08lx, 0x%08lx}\n",tag->ti_Tag,tidata));
  629.         retval++;
  630.         switch(tag->ti_Tag)
  631.         {
  632.         case DTA_Name:
  633.             strncpy(mdt->mdt_Name, (char *)tidata, 31);
  634.             break;
  635.         case DTA_Immediate:
  636.             mdt->mdt_Immediate=tidata;
  637.             break;
  638.         case DTA_Repeat:
  639.             mdt->mdt_Repeat=tidata;
  640.             break;
  641.         case SDTA_Cycles:
  642.             mdt->mdt_Cycles=tidata;
  643.             break;
  644.         case SDTA_Volume:
  645.             if (tidata > 64)
  646.                 mdt->mdt_Volume=64;
  647.             else
  648.                 mdt->mdt_Volume=tidata;
  649.             break;
  650.         case SDTA_SignalTask:
  651.             mdt->mdt_SignalTask=(struct Task *)tidata;
  652.             break;
  653.         case SDTA_SignalBit:
  654.             mdt->mdt_SignalBit=tidata;
  655.             break;
  656.         case MDTA_Buffer:
  657.             {
  658.                 ULONG len = GetTagData(MDTA_BufferLen,0,msg->ops_AttrList);
  659.  
  660.                 if(tidata && len)
  661.                 {
  662.                     if((mdt->mdt_Buffer) && (mdt->mdt_Flags & MDTF_ALLOCATED))
  663.                         FreeMem(mdt->mdt_Buffer,mdt->mdt_BufferLen);
  664.  
  665.                     mdt->mdt_Buffer     = (UBYTE *) tidata;
  666.                     mdt->mdt_BufferLen = len;
  667.                     mdt->mdt_BufferEnd = &mdt->mdt_Buffer[len];
  668.                     CLEARBIT(mdt->mdt_Flags, MDTF_ALLOCATED);
  669.                     SETBIT(mdt->mdt_Flags, MDTF_NEEDLAYOUT);
  670.  
  671.                     retval++;
  672.                 } else
  673.                     retval--;
  674.             }
  675.             break;
  676.         case MDTA_Cluster:
  677.             strncpy(mdt->mdt_Cluster, (char *)tidata, 30);
  678.             break;
  679.         default:
  680.             retval--;
  681.         }
  682.     }
  683.     return(retval);
  684. }
  685. /*FE*/
  686.  
  687.  
  688. /*FS*/ BOOL readPrefs(struct MidiDTData *mdt,STRPTR file)
  689. {
  690.     struct RDArgs *rdargs;
  691.     struct RDArgs *args;
  692.     BPTR fh;
  693.  
  694.     if((fh = Open(file,MODE_OLDFILE)))
  695.     {
  696.         UBYTE buf[256];
  697.         ULONG para[ARG_MAX];
  698.         LONG i;
  699.  
  700.         D(bug("Prefs file %s opened\n",file));
  701.         while(FGets(fh,buf,sizeof(buf)))
  702.         {
  703.             D(bug("Prefs line : %s",buf));
  704.             i=strlen(buf);
  705.             if( i>1 && (buf[i-1]=='\n' && (rdargs=(struct RDArgs *)AllocDosObject(DOS_RDARGS,NULL))) )
  706.             {
  707.                 rdargs->RDA_Source.CS_Buffer = buf;
  708.                 rdargs->RDA_Source.CS_Length = strlen(buf);
  709.  
  710.                 for(i=0 ; i<ARG_MAX ; i++)
  711.                     para[i]=0;
  712.  
  713.                 if((args = ReadArgs(prefstemplate,(LONG *) para,rdargs)))
  714.                 {
  715.                     D(bug("Prefs: Cluster %ld, Volume %ld\n",para[ARG_CLUSTER],para[ARG_VOLUME]));
  716.                     if(para[ARG_CLUSTER])
  717.                         strncpy(mdt->mdt_Cluster, (char*) para[ARG_CLUSTER], 30);
  718.  
  719.                     if(para[ARG_VOLUME])
  720.                     {
  721.                         mdt->mdt_Volume = (UWORD) *((LONG *) para[ARG_VOLUME]);
  722.  
  723.                         if(mdt->mdt_Volume > 64)
  724.                             mdt->mdt_Volume = 64;
  725.                     }
  726.                 }
  727.                 FreeDosObject(DOS_RDARGS , rdargs);
  728.             }
  729.         }
  730.         Close(fh);
  731.     }
  732.  
  733.     return((BOOL) (fh == NULL));
  734. }
  735. /*FE*/
  736.  
  737.  
  738. /*FS*/ void drawFrame(struct RastPort *rp, UWORD pen1, UWORD pen2, UWORD pen3,
  739.                              WORD x, WORD y, WORD w, WORD h)
  740. {
  741.     SetAPen(rp, pen1);
  742.     Move(rp, x,        y+h-1);
  743.     Draw(rp, x,        y);
  744.     Draw(rp, x+w-1,y);
  745.  
  746.     SetAPen(rp, pen2);
  747.     Move(rp, x+w,    y+1);
  748.     Draw(rp, x+w,    y+h);
  749.     Draw(rp, x+1,    y+h);
  750.  
  751.     SetAPen(rp, pen3);
  752.     Move(rp, x+5,    y+5);
  753.     Draw(rp, x+w-5,y+h/2);
  754.     Draw(rp, x+5,    y+h-5);
  755.     Draw(rp, x+5,    y+5);
  756. }
  757. /*FE*/
  758.  
  759. /*FS*/ ULONG RenderPlayButton(Object *obj, struct GadgetInfo *gi, struct MidiDTData *mdt)
  760. {
  761.     struct Gadget        *g=GOBJ(obj);
  762.     struct RastPort    *rp;
  763.     ULONG                    retval=FALSE;
  764.     UWORD                    *pens=gi->gi_DrInfo->dri_Pens;
  765.  
  766.  
  767.     if(rp=ObtainGIRPort(gi)) 
  768.     {
  769.         BYTE    selected=ISBITSET(g->Flags, GFLG_SELECTED);
  770.         WORD    x=mdt->mdt_Domain->Left        +6,
  771.                 y=mdt->mdt_Domain->Top        +6,
  772.                 w=mdt->mdt_Domain->Width  -12,
  773.                 h=mdt->mdt_Domain->Height -12;
  774.  
  775.         if ( w>15 && h>15)
  776.         {
  777.             if(ISBITSET(g->Flags, GFLG_RELRIGHT))
  778.                 x+=w-1;
  779.             if(selected)
  780.                 drawFrame(rp, pens[SHADOWPEN], pens[SHINEPEN], pens[HIGHLIGHTTEXTPEN], x,y,w,h);
  781.             else
  782.                 drawFrame(rp, pens[SHINEPEN], pens[SHADOWPEN], pens[HIGHLIGHTTEXTPEN], x,y,w,h);
  783.         }
  784.         ReleaseGIRPort(rp);
  785.         retval=TRUE;
  786.     }
  787.     return retval;
  788. }
  789. /*FE*/
  790.  
  791.  
  792. /*FS*/ ULONG TriggerPlayMidi(struct MidiDTData *mdt, ULONG Function, APTR Data)
  793. {
  794.     struct MsgPort *mport;
  795.  
  796.     mdt->mdt_Playing=Function;
  797.     D(bug("Playfunction: %ld\n",Function));
  798.     if( !mdt->mdt_PlayProc && Function!=STM_STOP )
  799.     {
  800.         if(mport = CreateMsgPort())
  801.         {
  802.             struct PlayMsg    msg={ { {NULL, NULL, NT_MESSAGE, 0, NULL},
  803.                                 NULL, (UWORD)sizeof(struct PlayMsg) }, NULL };
  804.  
  805.             msg.msg.mn_Node.ln_Type = NT_MESSAGE;
  806.             msg.msg.mn_ReplyPort    = mport;
  807.             msg.mdt                        = mdt;
  808.             if(mdt->mdt_PlayProc=CreateNewProcTags(NP_Entry, &PlayMidi,
  809.                                                 NP_Name, (ULONG)"MidiDT Player",
  810.                                                 NP_Priority, -1L,
  811.                                                 TAG_DONE))
  812.             {
  813.                 PutMsg(&mdt->mdt_PlayProc->pr_MsgPort, &msg);
  814.                 WaitPort(mport);
  815.                 GetMsg(mport);
  816.                 D(bug("Player launched, Cluster %s, Volume %ld\n",mdt->mdt_Cluster,(LONG)mdt->mdt_Volume));
  817.             }
  818.             DeleteMsgPort(mport);
  819.         }
  820.         D(else bug("CreateMsgPort failed\n"));
  821.     }
  822.     return(TRUE);
  823. }
  824. /*FE*/
  825.