Changeset 2778:f7b661680b55 in roaraudio


Ignore:
Timestamp:
09/24/09 02:11:34 (15 years ago)
Author:
phi
Branch:
default
Phase:
public
Message:

maybe working first win32 driver

Location:
roard
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • roard/driver_wmm.c

    r2775 r2778  
    2727#if defined(ROAR_HAVE_H_MMSYSTEM) && defined(ROAR_TARGET_WIN32) 
    2828 
     29static int _alloc_wave_headers(struct driver_wmm * self) { 
     30  int bytesPerBlock = self->wavefmt.nBlockAlign * self->splPerBlock; 
     31  /*   int bytes = internal->blocks * (sizeof(WAVEHDR) + bytesPerBlock); */ 
     32  int bytes = self->blocks * (sizeof(*self->wh) + bytesPerBlock); 
     33  int res; 
     34  MMRESULT mmres; 
     35 
     36  self->bigbuffer = malloc(bytes); 
     37  if (self->bigbuffer != NULL) { 
     38    int i; 
     39    BYTE * b; 
     40 
     41    memset(self->bigbuffer,0,bytes); 
     42    self->wh = self->bigbuffer; 
     43    self->spl = (LPBYTE) (self->wh+self->blocks); 
     44    for (i=0, b=self->spl; i<self->blocks; ++i, b+=bytesPerBlock) { 
     45      self->wh[i].data = b; 
     46      self->wh[i].wh.lpData = self->wh[i].data; 
     47      self->wh[i].length = bytesPerBlock; 
     48      self->wh[i].wh.dwBufferLength = self->wh[i].length; 
     49      self->wh[i].wh.dwUser = (DWORD_PTR)self; 
     50      mmres = waveOutPrepareHeader(self->hwo, 
     51                                   &self->wh[i].wh,sizeof(WAVEHDR)); 
     52      if (MMSYSERR_NOERROR != mmres) { 
     53        break; 
     54      } 
     55    } 
     56    if (i<self->blocks) { 
     57      while (--i >= 0) { 
     58        waveOutUnprepareHeader(self->hwo, 
     59                               &self->wh[i].wh,sizeof(WAVEHDR)); 
     60      } 
     61      free(self->bigbuffer); 
     62      self->wh        = 0; 
     63      self->spl       = 0; 
     64      self->bigbuffer = 0; 
     65    } else { 
     66      /* all ok ! */ 
     67    } 
     68  } 
     69 
     70  res = (self->bigbuffer != NULL); 
     71  return res; 
     72} 
     73 
     74static int _get_free_block(struct driver_wmm * self); 
     75static int _wait_wave_headers(struct driver_wmm * self, int wait_all) { 
     76  int res = 1; 
     77 
     78  while (self->sent_blocks > 0) { 
     79    int n; 
     80    _get_free_block(self); 
     81    n = self->sent_blocks; 
     82    if (n > 0) { 
     83      unsigned int ms = (self->msPerBlock>>1)+1; 
     84      if (wait_all) ms *= n; 
     85      Sleep(ms); 
     86    } 
     87  } 
     88 
     89  res &= !self->sent_blocks; 
     90  return res; 
     91} 
     92 
     93static int _get_free_block(struct driver_wmm * self) { 
     94  const int idx = self->widx; 
     95  int ridx = self->ridx; 
     96 
     97  while (self->wh[ridx].sent && !!(self->wh[ridx].wh.dwFlags & WHDR_DONE)) { 
     98    /* block successfully sent to hardware, release it */ 
     99    /*debug("_ao_get_free_block: release block %d\n",ridx);*/ 
     100    self->wh[ridx].sent = 0; 
     101    self->wh[ridx].wh.dwFlags &= ~WHDR_DONE; 
     102 
     103    --self->full_blocks; 
     104    if (self->full_blocks<0) { 
     105      self->full_blocks = 0; 
     106    } 
     107 
     108    --self->sent_blocks; 
     109    if (self->sent_blocks<0) { 
     110      self->sent_blocks = 0; 
     111    } 
     112    if (++ridx >= self->blocks) ridx = 0; 
     113  } 
     114  self->ridx = ridx; 
     115 
     116  return self->wh[idx].sent 
     117    ? -1 
     118    : idx; 
     119} 
     120 
     121static int _free_wave_headers(struct driver_wmm * self) { 
     122  MMRESULT mmres; 
     123  int res = 1; 
     124 
     125  if (self->wh) { 
     126    int i; 
     127 
     128    /* Reset so we dont need to wait ... Just a satefy net 
     129     * since _ao_wait_wave_headers() has been called once before. 
     130     */ 
     131    mmres = waveOutReset(self->hwo); 
     132    /* Wait again to be sure reseted waveheaders has been released. */ 
     133    _wait_wave_headers(self, 0); 
     134 
     135    for (i=self->blocks; --i>=0; ) { 
     136      mmres = waveOutUnprepareHeader(self->hwo, 
     137                                     &self->wh[i].wh,sizeof(WAVEHDR)); 
     138 
     139      res &= mmres == MMSYSERR_NOERROR; 
     140    } 
     141    self->wh  = 0; 
     142    self->spl = 0; 
     143  } 
     144 
     145  return res; 
     146} 
     147 
     148/* Send a block to audio hardware */ 
     149static int _send_block(struct driver_wmm * self, const int idx) { 
     150  MMRESULT mmres; 
     151 
     152  /* Satanity checks */ 
     153  if (self->wh[idx].sent) { 
     154    return 0; 
     155  } 
     156  if (!!(self->wh[idx].wh.dwFlags & WHDR_DONE)) { 
     157    return 0; 
     158  } 
     159 
     160  /* count <= 0, just pretend it's been sent */ 
     161  if (self->wh[idx].count <= 0) { 
     162    self->wh[idx].sent = 2; /* set with 2 so we can track these special cases */ 
     163    self->wh[idx].wh.dwFlags |= WHDR_DONE; 
     164    ++self->sent_blocks; 
     165    return 1; 
     166  } 
     167 
     168  self->wh[idx].wh.dwBufferLength = self->wh[idx].count; 
     169  self->wh[idx].count = 0; 
     170  mmres = waveOutWrite(self->hwo, 
     171                       &self->wh[idx].wh, sizeof(WAVEHDR)); 
     172  self->wh[idx].sent = (mmres == MMSYSERR_NOERROR); 
     173  /*&& !(internal->wh[idx].wh.dwFlags & WHDR_DONE);*/ 
     174  self->sent_blocks += self->wh[idx].sent; 
     175  return mmres == MMSYSERR_NOERROR; 
     176} 
     177 
    29178int     driver_wmm_open_vio(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) { 
    30179 struct driver_wmm * self; 
    31180 WAVEFORMATEX wavefmt; 
     181 MMRESULT mmres; 
    32182 
    33183 if ( (self = malloc(sizeof(struct driver_wmm))) == NULL ) 
     
    45195 memset(&wavefmt, 0, sizeof(wavefmt)); 
    46196 
    47  wavefmt.wFormatTag      = WAVE_FORMAT_PCM; 
    48  wavefmt.nChannels       = info->channels; 
    49  wavefmt.wBitsPerSample  = info->bits; 
    50  wavefmt.nSamplesPerSec  = info->rate; 
    51  wavefmt.nBlockAlign     = (wavefmt.wBitsPerSample>>3)*wavefmt.nChannels; 
    52  wavefmt.nAvgBytesPerSec = wavefmt.nSamplesPerSec*wavefmt.nBlockAlign; 
    53  wavefmt.cbSize          = 0; 
     197 self->wavefmt.wFormatTag      = WAVE_FORMAT_PCM; 
     198 self->wavefmt.nChannels       = info->channels; 
     199 self->wavefmt.wBitsPerSample  = info->bits; 
     200 self->wavefmt.nSamplesPerSec  = info->rate; 
     201 self->wavefmt.nBlockAlign     = (self->wavefmt.wBitsPerSample>>3)*self->wavefmt.nChannels; 
     202 self->wavefmt.nAvgBytesPerSec = self->wavefmt.nSamplesPerSec*self->wavefmt.nBlockAlign; 
     203 self->wavefmt.cbSize          = 0; 
    54204 
    55205 /* $$$ later this should be optionnal parms */ 
     206  self->id          = WAVE_MAPPER; 
    56207  self->blocks      = 64; 
    57208  self->splPerBlock = 512; 
     
    59210    (self->splPerBlock * 1000 + info->rate - 1) / info->rate; 
    60211 
     212  mmres = 
     213    waveOutOpen(&self->hwo, 
     214                self->id, 
     215                &self->wavefmt, 
     216                (DWORD_PTR)0/* waveOutProc */, 
     217                (DWORD_PTR)self, 
     218                CALLBACK_NULL/* |WAVE_FORMAT_DIRECT */|WAVE_ALLOWSYNC); 
     219 if ( mmres != MMSYSERR_NOERROR ) { 
     220  driver_wmm_close_vio(inst); 
     221  return -1; 
     222 } 
     223 
     224 // FIXME: do error checking 
     225 waveOutGetID(self->hwo, &(self->id)); 
     226 
     227 _alloc_wave_headers(self); 
     228 
     229 self->opened = 1; 
     230 
    61231 return 0; 
    62232} 
     
    71241  return -1; 
    72242 
     243 if ( self->opened ) { 
     244  _wait_wave_headers(self, 1); 
     245  _free_wave_headers(self); 
     246  waveOutClose(self->hwo); 
     247 } 
     248 
    73249 free(self); 
    74250 
     
    77253 
    78254ssize_t driver_wmm_write(struct roar_vio_calls * vio, void *buf, size_t count) { 
    79  return -1; 
     255 struct driver_wmm * self; 
     256 int ret = 1; 
     257 
     258 if ( vio == NULL ) 
     259  return -1; 
     260 
     261 if ( (self = vio->inst) == NULL ) 
     262  return -1; 
     263 
     264 if ( ! self->opened ) 
     265  return -1; 
     266 
     267  while(ret && count > 0) { 
     268    int n; 
     269    const int idx = _get_free_block(self); 
     270 
     271    if (idx == -1) { 
     272      /* debug("sleep %dms, rem %d bytes\n",internal->msPerBlock,num_bytes); */ 
     273      Sleep(self->msPerBlock); 
     274      continue; 
     275    } 
     276 
     277    /* Get free bytes in the block */ 
     278    n = self->wh[idx].wh.dwBufferLength 
     279      - self->wh[idx].count; 
     280 
     281    /*     debug("free in block %d : %d/%d\n", */ 
     282    /*    idx,n,internal->wh[idx].dwBufferLength); */ 
     283 
     284    /* Get amount to copy */ 
     285    if (n > (int)count) { 
     286      n = count; 
     287    } 
     288    /*     debug("copy = %d\n",n); */ 
     289 
     290 
     291 
     292    /* Do copy */ 
     293    CopyMemory((char*)self->wh[idx].wh.lpData 
     294               + self->wh[idx].count, 
     295               buf, n); 
     296 
     297    /* Updates pointers and counters */ 
     298    buf += n; 
     299    count -= n; 
     300    /*     debug("rem = %d\n",num_bytes); */ 
     301    self->wh[idx].count += n; 
     302 
     303    /* Is this block full ? */ 
     304    if (self->wh[idx].count 
     305        == self->wh[idx].wh.dwBufferLength) { 
     306      ++self->full_blocks; 
     307      /*       debug("blocks %d full, total:%d\n",internal->widx,internal->full_blocks); */ 
     308      if (++self->widx == self->blocks) { 
     309        self->widx = 0; 
     310      } 
     311      ret = _send_block(self, idx); 
     312    } 
     313  } 
     314 
     315  /*   debug("ao_wmm_play => %d rem => [%s]\n",num_bytes,ret?"success":"error"); */ 
     316  return ret > -1 ? count : -1; 
    80317} 
    81318 
  • roard/include/driver_wmm.h

    r2774 r2778  
    4040  int msPerBlock;       /* millisecond per block (approx.) */ 
    4141 
    42 //  void * bigbuffer;     /* Allocated buffer for waveheaders and sound data */ 
    43 //  myWH_t * wh;          /* Pointer to waveheaders in bigbuffer             */ 
    44 //  BYTE * spl;           /* Pointer to sound data in bigbuffer              */ 
     42  void * bigbuffer;     /* Allocated buffer for waveheaders and sound data */ 
     43  struct { 
     44   WAVEHDR wh;          /* waveheader                        */ 
     45   char *  data;        /* sample data ptr                   */ 
     46   int     idx;         /* index of this header              */ 
     47   int     count;       /* current byte count                */ 
     48   int     length;      /* size of data                      */ 
     49   int     sent;        /* set when header is sent to device */ 
     50  } * wh;          /* Pointer to waveheaders in bigbuffer             */ 
     51  BYTE * spl;           /* Pointer to sound data in bigbuffer              */ 
     52 
     53  int sent_blocks;      /* Number of waveheader sent (not ack).        */ 
     54  int full_blocks;      /* Number of waveheader full (ready to send).  */ 
     55  int widx;             /* Index to the block being currently filled.  */ 
     56  int ridx;             /* Index to the block being sent.              */ 
    4557}; 
    4658 
Note: See TracChangeset for help on using the changeset viewer.