コード例 #1
0
ファイル: runloop_data.c プロジェクト: aldatsa/RetroArch
static void rarch_main_data_thread_init(void)
{
   data_runloop_t *runloop  = rarch_main_data_get_ptr();

   if (!runloop)
      return;

   runloop->lock            = slock_new();
   runloop->cond_lock       = slock_new();
   runloop->cond            = scond_new();

#ifdef HAVE_OVERLAY
   rarch_main_data_overlay_thread_init();
#endif

   runloop->thread    = sthread_create(data_thread_loop, runloop);

   if (!runloop->thread)
      goto error;

   slock_lock(runloop->lock);
   runloop->thread_inited   = true;
   runloop->alive           = true;
   runloop->thread_code     = THREAD_CODE_ALIVE;
   slock_unlock(runloop->lock);

   return;

error:
   data_runloop_thread_deinit(runloop);
}
コード例 #2
0
ファイル: thread_wrapper.c プロジェクト: CatalystG/RetroArch
static bool thread_init(thread_video_t *thr, const video_info_t *info, const input_driver_t **input,
                        void **input_data)
{
    thr->lock = slock_new();
    thr->frame.lock = slock_new();
    thr->cond_cmd = scond_new();
    thr->cond_thread = scond_new();
    thr->input = input;
    thr->input_data = input_data;
    thr->info = *info;
    thr->alive = true;
    thr->focus = true;

    size_t max_size = info->input_scale * RARCH_SCALE_BASE;
    max_size *= max_size;
    max_size *= info->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
    thr->frame.buffer = (uint8_t*)malloc(max_size);
    if (!thr->frame.buffer)
        return false;

    memset(thr->frame.buffer, 0x80, max_size);

    thr->target_frame_time = (rarch_time_t)roundf(1000000LL / g_settings.video.refresh_rate);
    thr->last_time = rarch_get_time_usec();

    thr->thread = sthread_create(thread_loop, thr);
    if (!thr->thread)
        return false;
    thread_send_cmd(thr, CMD_INIT);
    thread_wait_reply(thr, CMD_INIT);

    return thr->cmd_data.b;
}
コード例 #3
0
ファイル: runloop_data.c プロジェクト: brianblakely/RetroArch
static void rarch_main_data_thread_init(void)
{
   g_data_runloop.lock            = slock_new();
   g_data_runloop.cond_lock       = slock_new();
   g_data_runloop.cond            = scond_new();

#ifdef HAVE_OVERLAY
   rarch_main_data_overlay_thread_init();
#endif

   g_data_runloop.thread    = sthread_create(data_thread_loop, &g_data_runloop);

   if (!g_data_runloop.thread)
      goto error;

   slock_lock(g_data_runloop.lock);
   g_data_runloop.thread_inited   = true;
   g_data_runloop.alive           = true;
   g_data_runloop.thread_code     = THREAD_CODE_ALIVE;
   slock_unlock(g_data_runloop.lock);

   return;

error:
   data_runloop_thread_deinit();
}
コード例 #4
0
ファイル: autosave.c プロジェクト: magicseb/RetroArch
autosave_t *autosave_new(const char *path, const void *data, size_t size, unsigned interval)
{
    autosave_t *handle = (autosave_t*)calloc(1, sizeof(*handle));
    if (!handle)
        return NULL;

    handle->bufsize = size;
    handle->interval = interval;
    handle->path = path;
    handle->buffer = malloc(size);
    handle->snes_buffer = data;

    if (!handle->buffer)
    {
        free(handle);
        return NULL;
    }
    memcpy(handle->buffer, handle->snes_buffer, handle->bufsize);

    handle->lock = slock_new();
    handle->cond_lock = slock_new();
    handle->cond = scond_new();

    handle->thread = sthread_create(autosave_thread, handle);

    return handle;
}
コード例 #5
0
ファイル: task_queue.c プロジェクト: Ezio-PS/RetroArch
static void retro_task_threaded_init(void)
{
   running_lock  = slock_new();
   finished_lock = slock_new();
   worker_cond   = scond_new();

   slock_lock(running_lock);
   worker_continue = true;
   slock_unlock(running_lock);

   worker_thread = sthread_create(threaded_worker, NULL);
}
コード例 #6
0
static void dispmanx_surface_setup(void *data, int width, int height, int pitch, float aspect,
   struct dispmanx_surface *surface)
{
   struct dispmanx_video *_dispvars = data;
   int i, dst_width, dst_height, dst_xpos, dst_ypos;

   /* Allocate memory for all the pages in each surface
    * and initialize variables inside each page's struct. */
   surface->pages = calloc(surface->numpages, sizeof(struct dispmanx_page));
   for (i = 0; i < surface->numpages; i++) {
      surface->pages[i].used = false;   
      surface->pages[i].dispvars = _dispvars;   
      surface->pages[i].page_used_mutex = slock_new(); 
   }

   /* Internal frame dimensions. Pitch is total pitch including info 
    * between scanlines */
   surface->width = width;
   surface->height = height;
   surface->pitch = pitch;
   surface->aspect = aspect;  
 
   /* The "visible" width obtained from the core pitch. We blit based on 
    * the "visible" width, for cores with things between scanlines. */
   int visible_width = pitch / surface->bpp;
 
   dst_width  = _dispvars->dispmanx_height * aspect;	
   dst_height = _dispvars->dispmanx_height;
   
   /* If we obtain a scaled image width that is bigger than the physical screen width,
   * then we keep the physical screen width as our maximun width. */
   if (dst_width > _dispvars->dispmanx_width) 
      dst_width = _dispvars->dispmanx_width;
   
   dst_xpos = (_dispvars->dispmanx_width - dst_width) / 2;
   dst_ypos = (_dispvars->dispmanx_height - dst_height) / 2;

   /* We configure the rects now. */
   vc_dispmanx_rect_set(&surface->dst_rect, dst_xpos, dst_ypos, dst_width, dst_height);
   vc_dispmanx_rect_set(&surface->bmp_rect, 0, 0, width, height);	
   vc_dispmanx_rect_set(&surface->src_rect, 0, 0, width << 16, height << 16);	

   for (i = 0; i < surface->numpages; i++) {
      surface->pages[i].resource = 
         vc_dispmanx_resource_create(surface->pixformat, 
	 visible_width, height, &(_dispvars->vc_image_ptr));
   }
   /* Add element. */
   _dispvars->update = vc_dispmanx_update_start(0);

   surface->element = vc_dispmanx_element_add(
      _dispvars->update,_dispvars->display, surface->layer, 
      &surface->dst_rect, surface->pages[0].resource, 
      &surface->src_rect, DISPMANX_PROTECTION_NONE,
      &surface->alpha, 0, (DISPMANX_TRANSFORM_T)0);

   vc_dispmanx_update_submit_sync(_dispvars->update);		

   surface->setup = true;
}
コード例 #7
0
ファイル: async_job.c プロジェクト: Kivutar/RetroArch
async_job_t *async_job_new(void)
{
   async_job_t *ajob = (async_job_t*)calloc(1, sizeof(*ajob));
   
   if (!ajob)
      return NULL;

   ajob->lock   = slock_new();

   if (!ajob->lock)
      goto error;

   ajob->sem = ssem_new(0);

   if (!ajob->sem)
      goto error;

   ajob->thread = sthread_create(async_job_processor, (void*)ajob);

   if (!ajob->thread)
      goto error;

   return ajob;

error:
   if (ajob->lock)
      slock_free(ajob->lock);
   ajob->lock = NULL;
   if (ajob->sem)
      ssem_free(ajob->sem);
   if (ajob)
      free((void*)ajob);
   return NULL;
}
コード例 #8
0
ファイル: rsemaphore.c プロジェクト: Kivutar/RetroArch
ssem_t *ssem_new(int value)
{
   ssem_t *semaphore = (ssem_t*)calloc(1, sizeof(*semaphore));

   if (!semaphore)
      goto error;
   
   semaphore->value   = value;
   semaphore->wakeups = 0;
   semaphore->mutex   = slock_new();

   if (!semaphore->mutex)
      goto error;

   semaphore->cond = scond_new();

   if (!semaphore->cond)
      goto error;

   return semaphore;

error:
   if (semaphore->mutex)
      slock_free(semaphore->mutex);
   semaphore->mutex = NULL;
   if (semaphore)
      free((void*)semaphore);
   return NULL;
}
コード例 #9
0
ファイル: drm_gfx.c プロジェクト: IlDucci/RetroArch
static void *drm_gfx_init(const video_info_t *video,
      const input_driver_t **input, void **input_data)
{
   struct drm_video *_drmvars = (struct drm_video*)
      calloc(1, sizeof(struct drm_video));
   if (!_drmvars)
      return NULL;

   /* Setup surface parameters */
   _drmvars->menu_active      = false;
   _drmvars->rgb32            = video->rgb32; 

   /* It's very important that we set aspect here because the 
    * call seq when a core is loaded is gfx_init()->set_aspect()->gfx_frame()
    * and we don't want the main surface to be setup in set_aspect() 
    * before we get to gfx_frame(). */
   _drmvars->current_aspect = video_driver_get_aspect_ratio();

   /* Initialize the rest of the mutexes and conditions. */
   _drmvars->vsync_condition  = scond_new();
   _drmvars->vsync_cond_mutex = slock_new();
   _drmvars->pending_mutex    = slock_new();
   _drmvars->core_width       = 0;
   _drmvars->core_height      = 0;

   _drmvars->main_surface     = NULL;
   _drmvars->menu_surface     = NULL;

   if (input && input_data)
      *input = NULL;

   /* DRM Init */
   if (!init_drm())
   {
      RARCH_ERR ("DRM: Failed to initialize DRM\n");
      return NULL;
   }
   else
      RARCH_LOG ("DRM: Init succesful.\n");

   _drmvars->kms_width  = drm.current_mode->hdisplay;  
   _drmvars->kms_height = drm.current_mode->vdisplay;  
 
   return _drmvars;
}
コード例 #10
0
ファイル: drm_gfx.c プロジェクト: IlDucci/RetroArch
static void drm_surface_setup(void *data,  int src_width, int src_height, 
      int pitch, int bpp, uint32_t pixformat,
      int alpha, float aspect, int numpages, int layer, 
      struct drm_surface **sp)
{
   struct drm_video *_drmvars = data;
   int i;
   struct drm_surface *surface = NULL;

   *sp = calloc (1, sizeof(struct drm_surface));

   surface = *sp;   

