home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 5 / CD_Magazyn_EXEC_nr_5.iso / Recent / mus / play / mhimdev.lha / mhimdev.library / src / mhimdev.c < prev    next >
C/C++ Source or Header  |  2001-06-03  |  11KB  |  416 lines

  1. /*****************************************************************************
  2.  
  3.     mhimdev.library - MHI driver for mpeg.device
  4.     Copyright (C) 2001  Michael Henke
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20. *****************************************************************************/
  21.  
  22.  
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <exec/memory.h>
  26. #include <exec/interrupts.h>
  27. #include <utility/tagitem.h>
  28. #include <libraries/mhi.h>
  29. #include <devices/melodympeg.h>
  30. #include "mhimdev.h"
  31.  
  32. static void myDoIO(struct IOMPEGReq *mdevreq, UWORD command);
  33. static void __asm softint_server(register __a1 struct mhimdevHandle *h);
  34.  
  35.  
  36.  
  37.  
  38. struct mhimdevHandle
  39. {
  40.     UBYTE               mdevunit, mdevname[256], mhistatus;
  41.     struct MsgPort      *mdevport;
  42.     struct IOMPEGReq    *mdevreq;
  43.     struct List         list_unused, list_getempty;
  44.     struct Task         *mhitask;
  45.     ULONG               mhisignal;
  46.     struct Interrupt    mdevsoftint;
  47.     LONG                requests_pending;
  48.     ULONG               mhivolume, mhipanning;
  49. };
  50.  
  51.  
  52.  
  53.  
  54.  
  55. APTR __asm
  56. i_MHIAllocDecoder(register __a0 struct Task *task, register __d0 ULONG mhisignal)
  57. {
  58.     struct mhimdevHandle *h;
  59. #ifdef DEBUG
  60. KPutStr("MHIAllocDecoder()\n");
  61. #endif
  62.     if(task==NULL) return(NULL);
  63.     h=(struct mhimdevHandle*)AllocVec(sizeof(struct mhimdevHandle),MEMF_PUBLIC|MEMF_CLEAR);
  64.     if(h==NULL) return(NULL);
  65.     h->mhitask=task;
  66.     h->mhisignal=mhisignal;
  67.     h->mhistatus=MHIF_STOPPED;
  68.     h->mhivolume=100;
  69.     h->mhipanning=50;
  70.     NewList(&h->list_unused);
  71.     NewList(&h->list_getempty);
  72.     {
  73.         struct DosLibrary *DOSBase;
  74.         UBYTE *varbuf;
  75.         LONG  varlen, args[2]={0,0};
  76.         struct RDArgs *rdargs, *rdargs2;
  77.         struct TagItem tagdone={TAG_DONE,0};
  78.         if((DOSBase=(struct DosLibrary*)OpenLibrary("dos.library",37)))
  79.         {
  80.             if((varbuf=AllocVec(1024,MEMF_PUBLIC|MEMF_CLEAR)))
  81.             {
  82.                 if((varlen=GetVar("MHIMDEV",varbuf,1024,LV_VAR))>0)
  83.                 {
  84. #ifdef DEBUG
  85. KPutStr("MHIMDEV varbuf=\"");
  86. KPutStr(varbuf);
  87. KPutStr("\"\n");
  88. #endif
  89.                     if((rdargs=AllocDosObject(DOS_RDARGS,&tagdone)))
  90.                     {
  91.                         rdargs->RDA_Source.CS_Buffer=varbuf;
  92.                         rdargs->RDA_Source.CS_Length=varlen;
  93.                         rdargs->RDA_Source.CS_CurChr=0;
  94.                         rdargs->RDA_Flags=RDAF_NOPROMPT;
  95.                         rdargs->RDA_DAList=0;
  96.                         rdargs2=ReadArgs("DEVICE,UNIT/N",args,rdargs);
  97.                         if(args[0]) CopyMem((APTR)args[0],h->mdevname,sizeof(h->mdevname)-1);
  98.                         if(args[1]) h->mdevunit=(*(LONG*)args[1]);
  99.                         FreeArgs(rdargs2);
  100.                         FreeDosObject(DOS_RDARGS,rdargs);
  101.                     }
  102.                 }
  103.                 FreeVec(varbuf);
  104.             }
  105.             CloseLibrary((struct Library*)DOSBase);
  106.         }
  107.     }
  108. #ifdef DEBUG
  109. KPutStr("MHIMDEV var:  DEVICE=");
  110. KPutStr(h->mdevname);
  111. KPutStr("  UNIT=");
  112. KPutChar((LONG)('0'+h->mdevunit));
  113. #endif
  114.     if((h->mdevport=CreateMsgPort()))
  115.     {
  116.         h->mdevsoftint.is_Data=(APTR)h;
  117.         h->mdevsoftint.is_Code=(void(*)(void))softint_server;
  118.         h->mdevport->mp_SoftInt= &h->mdevsoftint;
  119.         h->mdevport->mp_Flags=PA_SOFTINT;
  120.         if((h->mdevreq=(struct IOMPEGReq*)CreateIORequest(h->mdevport,sizeof(struct IOMPEGReq))))
  121.         {
  122.             if(OpenDevice(h->mdevname,(ULONG)h->mdevunit,(struct IORequest*)h->mdevreq,0)==0)
  123.             {
  124.                 myDoIO(h->mdevreq,CMD_RESET);
  125.                 myDoIO(h->mdevreq,MPEGCMD_PLAY);
  126.                 h->mdevreq->iomr_Arg1=1;
  127.                 myDoIO(h->mdevreq,MPEGCMD_PAUSE);
  128. #ifdef DEBUG
  129. KPutStr("  __open ok__\n");
  130. #endif
  131.                 return(h);
  132.             }
  133.             DeleteIORequest(h->mdevreq);
  134.         }
  135.         DeleteMsgPort(h->mdevport);
  136.     }
  137.     FreeVec(h);
  138. #ifdef DEBUG
  139. KPutStr("  **open failed**\n");
  140. #endif
  141.     return(NULL);
  142. }
  143.  
  144.  
  145.  
  146.  
  147.  
  148. void __asm
  149. i_MHIFreeDecoder(register __a3 APTR handle)
  150. {
  151.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  152.     struct IOMPEGReq *req;
  153. #ifdef DEBUG
  154. KPutStr("MHIFreeDecoder()\n");
  155. #endif
  156.     if(handle==NULL) return;
  157.     i_MHIStop(handle);
  158.     while((req=(struct IOMPEGReq*)RemHead(&h->list_unused)))
  159.         FreeMem(req,sizeof(struct IOMPEGReq));
  160.     CloseDevice((struct IORequest*)h->mdevreq);
  161.     DeleteIORequest(h->mdevreq);
  162.     DeleteMsgPort(h->mdevport);
  163.     FreeVec(h);
  164. }
  165.  
  166.  
  167.  
  168.  
  169.  
  170. BOOL __asm
  171. i_MHIQueueBuffer(register __a3 APTR handle, register __a0 APTR buffer, register __d0 ULONG size)
  172. {
  173.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  174.     struct IOMPEGReq *req;
  175. #ifdef DEBUG
  176. KPutStr("MHIQueueBuffer()\n");
  177. #endif
  178.     if((handle==NULL) || (buffer==NULL) || (size==0)) return(FALSE);
  179.     if(!(req=(struct IOMPEGReq*)RemHead(&h->list_unused)))
  180.     {
  181.         UWORD i;
  182.         for(i=0;i<32;i++)
  183.         {
  184.             req=(struct IOMPEGReq*)AllocMem(sizeof(struct IOMPEGReq),MEMF_PUBLIC);
  185.             if(req) AddTail(&h->list_unused,(struct Node*)req);
  186.         }
  187.         if(!(req=(struct IOMPEGReq*)RemHead(&h->list_unused)))
  188.             return(FALSE);
  189.     }
  190.     CopyMem(h->mdevreq,req,sizeof(struct IOMPEGReq));
  191.     req->iomr_Req.io_Command=CMD_WRITE;
  192.     req->iomr_Req.io_Data=buffer;
  193.     req->iomr_Req.io_Length=size;
  194.     req->iomr_Req.io_Flags=0;
  195.     req->iomr_StreamType=MPEGSTREAM_AUDIO;
  196.     req->iomr_MPEGFlags=0;
  197.     h->requests_pending++;
  198.     SendIO((struct IORequest*)req);
  199.     return(TRUE);
  200. }
  201.  
  202.  
  203.  
  204.  
  205.  
  206. APTR __asm
  207. i_MHIGetEmpty(register __a3 APTR handle)
  208. {
  209.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  210.     struct IOMPEGReq *req;
  211. #ifdef DEBUG
  212. KPutStr("MHIGetEmpty()\n");
  213. #endif
  214.     if(handle==NULL) return(NULL);
  215.     Disable();
  216.     req=(struct IOMPEGReq*)RemHead(&h->list_getempty);
  217.     Enable();
  218.     if(req==NULL) return(NULL);
  219.     AddTail(&h->list_unused,(struct Node*)req);
  220.     return(req->iomr_Req.io_Data);
  221. }
  222.  
  223.  
  224.  
  225.  
  226.  
  227. UBYTE __asm
  228. i_MHIGetStatus(register __a3 APTR handle)
  229. {
  230.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  231. #ifdef DEBUG
  232. KPutStr("MHIGetStatus()\n");
  233. #endif
  234.     if(handle==NULL) return(MHIF_STOPPED);
  235.     if((h->requests_pending<=0) && (h->mhistatus==MHIF_PLAYING))
  236.         return(MHIF_OUT_OF_DATA);
  237.     else
  238.         return(h->mhistatus);
  239. }
  240.  
  241.  
  242.  
  243.  
  244.  
  245. void __asm
  246. i_MHIPlay(register __a3 APTR handle)
  247. {
  248.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  249. #ifdef DEBUG
  250. KPutStr("MHIPlay()\n");
  251. #endif
  252.     if(handle==NULL) return;
  253.     myDoIO(h->mdevreq,MPEGCMD_PLAY);
  254.     h->mdevreq->iomr_Arg1=0;
  255.     myDoIO(h->mdevreq,MPEGCMD_PAUSE);
  256.     h->mhistatus=MHIF_PLAYING;
  257. }
  258.  
  259.  
  260.  
  261.  
  262.  
  263. void __asm
  264. i_MHIStop(register __a3 APTR handle)
  265. {
  266.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  267.     struct IOMPEGReq *req;
  268. #ifdef DEBUG
  269. KPutStr("MHIStop()\n");
  270. #endif
  271.     if(handle==NULL) return;
  272.     Disable();
  273.     h->mdevport->mp_Flags=PA_IGNORE;
  274.     Enable();
  275.     while((req=(struct IOMPEGReq*)RemHead(&h->list_getempty)))
  276.         AddTail(&h->list_unused,(struct Node*)req);
  277.     myDoIO(h->mdevreq,CMD_FLUSH);
  278.     while((req=(struct IOMPEGReq*)GetMsg(h->mdevport)))
  279.         if(req!=h->mdevreq) AddTail(&h->list_unused,(struct Node*)req);
  280.     h->requests_pending=0;
  281.     h->mdevreq->iomr_Arg1=1;
  282.     myDoIO(h->mdevreq,MPEGCMD_PAUSE);
  283.     h->mdevport->mp_Flags=PA_SOFTINT;
  284.     h->mhistatus=MHIF_STOPPED;
  285. }
  286.  
  287.  
  288.  
  289.  
  290.  
  291. void __asm
  292. i_MHIPause(register __a3 APTR handle)
  293. {
  294.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  295. #ifdef DEBUG
  296. KPutStr("MHIPause()\n");
  297. #endif
  298.     if(handle==NULL) return;
  299.     if(h->mhistatus==MHIF_PLAYING)
  300.     {
  301.         h->mdevreq->iomr_Arg1=1;
  302.         h->mhistatus=MHIF_PAUSED;
  303.     }
  304.     else if(h->mhistatus==MHIF_PAUSED)
  305.     {
  306.         h->mdevreq->iomr_Arg1=0;
  307.         h->mhistatus=MHIF_PLAYING;
  308.     }
  309.     else return;
  310.     myDoIO(h->mdevreq,MPEGCMD_PAUSE);
  311. }
  312.  
  313.  
  314.  
  315.  
  316.  
  317. ULONG __asm
  318. i_MHIQuery(register __d1 ULONG query)
  319. {
  320. #ifdef DEBUG
  321. KPutStr("MHIQuery()\n");
  322. #endif
  323.     switch(query)
  324.     {
  325.     case MHIQ_DECODER_NAME:
  326.         return((ULONG)"MHI driver for mpeg.device");
  327.     case MHIQ_DECODER_VERSION:
  328.         return((ULONG)IDSTRING);
  329.     case MHIQ_AUTHOR:
  330.         return((ULONG)"Michael Henke");
  331.     case MHIQ_IS_HARDWARE:
  332.         return(MHIF_TRUE);
  333.     case MHIQ_LAYER1:
  334.     case MHIQ_LAYER2:
  335.     case MHIQ_LAYER3:
  336.         /* mpeg.device is able to tell us but we can't access it from here */
  337.         /* we would need an initialised mhimdevHandle for this... */
  338.         return(MHIF_SUPPORTED);
  339.     case MHIQ_MPEG1:
  340.     case MHIQ_MPEG2:
  341.     case MHIQ_MPEG25:
  342.     case MHIQ_VARIABLE_BITRATE:
  343.     case MHIQ_JOINT_STERIO:
  344.         /* mpeg.device can't tell us these things but we are optimistic */
  345.         return(MHIF_SUPPORTED);
  346.     case MHIQ_VOLUME_CONTROL:
  347.     case MHIQ_PANNING_CONTROL:
  348.         /* these are standard features of mpeg.device */
  349.         return(MHIF_SUPPORTED);
  350.     default:
  351.         /* everything else is either MHIF_FALSE or MHIF_UNSUPPORTED ;-) */
  352.         return(MHIF_UNSUPPORTED);
  353.     }
  354. }
  355.  
  356.  
  357.  
  358.  
  359.  
  360. void __asm
  361. i_MHISetParam(register __a3 APTR handle, register __d0 UWORD param, register __d1 ULONG value)
  362. {
  363.     struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
  364.     struct MPEGAudioParams map;
  365.     ULONG vol;
  366. #ifdef DEBUG
  367. KPutStr("MHISetParam()\n");
  368. #endif
  369.     if(handle==NULL) return;
  370.     if(param==MHIP_VOLUME) h->mhivolume=(value>100 ? 100 : value);
  371.     else if(param==MHIP_PANNING) h->mhipanning=(value>100 ? 100 : value);
  372.     else return;
  373.     vol=0xffff*h->mhivolume;
  374.     map.map_VolumeLeft =(vol*(ULONG)(h->mhipanning>50 ? 100-h->mhipanning : 50))/5000;
  375.     map.map_VolumeRight=(vol*(ULONG)(h->mhipanning<50 ? h->mhipanning     : 50))/5000;
  376.     map.map_StreamID=0xffff;
  377.     h->mdevreq->iomr_Req.io_Data= ↦
  378.     h->mdevreq->iomr_Req.io_Length=sizeof(struct MPEGAudioParams);
  379.     myDoIO(h->mdevreq,MPEGCMD_SETAUDIOPARAMS);
  380. }
  381.  
  382.  
  383.  
  384.  
  385.  
  386. /*** private routines ***/
  387.  
  388. static void
  389. myDoIO(struct IOMPEGReq *mdevreq, UWORD command)
  390. {
  391.     mdevreq->iomr_Req.io_Command=command;
  392.     mdevreq->iomr_Req.io_Flags=0;
  393.     mdevreq->iomr_StreamType=MPEGSTREAM_AUDIO;
  394.     DoIO((struct IORequest*)mdevreq);
  395. }
  396.  
  397.  
  398. static void __asm
  399. softint_server(register __a1 struct mhimdevHandle *h)
  400. {
  401.     struct IOMPEGReq *req;
  402. #ifdef DEBUG
  403. KPutStr("--softint_server\n");
  404. #endif
  405.     while((req=(struct IOMPEGReq*)GetMsg(h->mdevport)))
  406.     {
  407.         if(req!=h->mdevreq)
  408.         {
  409.             AddTail(&h->list_getempty,(struct Node*)req);
  410.             h->requests_pending--;
  411.         }
  412.     }
  413.     Signal(h->mhitask,h->mhisignal);
  414. }
  415.  
  416.