Ejemplo n.º 1
0
bool ffemu_push_audio(ffemu_t *handle, const struct ffemu_audio_data *data)
{
   for (;;)
   {
      slock_lock(handle->lock);
      unsigned avail = fifo_write_avail(handle->audio_fifo);
      slock_unlock(handle->lock);

      if (!handle->alive)
         return false;

      if (avail >= data->frames * handle->params.channels * sizeof(int16_t))
         break;

      slock_lock(handle->cond_lock);
      if (handle->can_sleep)
      {
         handle->can_sleep = false;
         scond_wait(handle->cond, handle->cond_lock);
         handle->can_sleep = true;
      }
      else
         scond_signal(handle->cond);

      slock_unlock(handle->cond_lock);
   }

   slock_lock(handle->lock);
   fifo_write(handle->audio_fifo, data->data, data->frames * handle->params.channels * sizeof(int16_t));
   slock_unlock(handle->lock);
   scond_signal(handle->cond);

   return true;
}
Ejemplo n.º 2
0
static int process_cb(jack_nframes_t nframes, void *data)
{
   int i;
   jack_nframes_t f, avail[2], min_avail;
   jack_t *jd = (jack_t*)data;

   if (nframes <= 0)
   {
      scond_signal(jd->cond);
      return 0;
   }

   avail[0] = jack_ringbuffer_read_space(jd->buffer[0]);
   avail[1] = jack_ringbuffer_read_space(jd->buffer[1]);
   min_avail = ((avail[0] < avail[1]) ? avail[0] : avail[1]) / sizeof(jack_default_audio_sample_t);

   if (min_avail > nframes)
      min_avail = nframes;

   for (i = 0; i < 2; i++)
   {
      jack_default_audio_sample_t *out = (jack_default_audio_sample_t*)jack_port_get_buffer(jd->ports[i], nframes);
      assert(out);
      jack_ringbuffer_read(jd->buffer[i], (char*)out, min_avail * sizeof(jack_default_audio_sample_t));

      for (f = min_avail; f < nframes; f++)
         out[f] = 0.0f;
   }
   scond_signal(jd->cond);
   return 0;
}
Ejemplo n.º 3
0
static void audio_thread_loop(void *data)
{
   audio_thread_t *thr = (audio_thread_t*)data;

   if (!thr)
      return;

   RARCH_LOG("[Audio Thread]: Initializing audio driver.\n");
   thr->driver_data   = thr->driver->init(thr->device, thr->out_rate, thr->latency);
   slock_lock(thr->lock);
   thr->inited        = thr->driver_data ? 1 : -1;
   if (thr->inited > 0 && thr->driver->use_float)
      thr->use_float  = thr->driver->use_float(thr->driver_data);
   scond_signal(thr->cond);
   slock_unlock(thr->lock);

   if (thr->inited < 0)
      return;

   /* Wait until we start to avoid calling 
    * stop immediately after initialization. */
   slock_lock(thr->lock);
   while (thr->stopped)
      scond_wait(thr->cond, thr->lock);
   slock_unlock(thr->lock);

   RARCH_LOG("[Audio Thread]: Starting audio.\n");

   for (;;)
   {
      global_t *global = global_get_ptr();
      
      slock_lock(thr->lock);

      if (!thr->alive)
      {
         scond_signal(thr->cond);
         slock_unlock(thr->lock);
         break;
      }

      if (thr->stopped)
      {
         thr->driver->stop(thr->driver_data);
         while (thr->stopped)
            scond_wait(thr->cond, thr->lock);
         thr->driver->start(thr->driver_data);
      }

      slock_unlock(thr->lock);
      global->system.audio_callback.callback();
   }

   RARCH_LOG("[Audio Thread]: Tearing down driver.\n");
   thr->driver->free(thr->driver_data);
}
Ejemplo n.º 4
0
static void alsa_worker_thread(void *data)
{
   alsa_thread_t *alsa = (alsa_thread_t*)data;
   uint8_t        *buf = (uint8_t *)calloc(1, alsa->period_size);

   if (!buf)
   {
      RARCH_ERR("failed to allocate audio buffer");
      goto end;
   }

   while (!alsa->thread_dead)
   {
      size_t avail;
      size_t fifo_size;
      snd_pcm_sframes_t frames;
      slock_lock(alsa->fifo_lock);
      avail = fifo_read_avail(alsa->buffer);
      fifo_size = MIN(alsa->period_size, avail);
      fifo_read(alsa->buffer, buf, fifo_size);
      scond_signal(alsa->cond);
      slock_unlock(alsa->fifo_lock);

      /* If underrun, fill rest with silence. */
      memset(buf + fifo_size, 0, alsa->period_size - fifo_size);

      frames = snd_pcm_writei(alsa->pcm, buf, alsa->period_frames);

      if (frames == -EPIPE || frames == -EINTR || 
            frames == -ESTRPIPE)
      {
         if (snd_pcm_recover(alsa->pcm, frames, 1) < 0)
         {
            RARCH_ERR("[ALSA]: (#2) Failed to recover from error (%s)\n",
                  snd_strerror(frames));
            break;
         }

         continue;
      }
      else if (frames < 0)
      {
         RARCH_ERR("[ALSA]: Unknown error occurred (%s).\n",
               snd_strerror(frames));
         break;
      }
   }

end:
   slock_lock(alsa->cond_lock);
   alsa->thread_dead = true;
   scond_signal(alsa->cond);
   slock_unlock(alsa->cond_lock);
   free(buf);
}
Ejemplo n.º 5
0
bool ffemu_push_video(ffemu_t *handle, const struct ffemu_video_data *data)
{
   unsigned y;
   bool drop_frame = handle->video.frame_drop_count++ % handle->video.frame_drop_ratio;
   handle->video.frame_drop_count %= handle->video.frame_drop_ratio;
   if (drop_frame)
      return true;

   for (;;)
   {
      slock_lock(handle->lock);
      unsigned avail = fifo_write_avail(handle->attr_fifo);
      slock_unlock(handle->lock);

      if (!handle->alive)
         return false;

      if (avail >= sizeof(*data))
         break;

      slock_lock(handle->cond_lock);
      if (handle->can_sleep)
      {
         handle->can_sleep = false;
         scond_wait(handle->cond, handle->cond_lock);
         handle->can_sleep = true;
      }
      else
         scond_signal(handle->cond);

      slock_unlock(handle->cond_lock);
   }

   slock_lock(handle->lock);

   // Tightly pack our frame to conserve memory. libretro tends to use a very large pitch.
   struct ffemu_video_data attr_data = *data;

   if (attr_data.is_dupe)
      attr_data.width = attr_data.height = attr_data.pitch = 0;
   else
      attr_data.pitch = attr_data.width * handle->video.pix_size;

   fifo_write(handle->attr_fifo, &attr_data, sizeof(attr_data));

   int offset = 0;
   for (y = 0; y < attr_data.height; y++, offset += data->pitch)
      fifo_write(handle->video_fifo, (const uint8_t*)data->data + offset, attr_data.pitch);

   slock_unlock(handle->lock);
   scond_signal(handle->cond);

   return true;
}
Ejemplo n.º 6
0
static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data)
{
   struct dispmanx_page *page = data;

   if (!page)
      return;

   /* We signal the vsync condition, just in case 
    * we're waiting for it somewhere (no free pages, etc). */
   slock_lock(page->dispvars->vsync_cond_mutex);
   scond_signal(page->dispvars->vsync_condition);
   slock_unlock(page->dispvars->vsync_cond_mutex);

   slock_lock(page->dispvars->pending_mutex);
   page->dispvars->pageflip_pending--;	
   slock_unlock(page->dispvars->pending_mutex);

   if (page->dispvars->currentPage)
   {
      slock_lock(page->dispvars->currentPage->page_used_mutex);

      /* We mark as free the page that was visible until now */
      page->dispvars->currentPage->used = false;

      slock_unlock(page->dispvars->currentPage->page_used_mutex);
   }

   /* The page on which we just issued the flip that 
    * caused this callback becomes the visible one */
   page->dispvars->currentPage = page;
}
Ejemplo n.º 7
0
static void filter_thread_loop(void *data)
{
   struct filter_thread_data *thr = (struct filter_thread_data*)data;

   for (;;)
   {
      bool die;
      slock_lock(thr->lock);
      while (thr->done && !thr->die)
         scond_wait(thr->cond, thr->lock);
      die = thr->die;
      slock_unlock(thr->lock);

      if (die)
         break;

      if (thr->packet && thr->packet->work)
         thr->packet->work(thr->userdata, thr->packet->thread_data);

      slock_lock(thr->lock);
      thr->done = true;
      scond_signal(thr->cond);
      slock_unlock(thr->lock);
   }
}
Ejemplo n.º 8
0
void rarch_softfilter_free(rarch_softfilter_t *filt)
{
   unsigned i;
   i = 0;
   (void)i;
   if (!filt)
      return;

   free(filt->packets);
   if (filt->impl && filt->impl_data)
      filt->impl->destroy(filt->impl_data);
#if !defined(HAVE_FILTERS_BUILTIN) && defined(HAVE_DYLIB)
   if (filt->lib)
      dylib_close(filt->lib);
#endif
#ifdef HAVE_THREADS
   for (i = 0; i < filt->threads; i++)
   {
      if (!filt->thread_data[i].thread)
         continue;
      slock_lock(filt->thread_data[i].lock);
      filt->thread_data[i].die = true;
      scond_signal(filt->thread_data[i].cond);
      slock_unlock(filt->thread_data[i].lock);
      sthread_join(filt->thread_data[i].thread);
      slock_free(filt->thread_data[i].lock);
      scond_free(filt->thread_data[i].cond);
   }
   free(filt->thread_data);
#endif
   free(filt);
}
Ejemplo n.º 9
0
static void retro_task_threaded_push_running(retro_task_t *task)
{
   slock_lock(running_lock);
   task_queue_put(&tasks_running, task);
   scond_signal(worker_cond);
   slock_unlock(running_lock);
}
Ejemplo n.º 10
0
static void dispmanx_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data)
{
   struct dispmanx_page *page = data;

   /* Marking the page as free must be done before the signaling
    * so when update_main continues (it won't continue until we signal) 
    * we can chose this page as free */
   if (page->dispvars->current_page) {
      slock_lock(page->dispvars->current_page->page_used_mutex);

      /* We mark as free the page that was visible until now */
      page->dispvars->current_page->used = false;

      slock_unlock(page->dispvars->current_page->page_used_mutex);
   }

  /* The page on which we issued the flip that
   * caused this callback becomes the visible one */
   page->dispvars->current_page = page;

   /* These two things must be isolated "atomically" to avoid getting 
    * a false positive in the pending_mutex test in update_main. */ 
   slock_lock(page->dispvars->pending_mutex);
   
   page->dispvars->pageflip_pending--;	
   scond_signal(page->dispvars->vsync_condition);
  
   slock_unlock(page->dispvars->pending_mutex);
}
Ejemplo n.º 11
0
static void thread_send_cmd(thread_video_t *thr, enum thread_cmd cmd)
{
   slock_lock(thr->lock);
   thr->send_cmd = cmd;
   thr->reply_cmd = CMD_NONE;
   scond_signal(thr->cond_thread);
   slock_unlock(thr->lock);
}
Ejemplo n.º 12
0
static bool ffmpeg_push_audio(void *data,
      const struct ffemu_audio_data *audio_data)
{
   ffmpeg_t *handle = (ffmpeg_t*)data;

   if (!handle || !audio_data)
      return false;

   if (!handle->config.audio_enable)
      return true;

   for (;;)
   {
      unsigned avail;
      slock_lock(handle->lock);
      avail = fifo_write_avail(handle->audio_fifo);
      slock_unlock(handle->lock);

      if (!handle->alive)
         return false;

      if (avail >= audio_data->frames * handle->params.channels
            * sizeof(int16_t))
         break;

      slock_lock(handle->cond_lock);
      if (handle->can_sleep)
      {
         handle->can_sleep = false;
         scond_wait(handle->cond, handle->cond_lock);
         handle->can_sleep = true;
      }
      else
         scond_signal(handle->cond);

      slock_unlock(handle->cond_lock);
   }

   slock_lock(handle->lock);
   fifo_write(handle->audio_fifo, audio_data->data,
         audio_data->frames * handle->params.channels * sizeof(int16_t));
   slock_unlock(handle->lock);
   scond_signal(handle->cond);

   return true;
}
void CDIF_Queue::Write(const CDIF_Message &message)
{
   slock_lock((slock_t*)ze_mutex);

   ze_queue.push(message);

   scond_signal((scond_t*)ze_cond); // Signal while the mutex is held to prevent icky race conditions

   slock_unlock((slock_t*)ze_mutex);
}
Ejemplo n.º 14
0
static void shutdown_cb(void *data)
{
   jack_t *jd = (jack_t*)data;

   if (!jd)
      return;

   jd->shutdown = true;
   scond_signal(jd->cond);
}
Ejemplo n.º 15
0
static void audio_thread_unblock(audio_thread_t *thr)
{
   if (!thr)
      return;

   slock_lock(thr->lock);
   thr->stopped = false;
   scond_signal(thr->cond);
   slock_unlock(thr->lock);
}
Ejemplo n.º 16
0
static OSStatus audio_write_cb(void *userdata,
      AudioUnitRenderActionFlags *action_flags,
      const AudioTimeStamp *time_stamp, UInt32 bus_number,
      UInt32 number_frames, AudioBufferList *io_data)
{
   void *outbuf;
   unsigned write_avail;
   coreaudio_t *dev = (coreaudio_t*)userdata;

   (void)time_stamp;
   (void)bus_number;
   (void)number_frames;

   if (!io_data)
      return noErr;
   if (io_data->mNumberBuffers != 1)
      return noErr;

   write_avail = io_data->mBuffers[0].mDataByteSize;
   outbuf = io_data->mBuffers[0].mData;

   slock_lock(dev->lock);

   if (fifo_read_avail(dev->buffer) < write_avail)
   {
      *action_flags = kAudioUnitRenderAction_OutputIsSilence;

      /* Seems to be needed. */
      memset(outbuf, 0, write_avail);

      slock_unlock(dev->lock);

      /* Technically possible to deadlock without. */
      scond_signal(dev->cond); 
      return noErr;
   }

   fifo_read(dev->buffer, outbuf, write_avail);
   slock_unlock(dev->lock);
   scond_signal(dev->cond);
   return noErr;
}
Ejemplo n.º 17
0
static void dispmanx_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data)
{
   vc_ctx_data_t *vc = (vc_ctx_data_t*)data;

   if (!vc)
      return;

   slock_lock(vc->vsync_condition_mutex);
   scond_signal(vc->vsync_condition);
   slock_unlock(vc->vsync_condition_mutex);
}
Ejemplo n.º 18
0
static ssize_t audio_cb(void *data, size_t bytes, void *userdata)
{
   rsd_t *rsd = (rsd_t*)userdata;

   size_t avail = fifo_read_avail(rsd->buffer);
   size_t write_size = bytes > avail ? avail : bytes;
   fifo_read(rsd->buffer, data, write_size);
   scond_signal(rsd->cond);

   return write_size;
}
Ejemplo n.º 19
0
static void shutdown_cb(void *data)
{
   jack_t *jd = (jack_t*)data;

   if (!jd)
      return;

   jd->shutdown = true;
#ifdef HAVE_THREADS
   scond_signal(jd->cond);
#endif
}
Ejemplo n.º 20
0
static void sdl_audio_cb(void *data, Uint8 *stream, int len)
{
   sdl_audio_t *sdl = (sdl_audio_t*)data;

   size_t avail = fifo_read_avail(sdl->buffer);
   size_t write_size = len > (int)avail ? avail : len;
   fifo_read(sdl->buffer, stream, write_size);
   scond_signal(sdl->cond);

   // If underrun, fill rest with silence.
   memset(stream + write_size, 0, len - write_size);
}
Ejemplo n.º 21
0
static void frontend_gx_deinit(void *data)
{
   (void)data;

#if defined(HW_RVL) && !defined(IS_SALAMANDER)
   slock_lock(gx_device_cond_mutex);
   gx_stop_dev_thread = true;
   slock_unlock(gx_device_cond_mutex);
   scond_signal(gx_device_cond);
   sthread_join(gx_device_thread);
#endif
}
Ejemplo n.º 22
0
/* thread -> user */
static void thread_reply(thread_video_t *thr, const thread_packet_t *pkt)
{
   slock_lock(thr->lock);

   thr->cmd_data = *pkt;

   thr->reply_cmd = pkt->type;
   thr->send_cmd  = CMD_NONE;

   scond_signal(thr->cond_cmd);
   slock_unlock(thr->lock);
}
Ejemplo n.º 23
0
void autosave_free(autosave_t *handle)
{
   slock_lock(handle->cond_lock);
   handle->quit = true;
   slock_unlock(handle->cond_lock);
   scond_signal(handle->cond);
   sthread_join(handle->thread);

   slock_free(handle->lock);
   slock_free(handle->cond_lock);
   scond_free(handle->cond);

   free(handle->buffer);
   free(handle);
}
Ejemplo n.º 24
0
void Task::Impl::execute(const TWork &work, void *param)
{
	slock_lock(this->mutex);

	if (work == NULL || !this->_isThreadRunning)
   {
		slock_unlock(this->mutex);
		return;
	}

	this->workFunc = work;
	this->workFuncParam = param;
	scond_signal(this->condWork);

	slock_unlock(this->mutex);
}
Ejemplo n.º 25
0
void ssem_signal(ssem_t *semaphore)
{
   if (!semaphore)
      return;

   slock_lock(semaphore->mutex);
   semaphore->value++;

   if (semaphore->value <= 0)
   {
      semaphore->wakeups++;
      scond_signal(semaphore->cond);
   }

   slock_unlock(semaphore->mutex);
}
Ejemplo n.º 26
0
static void data_runloop_thread_deinit(void)
{
   if (!g_data_runloop.thread_inited)
   {
      slock_lock(g_data_runloop.cond_lock);
      g_data_runloop.alive = false;
      scond_signal(g_data_runloop.cond);
      slock_unlock(g_data_runloop.cond_lock);
      sthread_join(g_data_runloop.thread);

      slock_free(g_data_runloop.lock);
      slock_free(g_data_runloop.cond_lock);
      rarch_main_data_overlay_thread_uninit();
      scond_free(g_data_runloop.cond);
   }
}
Ejemplo n.º 27
0
static void data_runloop_thread_deinit(data_runloop_t *runloop)
{
   if (!runloop->thread_inited)
   {
      slock_lock(runloop->cond_lock);
      runloop->alive = false;
      scond_signal(runloop->cond);
      slock_unlock(runloop->cond_lock);
      sthread_join(runloop->thread);

      slock_free(runloop->lock);
      slock_free(runloop->cond_lock);
      rarch_main_data_overlay_thread_uninit();
      scond_free(runloop->cond);
   }
}
Ejemplo n.º 28
0
static void retro_task_threaded_deinit(void)
{
   slock_lock(running_lock);
   worker_continue = false;
   scond_signal(worker_cond);
   slock_unlock(running_lock);

   sthread_join(worker_thread);

   scond_free(worker_cond);
   slock_free(running_lock);
   slock_free(finished_lock);

   worker_thread = NULL;
   worker_cond   = NULL;
   running_lock  = NULL;
   finished_lock = NULL;
}
Ejemplo n.º 29
0
void rarch_softfilter_process(rarch_softfilter_t *filt,
      void *output, size_t output_stride,
      const void *input, unsigned width, unsigned height,
      size_t input_stride)
{
   unsigned i;

   if (!filt)
      return;

   if (filt->impl && filt->impl->get_work_packets)
      filt->impl->get_work_packets(filt->impl_data, filt->packets,
            output, output_stride, input, width, height, input_stride);
   
#ifdef HAVE_THREADS
   /* Fire off workers */
   for (i = 0; i < filt->threads; i++)
   {
#if 0
      RARCH_LOG("Firing off filter thread %u ...\n", i);
#endif
      filt->thread_data[i].packet = &filt->packets[i];
      slock_lock(filt->thread_data[i].lock);
      filt->thread_data[i].done = false;
      scond_signal(filt->thread_data[i].cond);
      slock_unlock(filt->thread_data[i].lock);
   }

   /* Wait for workers */
   for (i = 0; i < filt->threads; i++)
   {
#if 0
      RARCH_LOG("Waiting for filter thread %u ...\n", i);
#endif
      slock_lock(filt->thread_data[i].lock);
      while (!filt->thread_data[i].done)
         scond_wait(filt->thread_data[i].cond, filt->thread_data[i].lock);
      slock_unlock(filt->thread_data[i].lock);
   }
#else
   for (i = 0; i < filt->threads; i++)
      filt->packets[i].work(filt->impl_data, filt->packets[i].thread_data);
#endif
}
Ejemplo n.º 30
0
static void deinit_thread(ffemu_t *handle)
{
   if (handle->thread)
   {
      slock_lock(handle->cond_lock);
      handle->alive = false;
      handle->can_sleep = false;
      slock_unlock(handle->cond_lock);

      scond_signal(handle->cond);
      sthread_join(handle->thread);

      slock_free(handle->lock);
      slock_free(handle->cond_lock);
      scond_free(handle->cond);

      handle->thread = NULL;
   }
}