   /* Setup surface parameters */
   surface->numpages = numpages;
   /* We receive the total pitch, including things that are 
    * between scanlines and we calculate the visible pitch 
    * from the visible width. 
    *
    * These will be used to increase the offsets for blitting. */
   surface->total_pitch = pitch;
   surface->pitch       = src_width * bpp; 
   surface->bpp         = bpp;
   surface->pixformat   = pixformat;
   surface->src_width   = src_width;
   surface->src_height  = src_height;
   surface->aspect      = aspect;
   
   /* Allocate memory for all the pages in each surface
    * and initialize variables inside each page's struct. */
   surface->pages = (struct drm_page*)
      calloc(surface->numpages, sizeof(struct drm_page));

   for (i = 0; i < surface->numpages; i++)
   {
      surface->pages[i].used            = false;   
      surface->pages[i].surface         = surface;   
      surface->pages[i].drmvars         = _drmvars;   
      surface->pages[i].page_used_mutex = slock_new(); 
   }

   /* Create the framebuffer for each one of the pages of the surface. */
   for (i = 0; i < surface->numpages; i++)
   {
      surface->pages[i].buf.width  = src_width;
      surface->pages[i].buf.height = src_height;
      int ret                      = modeset_create_dumbfb(
            drm.fd, &surface->pages[i].buf, bpp, pixformat);	

      if (ret)
      {
         RARCH_ERR ("DRM: can't create fb\n");
      }
   }

   surface->flip_page = 0;
}
コード例 #11
0
static void *sunxi_gfx_init(const video_info_t *video,
      const input_driver_t **input, void **input_data)
{
   struct sunxi_video *_dispvars = (struct sunxi_video*)
      calloc(1, sizeof(struct sunxi_video));

   if (!_dispvars)
      return NULL;

   _dispvars->src_bytes_per_pixel = video->rgb32 ? 4 : 2;
   _dispvars->sunxi_disp          = sunxi_disp_init("/dev/fb0");

   /* Blank text console and disable cursor blinking. */
   sunxi_blank_console(_dispvars);

   _dispvars->pages = (struct sunxi_page*)calloc(NUMPAGES, sizeof (struct sunxi_page));

   if (!_dispvars->pages)
      goto error;

   _dispvars->dst_pitch           = _dispvars->sunxi_disp->xres * _dispvars->sunxi_disp->bits_per_pixel / 8;
   /* Considering 4 bytes per pixel since we will be in 32bpp on the CB/CB2/CT for hw scalers to work. */
   _dispvars->dst_pixels_per_line = _dispvars->dst_pitch / 4;
   _dispvars->pageflip_pending    = false;
   _dispvars->nextPage            = &_dispvars->pages[0];
   _dispvars->keep_vsync          = true;
   _dispvars->menu_active         = false;
   _dispvars->bytes_per_pixel     = video->rgb32 ? 4 : 2;

   switch (_dispvars->bytes_per_pixel)
   {
      case 2:
         pixman_blit = pixman_composite_src_0565_8888_asm_neon;
         break;
      case 4:
         pixman_blit = pixman_composite_src_8888_8888_asm_neon;
         break;
      default:
         goto error;
   }

   _dispvars->pending_mutex    = slock_new();
   _dispvars->vsync_condition  = scond_new();

   if (input && input_data)
      *input = NULL;

   /* Launching vsync thread */
   _dispvars->vsync_thread     = sthread_create(sunxi_vsync_thread_func, _dispvars);

   return _dispvars;

error:
   if (_dispvars)
      free(_dispvars);
   return NULL;
}
コード例 #12
0
static void *dispmanx_gfx_init(const video_info_t *video,
      const input_driver_t **input, void **input_data)
{
	int i; 
	struct dispmanx_video *_dispvars = calloc(1, sizeof(struct dispmanx_video));

   if (!_dispvars)
      return NULL;

	_dispvars->bytes_per_pixel  = video->rgb32 ? 4 : 2;
	_dispvars->screen           = 0;
	_dispvars->vcImagePtr       = 0;
	_dispvars->pageflip_pending = 0;	
	_dispvars->currentPage      = NULL;
	_dispvars->pages            = calloc(NUMPAGES, sizeof(struct dispmanx_page));

   if (!_dispvars->pages)
   {
      free(_dispvars);
      return NULL;
   }

	for (i = 0; i < NUMPAGES; i++)
   {
		_dispvars->pages[i].numpage         = i;
		_dispvars->pages[i].used            = false;
		_dispvars->pages[i].dispvars        = _dispvars;
		_dispvars->pages[i].page_used_mutex = slock_new(); 
	}

	/* Initialize the rest of the mutexes and conditions. */
	_dispvars->vsync_condition  = scond_new();
	_dispvars->pending_mutex    = slock_new();
	_dispvars->vsync_cond_mutex = slock_new(); 

	bcm_host_init();

	_dispvars->display = vc_dispmanx_display_open(_dispvars->screen);

	if (input && input_data)
		*input = NULL;

	return _dispvars;
}
コード例 #13
0
static bool thread_init(thread_video_t *thr, const video_info_t *info,
      const input_driver_t **input, void **input_data)
{
   size_t max_size;
   thread_packet_t pkt = {CMD_INIT};

   thr->lock                 = slock_new();
   thr->alpha_lock           = slock_new();
   thr->frame.lock           = slock_new();
   thr->cond_cmd             = scond_new();
   thr->cond_thread          = scond_new();
   thr->input                = input;
   thr->input_data           = input_data;
   thr->info                 = *info;
   thr->alive                = true;
   thr->focus                = true;
   thr->has_windowed         = true;
   thr->suppress_screensaver = true;

   max_size                  = info->input_scale * RARCH_SCALE_BASE;
   max_size                 *= max_size;
   max_size                 *= info->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
   thr->frame.buffer        = (uint8_t*)malloc(max_size);

   if (!thr->frame.buffer)
      return false;

   memset(thr->frame.buffer, 0x80, max_size);

   thr->last_time       = rarch_get_time_usec();
   thr->thread          = sthread_create(thread_loop, thr);
   if (!thr->thread)
      return false;

   thread_send_and_wait(thr, &pkt);

/*   thr->send_cmd_func   = thread_send_cmd;   */
/*   thr->wait_reply_func = thread_wait_reply; */

   thr->send_and_wait = thread_send_and_wait;
   return pkt.data.b;
}
コード例 #14
0
ファイル: task.cpp プロジェクト: lcsaintlee/desmume-1
Task::Impl::Impl()
{
	_isThreadRunning = false;
	workFunc = NULL;
	workFuncParam = NULL;
	ret = NULL;
	exitThread = false;

	mutex = slock_new();
   condWork = scond_new();
}
コード例 #15
0
ファイル: ffemu.c プロジェクト: Wyrick/RetroArch
static bool init_thread(ffemu_t *handle)
{
   handle->lock = slock_new();
   handle->cond_lock = slock_new();
   handle->cond = scond_new();
   handle->audio_fifo = fifo_new(32000 * sizeof(int16_t) * handle->params.channels * MAX_FRAMES / 60);
   handle->attr_fifo = fifo_new(sizeof(struct ffemu_video_data) * MAX_FRAMES);
   handle->video_fifo = fifo_new(handle->params.fb_width * handle->params.fb_height *
            handle->video.pix_size * MAX_FRAMES);

   handle->alive = true;
   handle->can_sleep = true;
   handle->thread = sthread_create(ffemu_thread, handle);

   assert(handle->lock && handle->cond_lock &&
      handle->cond && handle->audio_fifo &&
      handle->attr_fifo && handle->video_fifo && handle->thread);

   return true;
}
コード例 #16
0
ファイル: sdl_audio.c プロジェクト: mprobinson/RetroArch
static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency)
{
   (void)device;
   if (SDL_WasInit(0) == 0)
   {
      if (SDL_Init(SDL_INIT_AUDIO) < 0)
         return NULL;
   }
   else if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
      return NULL;

   sdl_audio_t *sdl = (sdl_audio_t*)calloc(1, sizeof(*sdl));
   if (!sdl)
      return NULL;

   // We have to buffer up some data ourselves, so we let SDL carry approx half of the latency. SDL double buffers audio and we do as well.
   int frames = find_num_frames(rate, latency / 4);

   SDL_AudioSpec spec = {0};
   spec.freq = rate;
   spec.format = AUDIO_S16SYS;
   spec.channels = 2;
   spec.samples = frames; // This is in audio frames, not samples ... :(
   spec.callback = sdl_audio_cb;
   spec.userdata = sdl;

   SDL_AudioSpec out;

   if (SDL_OpenAudio(&spec, &out) < 0)
   {
      RARCH_ERR("Failed to open SDL audio: %s\n", SDL_GetError());
      free(sdl);
      return 0;
   }
   g_settings.audio.out_rate = out.freq;

   sdl->lock = slock_new();
   sdl->cond = scond_new();

   RARCH_LOG("SDL audio: Requested %u ms latency, got %d ms\n", latency, (int)(out.samples * 4 * 1000 / g_settings.audio.out_rate));

   // Create a buffer twice as big as needed and prefill the buffer.
   size_t bufsize = out.samples * 4 * sizeof(int16_t);
   void *tmp = calloc(1, bufsize);
   sdl->buffer = fifo_new(bufsize);
   if (tmp)
   {
      fifo_write(sdl->buffer, tmp, bufsize);
      free(tmp);
   }

   SDL_PauseAudio(0);
   return sdl;
}
コード例 #17
0
ファイル: runloop_msg.c プロジェクト: ioev/RetroArch
void rarch_main_msg_queue_init(void)
{
   if (g_msg_queue)
      return;

   g_msg_queue = msg_queue_new(8);
   retro_assert(g_msg_queue);

#ifdef HAVE_THREADS
   mq_lock = slock_new();
   retro_assert(mq_lock);
#endif
}
コード例 #18
0
static void *dispmanx_gfx_init(const video_info_t *video,
      const input_driver_t **input, void **input_data)
{
   struct dispmanx_video *_dispvars = calloc(1, sizeof(struct dispmanx_video));

   bcm_host_init();
   _dispvars->display = vc_dispmanx_display_open(0 /* LCD */);
   /* If the console framebuffer has active overscan settings, 
    * the user must have overscan_scale=1 in config.txt to have 
    * the same size for both fb console and dispmanx. */
   graphics_get_display_size(_dispvars->display, &_dispvars->dispmanx_width, &_dispvars->dispmanx_height);

   /* Setup surface parameters */
   _dispvars->vc_image_ptr     = 0;
   _dispvars->pageflip_pending = 0;	
   _dispvars->current_page     = NULL;
   _dispvars->menu_active      = false;
  
   /* Initialize the rest of the mutexes and conditions. */
   _dispvars->vsync_condition  = scond_new();
   _dispvars->vsync_cond_mutex = slock_new();
   _dispvars->pending_mutex    = slock_new();

   dispmanx_surface_init(_dispvars,
      video->rgb32 ? 4 : 2, 
      video->rgb32 ? VC_IMAGE_XRGB8888 : VC_IMAGE_RGB565, 
      0   /* layer */, 
      255 /* alpha */, 
      3,  /* numpages */
      &_dispvars->surfaces[MAIN_SURFACE]);

   if (input && input_data)
      *input = NULL;
  
   dispmanx_blank_console(_dispvars);
 
   return _dispvars;
}
コード例 #19
0
CDIF_MT::CDIF_MT(CDAccess *cda) : disc_cdaccess(cda), CDReadThread(NULL), SBMutex(NULL), SBCond(NULL)
{
   try
   {
      CDIF_Message msg;
      RTS_Args s;

      SBMutex            = slock_new();
      SBCond             = scond_new();
      UnrecoverableError = false;

      s.cdif_ptr = this;

      CDReadThread = sthread_create((void (*)(void*))ReadThreadStart_C, &s);
      EmuThreadQueue.Read(&msg);
   }
   catch(...)
   {
      if(CDReadThread)
      {
         sthread_join((sthread_t*)CDReadThread);
         CDReadThread = NULL;
      }

      if(SBMutex)
      {
         slock_free((slock_t*)SBMutex);
         SBMutex = NULL;
      }

      if(SBCond)
      {
         scond_free((scond_t*)SBCond);
         SBCond = NULL;
      }

      if(disc_cdaccess)
      {
         delete disc_cdaccess;
         disc_cdaccess = NULL;
      }

      throw;
   }
}
コード例 #20
0
ファイル: rsound.c プロジェクト: AirBrowse/RetroArch
static void *rs_init(const char *device, unsigned rate, unsigned latency)
{
   int channels, format;
   rsd_t *rsd = (rsd_t*)calloc(1, sizeof(rsd_t));
   if (!rsd)
      return NULL;

   rsound_t *rd;

   if (rsd_init(&rd) < 0)
   {
      free(rsd);
      return NULL;
   }

   rsd->cond_lock = slock_new();
   rsd->cond = scond_new();

   rsd->buffer = fifo_new(1024 * 4);

   channels = 2;
   format   = RSD_S16_NE;

   rsd_set_param(rd, RSD_CHANNELS, &channels);
   rsd_set_param(rd, RSD_SAMPLERATE, &rate);
   rsd_set_param(rd, RSD_LATENCY, &latency);

   if (device)
      rsd_set_param(rd, RSD_HOST, (void*)device);

   rsd_set_param(rd, RSD_FORMAT, &format);

   rsd_set_callback(rd, rsound_audio_cb, err_cb, 256, rsd);

   if (rsd_start(rd) < 0)
   {
      free(rsd);
      rsd_free(rd);
      return NULL;
   }

   rsd->rd = rd;
   return rsd;
}
コード例 #21
0
/**
 * rarch_threaded_audio_init:
 * @out_driver                : output driver
 * @out_data                  : output audio data
 * @device                    : audio device (optional)
 * @out_rate                  : output audio rate
 * @latency                   : audio latency
 * @driver                    : audio driver
 *
 * Starts a audio driver in a new thread.
 * Access to audio driver will be mediated through this driver.
 * This driver interfaces with audio callback and is 
 * only used in that case.
 *
 * Returns: true (1) if successful, otherwise false (0).
 **/
bool rarch_threaded_audio_init(const audio_driver_t **out_driver,
      void **out_data, const char *device, unsigned audio_out_rate,
      unsigned latency, const audio_driver_t *drv)
{
   audio_thread_t *thr = (audio_thread_t*)calloc(1, sizeof(*thr));
   if (!thr)
      return false;

   thr->driver         = (const audio_driver_t*)drv;
   thr->device         = device;
   thr->out_rate       = audio_out_rate;
   thr->latency        = latency;

   if (!(thr->cond     = scond_new()))
      goto error;
   if (!(thr->lock     = slock_new()))
      goto error;

   thr->alive = true;
   thr->stopped = true;

   if (!(thr->thread   = sthread_create(audio_thread_loop, thr)))
      goto error;

   /* Wait until thread has initialized (or failed) the driver. */
   slock_lock(thr->lock);
   while (!thr->inited)
      scond_wait(thr->cond, thr->lock);
   slock_unlock(thr->lock);

   if (thr->inited < 0) /* Thread failed. */
      goto error;

   *out_driver         = &audio_thread;
   *out_data           = thr;
   return true;

error:
   *out_driver         = NULL;
   *out_data           = NULL;
   audio_thread_free(thr);
   return false;
}
コード例 #22
0
ファイル: ui_qt.cpp プロジェクト: dankcushions/RetroArch
static void *ui_companion_qt_init(void)
{
   ui_companion_qt_t *handle = (ui_companion_qt_t*)calloc(1, sizeof(*handle));
   if (!handle)
      return NULL;

#ifdef HAVE_QT_WRAPPER
   settings_t *settings = config_get_ptr();
   handle->lock         = slock_new();
   handle->thread       = sthread_create(qt_thread, handle);
   if (!handle->thread)
   {
      slock_free(handle->lock);
      free(handle);
      return NULL;
   }
#endif

   return handle;
}
コード例 #23
0
static int add_adapter(void *data, struct libusb_device *dev)
{
   int rc;
   struct libusb_device_descriptor desc;
   const char *device_name         = NULL;
   struct libusb_adapter *old_head = NULL;
   struct libusb_hid          *hid = (struct libusb_hid*)data;
   struct libusb_adapter *adapter  = (struct libusb_adapter*)
      calloc(1, sizeof(struct libusb_adapter));

   if (!adapter)
      return -1;

   if (!hid)
   {
      free(adapter);
      RARCH_ERR("Allocation of adapter failed.\n");
      return -1;
   }

   rc = libusb_get_device_descriptor(dev, &desc);

   if (rc != LIBUSB_SUCCESS)
   {
      RARCH_ERR("Error getting device descriptor.\n");
      goto error;
   }

   adapter->device = dev;

   libusb_get_description(adapter->device, adapter);

   if (adapter->endpoint_in == 0)
   {
      RARCH_ERR("Could not find HID config for device.\n");
      goto error;
   }

   rc = libusb_open (adapter->device, &adapter->handle);

   if (rc != LIBUSB_SUCCESS)
   {
      RARCH_ERR("Error opening device 0x%p (VID/PID: %04x:%04x).\n",
            (void*)adapter->device, desc.idVendor, desc.idProduct);
      goto error;
   }

   if (desc.iManufacturer)
   {
      libusb_get_string_descriptor_ascii(adapter->handle,
            desc.iManufacturer, adapter->manufacturer_name,
            sizeof(adapter->manufacturer_name));
#if 0
      RARCH_ERR(" Adapter Manufacturer name: %s\n",
            adapter->manufacturer_name);
#endif
   }

   if (desc.iProduct)
   {
      libusb_get_string_descriptor_ascii(adapter->handle,
            desc.iProduct, adapter->name,
            sizeof(adapter->name));
#if 0
      RARCH_ERR(" Adapter name: %s\n", adapter->name);
#endif
   }

   device_name   = (const char*)adapter->name;

   if (string_is_empty((const char*)adapter->name))
      goto error;

   adapter->send_control_lock = slock_new();
   adapter->send_control_buffer = fifo_new(4096);

   if (!adapter->send_control_lock || !adapter->send_control_buffer)
   {
      RARCH_ERR("Error creating send control buffer.\n");
      goto error;
   }

   adapter->slot = pad_connection_pad_init(hid->slots,
         device_name, desc.idVendor, desc.idProduct,
         adapter, &libusb_hid_device_send_control);

   if (adapter->slot == -1)
      goto error;

   if (!pad_connection_has_interface(hid->slots, adapter->slot))
   {
      RARCH_ERR(" Interface not found (%s).\n", adapter->name);
      goto error;
   }

   RARCH_LOG("Interface found: [%s].\n", adapter->name);

   if (libusb_kernel_driver_active(adapter->handle, 0) == 1
         && libusb_detach_kernel_driver(adapter->handle, 0))
   {
      RARCH_ERR("Error detaching handle 0x%p from kernel.\n", adapter->handle);
      goto error;
   }

   rc = libusb_claim_interface(adapter->handle, adapter->interface_number);

   if (rc != LIBUSB_SUCCESS)
   {
      RARCH_ERR("Error claiming interface %d .\n", adapter->interface_number);
      goto error;
   }

   RARCH_LOG("Device 0x%p attached (VID/PID: %04x:%04x).\n",
         adapter->device, desc.idVendor, desc.idProduct);

   libusb_hid_device_add_autodetect(adapter->slot,
         device_name, libusb_hid.ident, desc.idVendor, desc.idProduct);

   adapter->hid = hid;
   adapter->thread = sthread_create(adapter_thread, adapter);

   if (!adapter->thread)
   {
      RARCH_ERR("Error initializing adapter thread.\n");
      goto error;
   }

   old_head      = adapters.next;
   adapters.next = adapter;
   adapter->next = old_head;

   return 0;

error:
   if (adapter->thread)
      sthread_join(adapter->thread);
   if (adapter->send_control_lock)
      slock_free(adapter->send_control_lock);
   if (adapter->send_control_buffer)
      fifo_free(adapter->send_control_buffer);
   if (adapter)
      free(adapter);
   return -1;
}
コード例 #24
0
ファイル: platform_gx.c プロジェクト: AkimanBengus/RetroArch
static void frontend_gx_init(void *data)
{
   (void)data;
#ifdef HW_RVL
   IOS_ReloadIOS(IOS_GetVersion());
   L2Enhance();
#ifndef IS_SALAMANDER
   gx_init_mem2();
#endif
#endif

#ifdef USBGECKO
   DEBUG_Init(GDBSTUB_DEVICE_USB, 1);
   _break();
#endif

#if defined(DEBUG) && defined(IS_SALAMANDER)
   VIInit();
   GXRModeObj *rmode = VIDEO_GetPreferredMode(NULL);
   void *xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
   console_init(xfb, 20, 20, rmode->fbWidth,
         rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ);
   VIConfigure(rmode);
   VISetNextFramebuffer(xfb);
   VISetBlack(FALSE);
   VIFlush();
   VIWaitForRetrace();
   VIWaitForRetrace();
#endif

#ifndef DEBUG
   __exception_setreload(8);
#endif

   fatInitDefault();

#ifdef HAVE_LOGGER
   devoptab_list[STD_OUT] = &dotab_stdout;
   devoptab_list[STD_ERR] = &dotab_stdout;
   dotab_stdout.write_r = gx_logger_net;
#elif defined(HAVE_FILE_LOGGER) && !defined(IS_SALAMANDER)
   devoptab_list[STD_OUT] = &dotab_stdout;
   devoptab_list[STD_ERR] = &dotab_stdout;
   dotab_stdout.write_r = gx_logger_file;
#endif

#if defined(HW_RVL) && !defined(IS_SALAMANDER)
   gx_devices[GX_DEVICE_SD].interface = &__io_wiisd;
   gx_devices[GX_DEVICE_SD].name = "sd";
   gx_devices[GX_DEVICE_SD].mounted = fatMountSimple(
         gx_devices[GX_DEVICE_SD].name,
         gx_devices[GX_DEVICE_SD].interface);
   gx_devices[GX_DEVICE_USB].interface = &__io_usbstorage;
   gx_devices[GX_DEVICE_USB].name = "usb";
   gx_devices[GX_DEVICE_USB].mounted = fatMountSimple(
            gx_devices[GX_DEVICE_USB].name,
            gx_devices[GX_DEVICE_USB].interface);

   gx_device_cond_mutex = slock_new();
   gx_device_cond       = scond_new();
   gx_device_mutex      = slock_new();
   gx_device_thread     = sthread_create(gx_devthread, NULL);
#endif
}
コード例 #25
0
ファイル: alsathread.c プロジェクト: Ezio-PS/RetroArch
static void *alsa_thread_init(const char *device,
      unsigned rate, unsigned latency)
{
   snd_pcm_uframes_t buffer_size;
   snd_pcm_format_t format;
   snd_pcm_hw_params_t *params    = NULL;
   snd_pcm_sw_params_t *sw_params = NULL;
   const char *alsa_dev           = device ? device : "default";
   unsigned latency_usec          = latency * 1000 / 2;
   unsigned channels              = 2;
   unsigned periods               = 4;
   alsa_thread_t            *alsa = (alsa_thread_t*)
      calloc(1, sizeof(alsa_thread_t));

   if (!alsa)
      return NULL;

   TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, 0));

   TRY_ALSA(snd_pcm_hw_params_malloc(&params));
   alsa->has_float = alsathread_find_float_format(alsa->pcm, params);
   format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16;

   TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params));
   TRY_ALSA(snd_pcm_hw_params_set_access(
            alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED));
   TRY_ALSA(snd_pcm_hw_params_set_format(alsa->pcm, params, format));
   TRY_ALSA(snd_pcm_hw_params_set_channels(alsa->pcm, params, channels));
   TRY_ALSA(snd_pcm_hw_params_set_rate(alsa->pcm, params, rate, 0));

   TRY_ALSA(snd_pcm_hw_params_set_buffer_time_near(
            alsa->pcm, params, &latency_usec, NULL));
   TRY_ALSA(snd_pcm_hw_params_set_periods_near(
            alsa->pcm, params, &periods, NULL));

   TRY_ALSA(snd_pcm_hw_params(alsa->pcm, params));

   /* Shouldn't have to bother with this, 
    * but some drivers are apparently broken. */
   if (snd_pcm_hw_params_get_period_size(params, &alsa->period_frames, NULL))
      snd_pcm_hw_params_get_period_size_min(
            params, &alsa->period_frames, NULL);
   RARCH_LOG("ALSA: Period size: %d frames\n", (int)alsa->period_frames);
   if (snd_pcm_hw_params_get_buffer_size(params, &buffer_size))
      snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size);
   RARCH_LOG("ALSA: Buffer size: %d frames\n", (int)buffer_size);

   alsa->buffer_size = snd_pcm_frames_to_bytes(alsa->pcm, buffer_size);
   alsa->period_size = snd_pcm_frames_to_bytes(alsa->pcm, alsa->period_frames);

   TRY_ALSA(snd_pcm_sw_params_malloc(&sw_params));
   TRY_ALSA(snd_pcm_sw_params_current(alsa->pcm, sw_params));
   TRY_ALSA(snd_pcm_sw_params_set_start_threshold(
            alsa->pcm, sw_params, buffer_size / 2));
   TRY_ALSA(snd_pcm_sw_params(alsa->pcm, sw_params));

   snd_pcm_hw_params_free(params);
   snd_pcm_sw_params_free(sw_params);

   alsa->fifo_lock = slock_new();
   alsa->cond_lock = slock_new();
   alsa->cond = scond_new();
   alsa->buffer = fifo_new(alsa->buffer_size);
   if (!alsa->fifo_lock || !alsa->cond_lock || !alsa->cond || !alsa->buffer)
      goto error;

   alsa->worker_thread = sthread_create(alsa_worker_thread, alsa);
   if (!alsa->worker_thread)
   {
      RARCH_ERR("error initializing worker thread");
      goto error;
   }

   return alsa;

error:
   RARCH_ERR("ALSA: Failed to initialize...\n");
   if (params)
      snd_pcm_hw_params_free(params);

   if (sw_params)
      snd_pcm_sw_params_free(sw_params);

   alsa_thread_free(alsa);

   return NULL;
}
コード例 #26
0
ファイル: stubs.cpp プロジェクト: Oggom/mednafen-libretro
MDFN_Mutex *MDFND_CreateMutex()
{
   return (MDFN_Mutex*)slock_new();
}
コード例 #27
0
ファイル: runloop.c プロジェクト: Sotsukun/RetroArch
bool runloop_ctl(enum runloop_ctl_state state, void *data)
{
   static rarch_dir_list_t runloop_shader_dir;
   static char runloop_fullpath[PATH_MAX_LENGTH];
   static rarch_system_info_t runloop_system;
   static unsigned runloop_pending_windowed_scale;
   static retro_keyboard_event_t runloop_key_event = NULL;
   static unsigned runloop_max_frames              = false;
   static bool runloop_frame_time_last             = false;
   static bool runloop_set_frame_limit             = false;
   static bool runloop_paused                      = false;
   static bool runloop_idle                        = false;
   static bool runloop_exec                        = false;
   static bool runloop_slowmotion                  = false;
   static bool runloop_shutdown_initiated          = false;
   static bool runloop_core_shutdown_initiated     = false;
   static bool runloop_perfcnt_enable              = false;
   static bool runloop_overrides_active            = false;
   static bool runloop_game_options_active         = false;
#ifdef HAVE_THREADS
   static slock_t *runloop_msg_queue_lock          = NULL;
#endif
   static core_info_t *core_info_current           = NULL;
   static core_info_list_t *core_info_curr_list    = NULL;
   settings_t *settings                            = config_get_ptr();

   switch (state)
   {
      case RUNLOOP_CTL_DATA_ITERATE:
         rarch_task_check();
         return true;
      case RUNLOOP_CTL_SHADER_DIR_DEINIT:
         shader_dir_free(&runloop_shader_dir);
         return true;
      case RUNLOOP_CTL_SHADER_DIR_INIT:
         return shader_dir_init(&runloop_shader_dir);
      case RUNLOOP_CTL_SYSTEM_INFO_INIT:
         core.retro_get_system_info(&runloop_system.info);

         if (!runloop_system.info.library_name)
            runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN);
         if (!runloop_system.info.library_version)
            runloop_system.info.library_version = "v0";

#ifndef RARCH_CONSOLE
         strlcpy(runloop_system.title_buf, 
               msg_hash_to_str(MSG_PROGRAM), sizeof(runloop_system.title_buf));
         strlcat(runloop_system.title_buf, " : ", sizeof(runloop_system.title_buf));
#endif
         strlcat(runloop_system.title_buf, runloop_system.info.library_name, sizeof(runloop_system.title_buf));
         strlcat(runloop_system.title_buf, " ", sizeof(runloop_system.title_buf));
         strlcat(runloop_system.title_buf, runloop_system.info.library_version, sizeof(runloop_system.title_buf));
         strlcpy(runloop_system.valid_extensions, runloop_system.info.valid_extensions ?
               runloop_system.info.valid_extensions : DEFAULT_EXT,
               sizeof(runloop_system.valid_extensions));
         runloop_system.block_extract = runloop_system.info.block_extract;
         break;
      case RUNLOOP_CTL_GET_CORE_OPTION_SIZE:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            *idx = core_option_size(runloop_system.core_options);
         }
         return true;
      case RUNLOOP_CTL_HAS_CORE_OPTIONS:
         return runloop_system.core_options;
      case RUNLOOP_CTL_CURRENT_CORE_LIST_FREE:
         if (core_info_curr_list)
            core_info_list_free(core_info_curr_list);
         core_info_curr_list = NULL;
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_LIST_INIT:
         core_info_curr_list = core_info_list_new();
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_LIST_GET:
         {
            core_info_list_t **core = (core_info_list_t**)data;
            if (!core)
               return false;
            *core = core_info_curr_list;
         }
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_FREE:
         if (core_info_current)
            free(core_info_current);
         core_info_current = NULL;
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_INIT:
         core_info_current = (core_info_t*)calloc(1, sizeof(core_info_t));
         if (!core_info_current)
            return false;
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_GET:
         {
            core_info_t **core = (core_info_t**)data;
            if (!core)
               return false;
            *core = core_info_current;
         }
         return true;
      case RUNLOOP_CTL_SYSTEM_INFO_GET:
         {
            rarch_system_info_t **system = (rarch_system_info_t**)data;
            if (!system)
               return false;
            *system = &runloop_system;
         }
         return true;
      case RUNLOOP_CTL_SYSTEM_INFO_FREE:
         if (runloop_system.core_options)
         {
            core_option_flush(runloop_system.core_options);
            core_option_free(runloop_system.core_options);
         }

         runloop_system.core_options = NULL;

         /* No longer valid. */
         if (runloop_system.special)
            free(runloop_system.special);
         runloop_system.special = NULL;
         if (runloop_system.ports)
            free(runloop_system.ports);
         runloop_system.ports   = NULL;

         runloop_key_event = NULL;
         global_get_ptr()->frontend_key_event = NULL;
         audio_driver_unset_callback();
         memset(&runloop_system, 0, sizeof(rarch_system_info_t));
         break;
      case RUNLOOP_CTL_IS_FRAME_COUNT_END:
         {
            uint64_t *frame_count         = NULL;
            video_driver_ctl(RARCH_DISPLAY_CTL_GET_FRAME_COUNT, &frame_count);
            return runloop_max_frames && (*frame_count >= runloop_max_frames);
         }
      case RUNLOOP_CTL_SET_FRAME_TIME_LAST:
         runloop_frame_time_last = true;
         break;
      case RUNLOOP_CTL_UNSET_FRAME_TIME_LAST:
         runloop_frame_time_last = false;
         break;
      case RUNLOOP_CTL_SET_OVERRIDES_ACTIVE:
         runloop_overrides_active = true;
         break;
      case RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE:
         runloop_overrides_active = false; 
         break;
      case RUNLOOP_CTL_IS_OVERRIDES_ACTIVE:
         return runloop_overrides_active;
      case RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE:
         runloop_game_options_active = true;
         break;
      case RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE:
         runloop_game_options_active = false;
         break;
      case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE:
         return runloop_game_options_active;
      case RUNLOOP_CTL_IS_FRAME_TIME_LAST:
         return runloop_frame_time_last;
      case RUNLOOP_CTL_SET_FRAME_LIMIT:
         runloop_set_frame_limit = true;
         break;
      case RUNLOOP_CTL_UNSET_FRAME_LIMIT:
         runloop_set_frame_limit = false;
         break;
      case RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT:
         return runloop_set_frame_limit;
      case RUNLOOP_CTL_GET_PERFCNT:
         {
            bool **perfcnt = (bool**)data;
            if (!perfcnt)
               return false;
            *perfcnt = &runloop_perfcnt_enable;
         }
         return true;
      case RUNLOOP_CTL_SET_PERFCNT_ENABLE:
         runloop_perfcnt_enable = true;
         break;
      case RUNLOOP_CTL_UNSET_PERFCNT_ENABLE:
         runloop_perfcnt_enable = false;
         break;
      case RUNLOOP_CTL_IS_PERFCNT_ENABLE:
         return runloop_perfcnt_enable;
      case RUNLOOP_CTL_GET_WINDOWED_SCALE:
         {
            unsigned **scale = (unsigned**)data;
            if (!scale)
               return false;
            *scale       = (unsigned*)&runloop_pending_windowed_scale;
         }
         break;
      case RUNLOOP_CTL_SET_WINDOWED_SCALE:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            runloop_pending_windowed_scale = *idx;
         }
         break;
      case RUNLOOP_CTL_SET_LIBRETRO_PATH:
         {
            const char *fullpath = (const char*)data;
            if (!fullpath)
               return false;
            strlcpy(settings->libretro, fullpath, sizeof(settings->libretro));
         }
         break;
      case RUNLOOP_CTL_CLEAR_CONTENT_PATH:
         *runloop_fullpath = '\0';
         break;
      case RUNLOOP_CTL_GET_CONTENT_PATH:
         {
            char **fullpath = (char**)data;
            if (!fullpath)
               return false;
            *fullpath       = (char*)runloop_fullpath;
         }
         break;
      case RUNLOOP_CTL_SET_CONTENT_PATH:
         {
            const char *fullpath = (const char*)data;
            if (!fullpath)
               return false;
            strlcpy(runloop_fullpath, fullpath, sizeof(runloop_fullpath));
         }
         break;
      case RUNLOOP_CTL_CHECK_FOCUS:
         if (settings->pause_nonactive)
            return video_driver_ctl(RARCH_DISPLAY_CTL_IS_FOCUSED, NULL);
         return true;
      case RUNLOOP_CTL_CHECK_IDLE_STATE:
         {
            event_cmd_state_t *cmd    = (event_cmd_state_t*)data;
            bool focused              = runloop_ctl(RUNLOOP_CTL_CHECK_FOCUS, NULL);

            check_pause(settings, focused,
                  runloop_cmd_triggered(cmd, RARCH_PAUSE_TOGGLE),
                  runloop_cmd_triggered(cmd, RARCH_FRAMEADVANCE));

            if (!runloop_ctl(RUNLOOP_CTL_CHECK_PAUSE_STATE, cmd) || !focused)
               return false;
            break;
         }
      case RUNLOOP_CTL_CHECK_STATE:
         {
            bool tmp                  = false;
            event_cmd_state_t *cmd    = (event_cmd_state_t*)data;

            if (!cmd || runloop_idle)
               return false;

            if (runloop_cmd_triggered(cmd, RARCH_SCREENSHOT))
               event_command(EVENT_CMD_TAKE_SCREENSHOT);

            if (runloop_cmd_triggered(cmd, RARCH_MUTE))
               event_command(EVENT_CMD_AUDIO_MUTE_TOGGLE);

            if (runloop_cmd_triggered(cmd, RARCH_OSK))
            {
               if (input_driver_ctl(RARCH_INPUT_CTL_IS_KEYBOARD_LINEFEED_ENABLED, NULL))
                  input_driver_ctl(RARCH_INPUT_CTL_UNSET_KEYBOARD_LINEFEED_ENABLED, NULL);
               else
                  input_driver_ctl(RARCH_INPUT_CTL_SET_KEYBOARD_LINEFEED_ENABLED, NULL);
            }

            if (runloop_cmd_press(cmd, RARCH_VOLUME_UP))
               event_command(EVENT_CMD_VOLUME_UP);
            else if (runloop_cmd_press(cmd, RARCH_VOLUME_DOWN))
               event_command(EVENT_CMD_VOLUME_DOWN);

#ifdef HAVE_NETPLAY
            tmp = runloop_cmd_triggered(cmd, RARCH_NETPLAY_FLIP);
            netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, &tmp);
            tmp = runloop_cmd_triggered(cmd, RARCH_FULLSCREEN_TOGGLE_KEY);
            netplay_driver_ctl(RARCH_NETPLAY_CTL_FULLSCREEN_TOGGLE, &tmp);
#endif
            if (!runloop_ctl(RUNLOOP_CTL_CHECK_IDLE_STATE, data))
               return false;

            check_fast_forward_button(
                  runloop_cmd_triggered(cmd, RARCH_FAST_FORWARD_KEY),
                  runloop_cmd_press    (cmd, RARCH_FAST_FORWARD_HOLD_KEY),
                  runloop_cmd_pressed  (cmd, RARCH_FAST_FORWARD_HOLD_KEY));
            check_stateslots(settings,
                  runloop_cmd_triggered(cmd, RARCH_STATE_SLOT_PLUS),
                  runloop_cmd_triggered(cmd, RARCH_STATE_SLOT_MINUS)
                  );

            if (runloop_cmd_triggered(cmd, RARCH_SAVE_STATE_KEY))
               event_command(EVENT_CMD_SAVE_STATE);
            else if (runloop_cmd_triggered(cmd, RARCH_LOAD_STATE_KEY))
               event_command(EVENT_CMD_LOAD_STATE);

            state_manager_check_rewind(runloop_cmd_press(cmd, RARCH_REWIND));

            tmp = runloop_cmd_press(cmd, RARCH_SLOWMOTION);

            runloop_ctl(RUNLOOP_CTL_CHECK_SLOWMOTION, &tmp);

            if (runloop_cmd_triggered(cmd, RARCH_MOVIE_RECORD_TOGGLE))
               runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE, NULL);

            check_shader_dir(&runloop_shader_dir,
                  runloop_cmd_triggered(cmd, RARCH_SHADER_NEXT),
                  runloop_cmd_triggered(cmd, RARCH_SHADER_PREV));

            if (runloop_cmd_triggered(cmd, RARCH_DISK_EJECT_TOGGLE))
               event_command(EVENT_CMD_DISK_EJECT_TOGGLE);
            else if (runloop_cmd_triggered(cmd, RARCH_DISK_NEXT))
               event_command(EVENT_CMD_DISK_NEXT);
            else if (runloop_cmd_triggered(cmd, RARCH_DISK_PREV))
               event_command(EVENT_CMD_DISK_PREV);

            if (runloop_cmd_triggered(cmd, RARCH_RESET))
               event_command(EVENT_CMD_RESET);

            cheat_manager_state_checks(
                  runloop_cmd_triggered(cmd, RARCH_CHEAT_INDEX_PLUS),
                  runloop_cmd_triggered(cmd, RARCH_CHEAT_INDEX_MINUS),
                  runloop_cmd_triggered(cmd, RARCH_CHEAT_TOGGLE));
         }
         break;
      case RUNLOOP_CTL_CHECK_PAUSE_STATE:
         {
            bool check_is_oneshot;
            event_cmd_state_t *cmd    = (event_cmd_state_t*)data;

            if (!cmd)
               return false;

            check_is_oneshot     = runloop_cmd_triggered(cmd, RARCH_FRAMEADVANCE) 
               || runloop_cmd_press(cmd, RARCH_REWIND);

            if (!runloop_paused)
               return true;

            if (runloop_cmd_triggered(cmd, RARCH_FULLSCREEN_TOGGLE_KEY))
            {
               event_command(EVENT_CMD_FULLSCREEN_TOGGLE);
               video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL);
            }

            if (!check_is_oneshot)
               return false;
         }
         break;
      case RUNLOOP_CTL_CHECK_SLOWMOTION:
         {
            bool *ptr            = (bool*)data;

            if (!ptr)
               return false;

            runloop_slowmotion   = *ptr;

            if (!runloop_slowmotion)
               return false;

            if (settings->video.black_frame_insertion)
               video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL);

            if (state_manager_frame_is_reversed())
               runloop_msg_queue_push_new(MSG_SLOW_MOTION_REWIND, 0, 30, true);
            else
               runloop_msg_queue_push_new(MSG_SLOW_MOTION, 0, 30, true);
         }
         break;
      case RUNLOOP_CTL_CHECK_MOVIE:
         if (bsv_movie_ctl(BSV_MOVIE_CTL_PLAYBACK_ON, NULL))
            return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_PLAYBACK, NULL);
         if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_INIT, NULL);
         return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_RECORD, NULL);
      case RUNLOOP_CTL_CHECK_MOVIE_RECORD:
         if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return false;

         runloop_msg_queue_push_new(
               MSG_MOVIE_RECORD_STOPPED, 2, 180, true);
         RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED));

         event_command(EVENT_CMD_BSV_MOVIE_DEINIT);
         break;
      case RUNLOOP_CTL_CHECK_MOVIE_INIT:
         if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return false;
         {
            char msg[128];
            char path[PATH_MAX_LENGTH];

            settings->rewind_granularity = 1;

            if (settings->state_slot > 0)
               snprintf(path, sizeof(path), "%s%d",
                     bsv_movie_get_path(), settings->state_slot);
            else
               strlcpy(path, bsv_movie_get_path(), sizeof(path));

            strlcat(path, ".bsv", sizeof(path));

            snprintf(msg, sizeof(msg), "%s \"%s\".",
                  msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
                  path);

            bsv_movie_init_handle(path, RARCH_MOVIE_RECORD);

            if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
               return false;
            else if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            {
               runloop_msg_queue_push(msg, 1, 180, true);
               RARCH_LOG("%s \"%s\".\n",
                     msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
                     path);
            }
            else
            {
               runloop_msg_queue_push_new(
                     MSG_FAILED_TO_START_MOVIE_RECORD,
                     1, 180, true);
               RARCH_ERR("%s\n", msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
            }
         }
         break;
      case RUNLOOP_CTL_CHECK_MOVIE_PLAYBACK:
         if (!bsv_movie_ctl(BSV_MOVIE_CTL_END, NULL))
            return false;

         runloop_msg_queue_push_new(
               MSG_MOVIE_PLAYBACK_ENDED, 1, 180, false);
         RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED));

         event_command(EVENT_CMD_BSV_MOVIE_DEINIT);

         bsv_movie_ctl(BSV_MOVIE_CTL_UNSET_END, NULL);
         bsv_movie_ctl(BSV_MOVIE_CTL_UNSET_PLAYBACK, NULL);
         break;
      case RUNLOOP_CTL_STATE_FREE:
         runloop_perfcnt_enable     = false;
         runloop_idle               = false;
         runloop_paused             = false;
         runloop_slowmotion         = false;
         runloop_frame_time_last    = false;
         runloop_set_frame_limit    = false;
         runloop_overrides_active   = false;
         runloop_max_frames         = 0;
         break;
      case RUNLOOP_CTL_GLOBAL_FREE:
         {
            global_t *global;
            event_command(EVENT_CMD_TEMPORARY_CONTENT_DEINIT);
            event_command(EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT);
            event_command(EVENT_CMD_RECORD_DEINIT);
            event_command(EVENT_CMD_LOG_FILE_DEINIT);

            rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL);
            runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH,  NULL);
            runloop_overrides_active   = false;

            global = global_get_ptr();
            memset(global, 0, sizeof(struct global));
         }
         break;
      case RUNLOOP_CTL_CLEAR_STATE:
         driver_ctl(RARCH_DRIVER_CTL_DEINIT,  NULL);
         runloop_ctl(RUNLOOP_CTL_STATE_FREE,  NULL);
         runloop_ctl(RUNLOOP_CTL_GLOBAL_FREE, NULL);
         break;
      case RUNLOOP_CTL_SET_MAX_FRAMES:
         {
            unsigned *ptr = (unsigned*)data;
            if (!ptr)
               return false;
            runloop_max_frames = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_IDLE:
         return runloop_idle;
      case RUNLOOP_CTL_SET_IDLE:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_idle = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_SLOWMOTION:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            *ptr = runloop_slowmotion;
         }
         break;
      case RUNLOOP_CTL_SET_SLOWMOTION:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_slowmotion = *ptr;
         }
         break;
      case RUNLOOP_CTL_SET_PAUSED:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_paused = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_PAUSED:
         return runloop_paused;
      case RUNLOOP_CTL_MSG_QUEUE_FREE:
#ifdef HAVE_THREADS
         slock_free(runloop_msg_queue_lock);
         runloop_msg_queue_lock = NULL;
#endif
         break;
      case RUNLOOP_CTL_MSG_QUEUE_DEINIT:
         if (!g_msg_queue)
            return true;

         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_LOCK, NULL);

         msg_queue_free(g_msg_queue);

         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_UNLOCK, NULL);
         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_FREE, NULL);

         g_msg_queue = NULL;
         break;
      case RUNLOOP_CTL_MSG_QUEUE_INIT:
         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL);
         g_msg_queue = msg_queue_new(8);
         retro_assert(g_msg_queue);

#ifdef HAVE_THREADS
         runloop_msg_queue_lock = slock_new();
         retro_assert(runloop_msg_queue_lock);
#endif
         break;
      case RUNLOOP_CTL_MSG_QUEUE_LOCK:
#ifdef HAVE_THREADS
         slock_lock(runloop_msg_queue_lock);
#endif
         break;
      case RUNLOOP_CTL_MSG_QUEUE_UNLOCK:
#ifdef HAVE_THREADS
         slock_unlock(runloop_msg_queue_lock);
#endif
         break;
      case RUNLOOP_CTL_PREPARE_DUMMY:
#ifdef HAVE_MENU
         menu_driver_ctl(RARCH_MENU_CTL_UNSET_LOAD_NO_CONTENT, NULL);
#endif
         runloop_data_clear_state();

         runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL);

         rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL);
         break;
      case RUNLOOP_CTL_SET_CORE_SHUTDOWN:
         runloop_core_shutdown_initiated = true;
         break;
      case RUNLOOP_CTL_UNSET_CORE_SHUTDOWN:
         runloop_core_shutdown_initiated = false;
         break;
      case RUNLOOP_CTL_IS_CORE_SHUTDOWN:
         return runloop_core_shutdown_initiated;
      case RUNLOOP_CTL_SET_SHUTDOWN:
         runloop_shutdown_initiated = true;
         break;
      case RUNLOOP_CTL_UNSET_SHUTDOWN:
         runloop_shutdown_initiated = false;
         break;
      case RUNLOOP_CTL_IS_SHUTDOWN:
         return runloop_shutdown_initiated;
      case RUNLOOP_CTL_SET_EXEC:
         runloop_exec = true;
         break;
      case RUNLOOP_CTL_UNSET_EXEC:
         runloop_exec = false;
         break;
      case RUNLOOP_CTL_IS_EXEC:
         return runloop_exec;
      case RUNLOOP_CTL_DATA_DEINIT:
         rarch_task_deinit();
         break;
      case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED:
         return runloop_system.core_options ?
            core_option_updated(runloop_system.core_options) : false;
      case RUNLOOP_CTL_CORE_OPTION_PREV:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            core_option_prev(runloop_system.core_options, *idx);
            if (ui_companion_is_on_foreground())
               ui_companion_driver_notify_refresh();
         }
         return true;
      case RUNLOOP_CTL_CORE_OPTION_NEXT:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            core_option_next(runloop_system.core_options, *idx);
            if (ui_companion_is_on_foreground())
               ui_companion_driver_notify_refresh();
         }
         return true;
      case RUNLOOP_CTL_CORE_OPTIONS_GET:
         {
            struct retro_variable *var = (struct retro_variable*)data;

            if (!runloop_system.core_options || !var)
               return false;

            RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key);
            core_option_get(runloop_system.core_options, var);
            RARCH_LOG("\t%s\n", var->value ? var->value : "N/A");
         }
         return true;
      case RUNLOOP_CTL_CORE_OPTIONS_INIT:
         {
            char *game_options_path           = NULL;
            bool ret                          = false;
            const struct retro_variable *vars = (const struct retro_variable*)data;
            char buf[PATH_MAX_LENGTH]         = {0};
            global_t *global                  = global_get_ptr();
            const char *options_path          = settings->core_options_path;

            if (!*options_path && *global->path.config)
            {
               fill_pathname_resolve_relative(buf, global->path.config,
                     "retroarch-core-options.cfg", sizeof(buf));
               options_path = buf;
            }


            if (settings->game_specific_options)
               ret = rarch_game_specific_options(&game_options_path);

            if(ret)
            {
               runloop_ctl(RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE, NULL);
               runloop_system.core_options = core_option_new(game_options_path, vars);
               free(game_options_path);
            }
            else
            {
               runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL);
               runloop_system.core_options = core_option_new(options_path, vars);
            }

         }
         break;
      case RUNLOOP_CTL_CORE_OPTIONS_DEINIT:
         if (!runloop_system.core_options)
            return false;

         core_option_flush(runloop_system.core_options);
         core_option_free(runloop_system.core_options);

         runloop_system.core_options = NULL;
         return true;
      case RUNLOOP_CTL_KEY_EVENT_GET:
         {
            retro_keyboard_event_t **key_event = (retro_keyboard_event_t**)data;
            if (!key_event)
               return false;
            *key_event = &runloop_key_event;
         }
         break;
      case RUNLOOP_CTL_NONE:
      default:
         return false;
   }

   return true;
}
コード例 #28
0
ファイル: video_filter.c プロジェクト: AlexFolland/RetroArch
static bool create_softfilter_graph(rarch_softfilter_t *filt,
      enum retro_pixel_format in_pixel_format,
      unsigned max_width, unsigned max_height,
      softfilter_simd_mask_t cpu_features,
      unsigned threads)
{
   unsigned input_fmts, input_fmt, output_fmts, i = 0;
   struct config_file_userdata userdata;
   char key[64]  = {0};
   char name[64] = {0};

   (void)i;

   snprintf(key, sizeof(key), "filter");

   if (!config_get_array(filt->conf, key, name, sizeof(name)))
   {
      RARCH_ERR("Could not find 'filter' array in config.\n");
      return false;
   }

   if (filt->num_plugs == 0)
   {
      RARCH_ERR("No filter plugs found. Exiting...\n");
      return false;
   }

   filt->impl = softfilter_find_implementation(filt, name);
   if (!filt->impl)
   {
      RARCH_ERR("Could not find implementation.\n");
      return false;
   }

   userdata.conf = filt->conf;
   /* Index-specific configs take priority over ident-specific. */
   userdata.prefix[0] = key; 
   userdata.prefix[1] = filt->impl->short_ident;

   /* Simple assumptions. */
   filt->pix_fmt = in_pixel_format;
   input_fmts = filt->impl->query_input_formats();

   switch (in_pixel_format)
   {
      case RETRO_PIXEL_FORMAT_XRGB8888:
         input_fmt = SOFTFILTER_FMT_XRGB8888;
         break;
      case RETRO_PIXEL_FORMAT_RGB565:
         input_fmt = SOFTFILTER_FMT_RGB565;
         break;
      default:
         return false;
   }

   if (!(input_fmt & input_fmts))
   {
      RARCH_ERR("Softfilter does not support input format.\n");
      return false;
   }

   output_fmts = filt->impl->query_output_formats(input_fmt);
   /* If we have a match of input/output formats, use that. */
   if (output_fmts & input_fmt)
      filt->out_pix_fmt = in_pixel_format;
   else if (output_fmts & SOFTFILTER_FMT_XRGB8888)
      filt->out_pix_fmt = RETRO_PIXEL_FORMAT_XRGB8888;
   else if (output_fmts & SOFTFILTER_FMT_RGB565)
      filt->out_pix_fmt = RETRO_PIXEL_FORMAT_RGB565;
   else
   {
      RARCH_ERR("Did not find suitable output format for softfilter.\n");
      return false;
   }

   filt->max_width = max_width;
   filt->max_height = max_height;

   filt->impl_data = filt->impl->create(
         &softfilter_config, input_fmt, input_fmt, max_width, max_height,
         threads != RARCH_SOFTFILTER_THREADS_AUTO ? threads : 
         retro_get_cpu_cores(), cpu_features,
         &userdata);
   if (!filt->impl_data)
   {
      RARCH_ERR("Failed to create softfilter state.\n");
      return false;
   }

   threads = filt->impl->query_num_threads(filt->impl_data);
   if (!threads)
   {
      RARCH_ERR("Invalid number of threads.\n");
      return false;
   }

   filt->threads = threads;
   RARCH_LOG("Using %u threads for softfilter.\n", threads);

   filt->packets = (struct softfilter_work_packet*)
      calloc(threads, sizeof(*filt->packets));
   if (!filt->packets)
   {
      RARCH_ERR("Failed to allocate softfilter packets.\n");
      return false;
   }

#ifdef HAVE_THREADS
   filt->thread_data = (struct filter_thread_data*)
      calloc(threads, sizeof(*filt->thread_data));
   if (!filt->thread_data)
      return false;

   for (i = 0; i < threads; i++)
   {
      filt->thread_data[i].userdata = filt->impl_data;
      filt->thread_data[i].done = true;

      filt->thread_data[i].lock = slock_new();
      if (!filt->thread_data[i].lock)
         return false;
      filt->thread_data[i].cond = scond_new();
      if (!filt->thread_data[i].cond)
         return false;
      filt->thread_data[i].thread = sthread_create(
            filter_thread_loop, &filt->thread_data[i]);
      if (!filt->thread_data[i].thread)
         return false;
   }
#endif

   return true;
}
コード例 #29
0
ファイル: runloop.c プロジェクト: tarcisiogc/RetroArch
bool runloop_ctl(enum runloop_ctl_state state, void *data)
{

   switch (state)
   {
      case RUNLOOP_CTL_SHADER_DIR_DEINIT:
         shader_dir_free(&runloop_shader_dir);
         break;
      case RUNLOOP_CTL_SHADER_DIR_INIT:
         return shader_dir_init(&runloop_shader_dir);
      case RUNLOOP_CTL_SYSTEM_INFO_INIT:
         core_get_system_info(&runloop_system.info);

         if (!runloop_system.info.library_name)
            runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN);
         if (!runloop_system.info.library_version)
            runloop_system.info.library_version = "v0";

         video_driver_set_title_buf();

         strlcpy(runloop_system.valid_extensions,
               runloop_system.info.valid_extensions ?
               runloop_system.info.valid_extensions : DEFAULT_EXT,
               sizeof(runloop_system.valid_extensions));
         break;
      case RUNLOOP_CTL_GET_CORE_OPTION_SIZE:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            *idx = core_option_manager_size(runloop_core_options);
         }
         break;
      case RUNLOOP_CTL_HAS_CORE_OPTIONS:
         return runloop_core_options;
      case RUNLOOP_CTL_CORE_OPTIONS_LIST_GET:
         {
            core_option_manager_t **coreopts = (core_option_manager_t**)data;
            if (!coreopts)
               return false;
            *coreopts = runloop_core_options;
         }
         break;
      case RUNLOOP_CTL_SYSTEM_INFO_GET:
         {
            rarch_system_info_t **system = (rarch_system_info_t**)data;
            if (!system)
               return false;
            *system = &runloop_system;
         }
         break;
      case RUNLOOP_CTL_SYSTEM_INFO_FREE:

         /* No longer valid. */
         if (runloop_system.subsystem.data)
            free(runloop_system.subsystem.data);
         runloop_system.subsystem.data = NULL;
         runloop_system.subsystem.size = 0;
         
         if (runloop_system.ports.data)
            free(runloop_system.ports.data);
         runloop_system.ports.data = NULL;
         runloop_system.ports.size = 0;
         
         if (runloop_system.mmaps.descriptors)
            free((void *)runloop_system.mmaps.descriptors);
         runloop_system.mmaps.descriptors     = NULL;
         runloop_system.mmaps.num_descriptors = 0;
         
         runloop_key_event          = NULL;
         runloop_frontend_key_event = NULL;

         audio_driver_unset_callback();
         memset(&runloop_system, 0, sizeof(rarch_system_info_t));
         break;
      case RUNLOOP_CTL_SET_FRAME_TIME_LAST:
         runloop_frame_time_last_enable = true;
         break;
      case RUNLOOP_CTL_UNSET_FRAME_TIME_LAST:
         if (!runloop_ctl(RUNLOOP_CTL_IS_FRAME_TIME_LAST, NULL))
            return false;
         runloop_frame_time_last        = 0;
         runloop_frame_time_last_enable = false;
         break;
      case RUNLOOP_CTL_SET_OVERRIDES_ACTIVE:
         runloop_overrides_active = true;
         break;
      case RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE:
         runloop_overrides_active = false; 
         break;
      case RUNLOOP_CTL_IS_OVERRIDES_ACTIVE:
         return runloop_overrides_active;
      case RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE:
         runloop_game_options_active = true;
         break;
      case RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE:
         runloop_game_options_active = false;
         break;
      case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE:
         return runloop_game_options_active;
      case RUNLOOP_CTL_IS_FRAME_TIME_LAST:
         return runloop_frame_time_last_enable;
      case RUNLOOP_CTL_SET_FRAME_LIMIT:
         runloop_set_frame_limit = true;
         break;
      case RUNLOOP_CTL_UNSET_FRAME_LIMIT:
         runloop_set_frame_limit = false;
         break;
      case RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT:
         return runloop_set_frame_limit;
      case RUNLOOP_CTL_GET_PERFCNT:
         {
            bool **perfcnt = (bool**)data;
            if (!perfcnt)
               return false;
            *perfcnt = &runloop_perfcnt_enable;
         }
         break;
      case RUNLOOP_CTL_SET_PERFCNT_ENABLE:
         runloop_perfcnt_enable = true;
         break;
      case RUNLOOP_CTL_UNSET_PERFCNT_ENABLE:
         runloop_perfcnt_enable = false;
         break;
      case RUNLOOP_CTL_IS_PERFCNT_ENABLE:
         return runloop_perfcnt_enable;
      case RUNLOOP_CTL_SET_NONBLOCK_FORCED:
         runloop_force_nonblock = true;
         break;
      case RUNLOOP_CTL_UNSET_NONBLOCK_FORCED:
         runloop_force_nonblock = false;
         break;
      case RUNLOOP_CTL_IS_NONBLOCK_FORCED:
         return runloop_force_nonblock;
      case RUNLOOP_CTL_SET_FRAME_TIME:
         {
            const struct retro_frame_time_callback *info =
               (const struct retro_frame_time_callback*)data;
#ifdef HAVE_NETPLAY
            global_t *global = global_get_ptr();

            /* retro_run() will be called in very strange and
             * mysterious ways, have to disable it. */
            if (global->netplay.enable)
               return false;
#endif
            runloop_frame_time = *info;
         }
         break;
      case RUNLOOP_CTL_GET_WINDOWED_SCALE:
         {
            unsigned **scale = (unsigned**)data;
            if (!scale)
               return false;
            *scale       = (unsigned*)&runloop_pending_windowed_scale;
         }
         break;
      case RUNLOOP_CTL_SET_WINDOWED_SCALE:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            runloop_pending_windowed_scale = *idx;
         }
         break;
      case RUNLOOP_CTL_SET_LIBRETRO_PATH:
         {
            const char *fullpath = (const char*)data;
            if (!fullpath)
               return false;
            config_set_active_core_path(fullpath);
         }
         break;
      case RUNLOOP_CTL_CLEAR_CONTENT_PATH:
         *runloop_fullpath = '\0';
         break;
      case RUNLOOP_CTL_GET_CONTENT_PATH:
         {
            char **fullpath = (char**)data;
            if (!fullpath)
               return false;
            *fullpath       = (char*)runloop_fullpath;
         }
         break;
      case RUNLOOP_CTL_SET_CONTENT_PATH:
         {
            const char *fullpath = (const char*)data;
            if (!fullpath)
               return false;
            strlcpy(runloop_fullpath, fullpath, sizeof(runloop_fullpath));
         }
         break;
      case RUNLOOP_CTL_CLEAR_DEFAULT_SHADER_PRESET:
         *runloop_default_shader_preset = '\0';
         break;
      case RUNLOOP_CTL_GET_DEFAULT_SHADER_PRESET:
         {
            char **preset = (char**)data;
            if (!preset)
               return false;
            *preset       = (char*)runloop_default_shader_preset;
         }
         break;
      case RUNLOOP_CTL_SET_DEFAULT_SHADER_PRESET:
         {
            const char *preset = (const char*)data;
            if (!preset)
               return false;
            strlcpy(runloop_default_shader_preset, preset,
               sizeof(runloop_default_shader_preset));
         }
         break;
      case RUNLOOP_CTL_FRAME_TIME_FREE:
         memset(&runloop_frame_time, 0, sizeof(struct retro_frame_time_callback));
         runloop_frame_time_last           = 0;
         runloop_max_frames                = 0;
         break;
      case RUNLOOP_CTL_STATE_FREE:
         runloop_perfcnt_enable            = false;
         runloop_idle                      = false;
         runloop_paused                    = false;
         runloop_slowmotion                = false;
         runloop_frame_time_last_enable    = false;
         runloop_set_frame_limit           = false;
         runloop_overrides_active          = false;
         runloop_ctl(RUNLOOP_CTL_FRAME_TIME_FREE, NULL);
         break;
      case RUNLOOP_CTL_GLOBAL_FREE:
         {
            global_t *global = NULL;
            command_event(CMD_EVENT_TEMPORARY_CONTENT_DEINIT, NULL);
            command_event(CMD_EVENT_SUBSYSTEM_FULLPATHS_DEINIT, NULL);
            command_event(CMD_EVENT_RECORD_DEINIT, NULL);
            command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL);

            rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL);
            runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH,  NULL);
            runloop_overrides_active   = false;

            core_unset_input_descriptors();

            global = global_get_ptr();
            memset(global, 0, sizeof(struct global));
            config_free_state();
         }
         break;
      case RUNLOOP_CTL_CLEAR_STATE:
         driver_ctl(RARCH_DRIVER_CTL_DEINIT,  NULL);
         runloop_ctl(RUNLOOP_CTL_STATE_FREE,  NULL);
         runloop_ctl(RUNLOOP_CTL_GLOBAL_FREE, NULL);
         break;
      case RUNLOOP_CTL_SET_MAX_FRAMES:
         {
            unsigned *ptr = (unsigned*)data;
            if (!ptr)
               return false;
            runloop_max_frames = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_IDLE:
         return runloop_idle;
      case RUNLOOP_CTL_SET_IDLE:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_idle = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_SLOWMOTION:
         return runloop_slowmotion;
      case RUNLOOP_CTL_SET_SLOWMOTION:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_slowmotion = *ptr;
         }
         break;
      case RUNLOOP_CTL_SET_PAUSED:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_paused = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_PAUSED:
         return runloop_paused;
      case RUNLOOP_CTL_MSG_QUEUE_PULL:
         runloop_msg_queue_lock();
         {
            const char **ret = (const char**)data;
            if (!ret)
               return false;
            *ret = msg_queue_pull(runloop_msg_queue);
         }
         runloop_msg_queue_unlock();
         break;
      case RUNLOOP_CTL_MSG_QUEUE_FREE:
#ifdef HAVE_THREADS
         slock_free(_runloop_msg_queue_lock);
         _runloop_msg_queue_lock = NULL;
#endif
         break;
      case RUNLOOP_CTL_MSG_QUEUE_CLEAR:
         msg_queue_clear(runloop_msg_queue);
         break;
      case RUNLOOP_CTL_MSG_QUEUE_DEINIT:
         if (!runloop_msg_queue)
            return true;

         runloop_msg_queue_lock();

         msg_queue_free(runloop_msg_queue);

         runloop_msg_queue_unlock();
         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_FREE, NULL);

         runloop_msg_queue = NULL;
         break;
      case RUNLOOP_CTL_MSG_QUEUE_INIT:
         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL);
         runloop_msg_queue = msg_queue_new(8);
         retro_assert(runloop_msg_queue);

#ifdef HAVE_THREADS
         _runloop_msg_queue_lock = slock_new();
         retro_assert(_runloop_msg_queue_lock);
#endif
         break;
      case RUNLOOP_CTL_TASK_INIT:
         {
#ifdef HAVE_THREADS
            settings_t *settings = config_get_ptr();
            bool threaded_enable = settings->threaded_data_runloop_enable;
#else
            bool threaded_enable = false;
#endif
            task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL);
            task_queue_ctl(TASK_QUEUE_CTL_INIT, &threaded_enable);
         }
         break;
      case RUNLOOP_CTL_SET_CORE_SHUTDOWN:
         runloop_core_shutdown_initiated = true;
         break;
      case RUNLOOP_CTL_UNSET_CORE_SHUTDOWN:
         runloop_core_shutdown_initiated = false;
         break;
      case RUNLOOP_CTL_IS_CORE_SHUTDOWN:
         return runloop_core_shutdown_initiated;
      case RUNLOOP_CTL_SET_SHUTDOWN:
         runloop_shutdown_initiated = true;
         break;
      case RUNLOOP_CTL_UNSET_SHUTDOWN:
         runloop_shutdown_initiated = false;
         break;
      case RUNLOOP_CTL_IS_SHUTDOWN:
         return runloop_shutdown_initiated;
      case RUNLOOP_CTL_SET_EXEC:
         runloop_exec = true;
         break;
      case RUNLOOP_CTL_UNSET_EXEC:
         runloop_exec = false;
         break;
      case RUNLOOP_CTL_IS_EXEC:
         return runloop_exec;
      case RUNLOOP_CTL_DATA_DEINIT:
         task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL);
         break;
      case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED:
         if (!runloop_core_options)
            return false;
         return  core_option_manager_updated(runloop_core_options);
      case RUNLOOP_CTL_CORE_OPTION_PREV:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            core_option_manager_prev(runloop_core_options, *idx);
            if (ui_companion_is_on_foreground())
               ui_companion_driver_notify_refresh();
         }
         break;
      case RUNLOOP_CTL_CORE_OPTION_NEXT:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            core_option_manager_next(runloop_core_options, *idx);
            if (ui_companion_is_on_foreground())
               ui_companion_driver_notify_refresh();
         }
         break;
      case RUNLOOP_CTL_CORE_OPTIONS_GET:
         {
            struct retro_variable *var = (struct retro_variable*)data;

            if (!runloop_core_options || !var)
               return false;

            RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key);
            core_option_manager_get(runloop_core_options, var);
            RARCH_LOG("\t%s\n", var->value ? var->value : 
                  msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE));
         }
         break;
      case RUNLOOP_CTL_CORE_OPTIONS_INIT:
         {
            char *game_options_path           = NULL;
            bool ret                          = false;
            char buf[PATH_MAX_LENGTH]         = {0};
            global_t *global                  = global_get_ptr();
            settings_t *settings              = config_get_ptr();
            const char *options_path          = settings->path.core_options;
            const struct retro_variable *vars = 
               (const struct retro_variable*)data;

            if (string_is_empty(options_path) 
                  && !string_is_empty(global->path.config))
            {
               fill_pathname_resolve_relative(buf, global->path.config,
                     file_path_str(FILE_PATH_CORE_OPTIONS_CONFIG), sizeof(buf));
               options_path = buf;
            }


            if (settings->game_specific_options)
               ret = rarch_game_specific_options(&game_options_path);

            if(ret)
            {
               runloop_ctl(RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE, NULL);
               runloop_core_options = 
                  core_option_manager_new(game_options_path, vars);
               free(game_options_path);
            }
            else
            {
               runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL);
               runloop_core_options = 
                  core_option_manager_new(options_path, vars);
            }

         }
         break;
      case RUNLOOP_CTL_CORE_OPTIONS_FREE:
         if (runloop_core_options)
            core_option_manager_free(runloop_core_options);
         runloop_core_options          = NULL;
         break;
      case RUNLOOP_CTL_CORE_OPTIONS_DEINIT:
         {
            global_t *global                  = global_get_ptr();
            if (!runloop_core_options)
               return false;

            /* check if game options file was just created and flush
               to that file instead */
            if(global && !string_is_empty(global->path.core_options_path))
            {
               core_option_manager_flush_game_specific(runloop_core_options,
                     global->path.core_options_path);
               global->path.core_options_path[0] = '\0';
            }
            else
               core_option_manager_flush(runloop_core_options);

            if (runloop_ctl(RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE, NULL))
               runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL);

            runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_FREE, NULL);
         }
         break;
      case RUNLOOP_CTL_KEY_EVENT_GET:
         {
            retro_keyboard_event_t **key_event = 
               (retro_keyboard_event_t**)data;
            if (!key_event)
               return false;
            *key_event = &runloop_key_event;
         }
         break;
      case RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET:
         {
            retro_keyboard_event_t **key_event = 
               (retro_keyboard_event_t**)data;
            if (!key_event)
               return false;
            *key_event = &runloop_frontend_key_event;
         }
         break;
      case RUNLOOP_CTL_HTTPSERVER_INIT:
#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB)
         httpserver_init(8888);
#endif
         break;
      case RUNLOOP_CTL_HTTPSERVER_DESTROY:
#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB)
         httpserver_destroy();
#endif
         break;
      case RUNLOOP_CTL_NONE:
      default:
         break;
   }

   return true;
}
コード例 #30
0
ファイル: jack.c プロジェクト: Joonie86/RetroArch
static void *ja_init(const char *device, unsigned rate, unsigned latency)
{
   int i;
   const char **jports = NULL;
   char *dest_ports[2];
   size_t bufsize = 0;
   int parsed = 0;
   settings_t *settings = config_get_ptr();
   jack_t *jd = (jack_t*)calloc(1, sizeof(jack_t));

   if (!jd)
      return NULL;

   jd->cond      = scond_new();
   jd->cond_lock = slock_new();

   jd->client = jack_client_open("RetroArch", JackNullOption, NULL);
   if (jd->client == NULL)
      goto error;

   settings->audio.out_rate = jack_get_sample_rate(jd->client);

   jack_set_process_callback(jd->client, process_cb, jd);
   jack_on_shutdown(jd->client, shutdown_cb, jd);

   jd->ports[0] = jack_port_register(jd->client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
   jd->ports[1] = jack_port_register(jd->client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
   if (jd->ports[0] == NULL || jd->ports[1] == NULL)
   {
      RARCH_ERR("Failed to register ports.\n");
      goto error;
   }
   
   jports = jack_get_ports(jd->client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
   if (jports == NULL)
   {
      RARCH_ERR("Failed to get ports.\n");
      goto error;
   }

   bufsize = find_buffersize(jd, latency);
   jd->buffer_size = bufsize;

   RARCH_LOG("JACK: Internal buffer size: %d frames.\n", (int)(bufsize / sizeof(jack_default_audio_sample_t)));
   for (i = 0; i < 2; i++)
   {
      jd->buffer[i] = jack_ringbuffer_create(bufsize);
      if (jd->buffer[i] == NULL)
      {
         RARCH_ERR("Failed to create buffers.\n");
         goto error;
      }
   }

   parsed = parse_ports(dest_ports, jports);

   if (jack_activate(jd->client) < 0)
   {
      RARCH_ERR("Failed to activate Jack...\n");
      goto error;
   }

   for (i = 0; i < 2; i++)
   {
      if (jack_connect(jd->client, jack_port_name(jd->ports[i]), dest_ports[i]))
      {
         RARCH_ERR("Failed to connect to Jack port.\n");
         goto error;
      }
   }

   for (i = 0; i < parsed; i++)
      free(dest_ports[i]);
  
   jack_free(jports);
   return jd;

error:
   if (jports != NULL)
      jack_free(jports);
   return NULL;
}