Ejemplo n.º 1
0
/* gfx_gdi_init:
 */
static struct BITMAP *gfx_gdi_init(int w, int h, int v_w, int v_h, int color_depth)
{
   /* virtual screen are not supported */
   if ((v_w!=0 && v_w!=w) || (v_h!=0 && v_h!=h))
      return NULL;
   
   _enter_critical();

   gfx_gdi.w = w;
   gfx_gdi.h = h;

   if (adjust_window(w, h) != 0) {
      _TRACE(PREFIX_E "window size not supported.\n");
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported"));
      goto Error;
   }

   /* the last flag serves as an end of loop delimiter */
   gdi_dirty_lines = _AL_MALLOC_ATOMIC((h+1) * sizeof(char));
   ASSERT(gdi_dirty_lines);
   memset(gdi_dirty_lines, 0, (h+1) * sizeof(char));
   gdi_dirty_lines[h] = 1;

   /* create the screen surface */
   screen_surf = _AL_MALLOC_ATOMIC(w * h * BYTES_PER_PIXEL(color_depth));
   gdi_screen = _make_bitmap(w, h, (unsigned long)screen_surf, &gfx_gdi, color_depth, w * BYTES_PER_PIXEL(color_depth));
   gdi_screen->write_bank = gfx_gdi_write_bank; 
   _screen_vtable.acquire = gfx_gdi_lock;
   _screen_vtable.release = gfx_gdi_unlock;
   _screen_vtable.unwrite_bank = gfx_gdi_unwrite_bank; 

   /* create render timer */
   vsync_event = CreateEvent(NULL, FALSE, FALSE, NULL);
   install_int(render_proc, RENDER_DELAY);

   /* connect to the system driver */
   win_gfx_driver = &win_gfx_driver_gdi;

   /* set the default switching policy */
   set_display_switch_mode(SWITCH_PAUSE);

   /* grab input devices */
   win_grab_input();

   _exit_critical();

   return gdi_screen;

 Error:
   _exit_critical();

   gfx_gdi_exit(NULL);

   return NULL;
}
Ejemplo n.º 2
0
/* sys_directx_get_executable_name:
 *  Returns full path to the current executable.
 */
static void sys_directx_get_executable_name(char *output, int size)
{
    char *temp = _AL_MALLOC_ATOMIC(size);

    if (GetModuleFileName(allegro_inst, temp, size))
        do_uconvert(temp, U_ASCII, output, U_CURRENT, size);
    else
        usetc(output, 0);

    _AL_FREE(temp);
}
Ejemplo n.º 3
0
/* sys_directx_message:
 *  Displays a message.
 */
static void sys_directx_message(AL_CONST char *msg)
{
    char *tmp1 = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE);
    char tmp2[WND_TITLE_SIZE*2];
    HWND allegro_wnd = win_get_window();

    while ((ugetc(msg) == '\r') || (ugetc(msg) == '\n'))
        msg += uwidth(msg);

    MessageBoxW(allegro_wnd,
                (unsigned short *)uconvert(msg, U_CURRENT, tmp1, U_UNICODE, ALLEGRO_MESSAGE_SIZE),
                (unsigned short *)uconvert(wnd_title, U_ASCII, tmp2, U_UNICODE, sizeof(tmp2)),
                MB_OK);

    _AL_FREE(tmp1);
}
Ejemplo n.º 4
0
/* get_dib_from_bitmap_32:
 *  Creates a Windows device-independent bitmap (DIB) from an Allegro BITMAP.
 *  You have to free the memory allocated by this function.
 *
 *  This version always creates a 32-bit DIB.
 */
static BYTE *get_dib_from_bitmap_32(ALLEGRO_BITMAP *bitmap)
{
   int w, h;
   int x, y;
   int pitch;
   BYTE *pixels;
   BYTE *dst;

   w = al_get_bitmap_width(bitmap);
   h = al_get_bitmap_height(bitmap);
   pitch = w * 4;

   pixels = (BYTE *) _AL_MALLOC_ATOMIC(h * pitch);
   if (!pixels)
      return NULL;

   for (y = 0; y < h; y++) {
      dst = pixels + y * pitch;

      for (x = 0; x < w; x++) {
         ALLEGRO_COLOR col;
         unsigned char r, g, b, a;

         col = al_get_pixel(bitmap, x, y);
         al_unmap_rgba(col, &r, &g, &b, &a);

         /* BGR */
         dst[0] = b;
         dst[1] = g;
         dst[2] = r;
         dst[3] = a;

         dst += 4;
      }
   }

   return pixels;
}
Ejemplo n.º 5
0
/* Function: al_load_ogg_vorbis_f
 */
ALLEGRO_SAMPLE *al_load_ogg_vorbis_f(ALLEGRO_FILE* file)
{
   /* Note: decoding library returns floats.  I always return 16-bit (most
    * commonly supported).
    */
#ifdef ALLEGRO_LITTLE_ENDIAN
   const int endian = 0; /* 0 for Little-Endian, 1 for Big-Endian */
#else
   const int endian = 1; /* 0 for Little-Endian, 1 for Big-Endian */
#endif
   int word_size = 2; /* 1 = 8bit, 2 = 16-bit. nothing else */
   int signedness = 1; /* 0  for unsigned, 1 for signed */
   const int packet_size = 4096; /* suggestion for size to read at a time */
   OggVorbis_File vf;
   vorbis_info* vi;
   char *buffer;
   long pos;
   ALLEGRO_SAMPLE *sample;
   int channels;
   long rate;
   long total_samples;
   int bitstream;
   long total_size;
   AL_OV_DATA ov;

   if (file == NULL) {
      ALLEGRO_WARN("Audio file failed to open.\n");
      return NULL;
   }
   ov.file = file;
   if (ov_open_callbacks(&ov, &vf, NULL, 0, callbacks) < 0) {
      ALLEGRO_WARN("Audio file does not appear to be an Ogg bitstream.\n");
      al_fclose(file);
      return NULL;
   }

   vi = ov_info(&vf, -1);

   channels = vi->channels;
   rate = vi->rate;
   total_samples = ov_pcm_total(&vf, -1);
   bitstream = -1;
   total_size = total_samples * channels * word_size;

   ALLEGRO_DEBUG("channels %d\n", channels);
   ALLEGRO_DEBUG("word_size %d\n", word_size);
   ALLEGRO_DEBUG("rate %ld\n", rate);
   ALLEGRO_DEBUG("total_samples %ld\n", total_samples);
   ALLEGRO_DEBUG("total_size %ld\n", total_size);

   buffer = _AL_MALLOC_ATOMIC(total_size);
   if (!buffer) {
      al_fclose(file);
      return NULL;
   }

   pos = 0;
   while (pos < total_size) {
      /* XXX error handling */
#if !defined(ALLEGRO_GP2XWIZ) && !defined(ALLEGRO_IPHONE)
      long read = ov_read(&vf, buffer + pos, packet_size, endian, word_size,
         signedness, &bitstream);
#else
      (void)endian;
      (void)signedness;
      long read = ov_read(&vf, buffer + pos, packet_size, &bitstream);
#endif
      pos += read;
      if (read == 0)
         break;
   }

   ov_clear(&vf);

   sample = al_create_sample(buffer, total_samples, rate,
      _al_word_size_to_depth_conf(word_size),
      _al_count_to_channel_conf(channels), true);

   if (!sample) {
      _AL_FREE(buffer);
   }

   return sample;
}
Ejemplo n.º 6
0
/* _unix_read_os_type:
 *  Set the os_type variable to something sensible.
 */
void _unix_read_os_type(void)
{
   #ifdef ALLEGRO_HAVE_SYS_UTSNAME_H

      struct utsname utsn;
      char *tmpstr, *tmpstr2;
      size_t pos;
      
      uname(&utsn);

      /* fetch OS version and revision */
      tmpstr = _AL_MALLOC_ATOMIC(strlen(utsn.release)+1);
      _al_sane_strncpy(tmpstr, utsn.release, strlen(utsn.release)+1);
      tmpstr2 = NULL;

      for (pos = 0; pos <= strlen(utsn.release); pos++) {
         if (tmpstr[pos] == '.') {
	    tmpstr[pos] = '\0';
	    if (!tmpstr2)
	       tmpstr2 = tmpstr + pos + 1;
	 }
      }

      os_version = atoi(tmpstr);
      os_revision = atoi(tmpstr2);

      _AL_FREE(tmpstr);

      /* try to detect Unix systems we know of */
      if (!strcmp(utsn.sysname, "Linux")) {
	 os_type = OSTYPE_LINUX;
      }
      else if (!strcmp(utsn.sysname, "SunOS")) {
	 os_type = OSTYPE_SUNOS;
      }
      else if (!strcmp(utsn.sysname, "FreeBSD")) {
	 os_type = OSTYPE_FREEBSD;
      }
      else if (!strcmp(utsn.sysname, "NetBSD")) {
	 os_type = OSTYPE_NETBSD;
      }
      else if (!strcmp(utsn.sysname, "OpenBSD")) {
	 os_type = OSTYPE_OPENBSD;
      }
      else if ((!strcmp(utsn.sysname, "IRIX"))
	       || (!strcmp(utsn.sysname, "IRIX64"))) {
	 os_type = OSTYPE_IRIX;
      }
      else if (!strcmp(utsn.sysname, "Darwin")) {
	 os_type = OSTYPE_DARWIN;
      }
      else if (!strcmp(utsn.sysname, "QNX")) {
	 os_type = OSTYPE_QNX;
      }
      else {
	 os_type = OSTYPE_UNIX;     /* that's all we can say for now */
      }

   #else

      os_type = OSTYPE_UNIX;

   #endif
   
   os_multitasking = TRUE;
}
Ejemplo n.º 7
0
/* jack_init:
 *  JACK init routine.
 */
static int jack_init(int input, int voices)
{
   const char **ports;
   char tmp[128];

   if (!jack_detect(input))
      return -1;

   jack_bufsize = get_config_int("sound", "jack_buffer_size",
      jack_bufsize);

   if (jack_bufsize == -1)
      jack_bufsize = jack_get_buffer_size (jack_client);

   /* Those are already read in from the config file by Allegro. */
   jack_16bit = (_sound_bits == 16 ? 1 : 0);
   jack_stereo = (_sound_stereo ? 1 : 0);

   /* Let Allegro mix in its native unsigned format. */
   jack_signed = 0;

   jack_set_process_callback (jack_client, jack_process, NULL);

   output_left = jack_port_register (jack_client, jack_stereo ? "left" : "mono",
      JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);

   if (jack_stereo)
      output_right = jack_port_register (jack_client, "right",
         JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);

   jack_rate = jack_get_sample_rate (jack_client);

   jack_buffer = _AL_MALLOC_ATOMIC(jack_bufsize * (1 + jack_16bit) * (1 + jack_stereo));
   if (!jack_buffer) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
         "Cannot allocate audio buffer"));
      jack_exit (input);
      return -1;
   }

   digi_jack.voices = voices;

   if (_mixer_init(jack_bufsize *  (1 + jack_stereo), jack_rate,
      jack_stereo, jack_16bit, &digi_jack.voices)) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
         "Cannot init software mixer"));
      jack_exit (input);
      return -1;
   }

   _mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed);

   if (jack_activate (jack_client)) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
         "Cannot activate Jack client"));
      jack_exit (input);
      return 1;
   }

   /* Try to connect the ports. Failure to connect is not critical, since with
    * JACK, users may connect/disconnect ports anytime, without Allegro caring.
    */
   if ((ports = jack_get_ports (jack_client, NULL, NULL,
      JackPortIsPhysical|JackPortIsInput)) == NULL) {
      TRACE (PREFIX_I "Cannot find any physical playback ports");
   }

   if (ports) {
      if (ports[0]) {
	 if (jack_connect (jack_client, jack_port_name (output_left), ports[0]) == 0)
	    TRACE (PREFIX_I "Connected left playback port to %s", ports[0]);
      }
      if (jack_stereo && ports[1]) {
	 if (jack_connect (jack_client, jack_port_name (output_right), ports[1]) == 0)
	    TRACE (PREFIX_I "Connected right playback port to %s", ports[1]);
      }
      _AL_FREE (ports);
   }

   uszprintf(jack_desc, sizeof(jack_desc),
      get_config_text ("Jack, client '%s': %d bits, %s, %d bps, %s"),
      jack_client_name, jack_16bit ? 16 : 8,
      uconvert_ascii((jack_signed ? "signed" : "unsigned"), tmp),
      jack_rate, uconvert_ascii((jack_stereo ? "stereo" : "mono"), tmp));

   return 0;
}
Ejemplo n.º 8
0
static int
sndio_init(int input, int voices)
{
	char tmp1[128], tmp2[128];

	if (input) {
		digi_driver->rec_cap_bits = 16;
		digi_driver->rec_cap_stereo = TRUE;
		return 0;
	}

	if (open_sndio_device(0) != 0)
		return -1;

	sndio_play_bufdata = _AL_MALLOC_ATOMIC(sndio_play_bufsize);
	if (sndio_play_bufdata == 0) {
		ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
		    get_config_text("Can not allocate audio buffer"));
		sio_close(hdl);
		return -1;
	}

	sndio_realpos = sndio_playpos = 0;
	sio_onmove(hdl, movecb, NULL);

	sndio_volume = 127;
	sio_onvol(hdl, volcb, NULL);

	if (!sio_start(hdl)) {
		ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
		    get_config_text("Can not start sndio"));
		sio_close(hdl);
		return -1;
	}

	digi_sndio.voices = voices;

	/* first arg is total number of samples */
	if (_mixer_init(sndio_play_round * (_sound_stereo ? 2 : 1),
	    _sound_freq, _sound_stereo, ((_sound_bits == 16) ? 1 : 0),
	    &digi_sndio.voices) != 0) {
		ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
		    get_config_text("Can not init software mixer"));
		sio_close(hdl);
		return -1;
	}

	_mix_some_samples((uintptr_t) sndio_play_bufdata, 0, sndio_signed);

	/* Add audio interrupt.  */
	_unix_bg_man->register_func(sndio_update);

	uszprintf(sndio_desc, sizeof(sndio_desc),
	    get_config_text("%s: %d bits, %s, %d Hz, %s"),
	    "sndio device",
	    _sound_bits,
	    uconvert_ascii((sndio_signed ? "signed" : "unsigned"), tmp1),
	    _sound_freq,
	    uconvert_ascii((par.pchan == 2 ? "stereo" : "mono"), tmp2));

	digi_driver->desc = sndio_desc;

	return 0;
}
Ejemplo n.º 9
0
/* create_bitmap_ex
 *  Creates a new memory bitmap in the specified color_depth
 */
BITMAP *create_bitmap_ex(int color_depth, int width, int height)
{
   GFX_VTABLE *vtable;
   BITMAP *bitmap;
   int nr_pointers;
   int padding;
   int i;

   ASSERT(width >= 0);
   ASSERT(height > 0);
   ASSERT(system_driver);

   if (system_driver->create_bitmap)
      return system_driver->create_bitmap(color_depth, width, height);

   vtable = _get_vtable(color_depth);
   if (!vtable)
      return NULL;

   /* We need at least two pointers when drawing, otherwise we get crashes with
    * Electric Fence.  We think some of the assembly code assumes a second line
    * pointer is always available.
    */
   nr_pointers = MAX(2, height);
   bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * nr_pointers));
   if (!bitmap)
      return NULL;

   /* This avoids a crash for assembler code accessing the last pixel, as it
    * read 4 bytes instead of 3.
    */
   padding = (color_depth == 24) ? 1 : 0;

   bitmap->dat = _AL_MALLOC_ATOMIC(width * height * BYTES_PER_PIXEL(color_depth) + padding);
   if (!bitmap->dat) {
      _AL_FREE(bitmap);
      return NULL;
   }

   bitmap->w = bitmap->cr = width;
   bitmap->h = bitmap->cb = height;
   bitmap->clip = TRUE;
   bitmap->cl = bitmap->ct = 0;
   bitmap->vtable = vtable;
   bitmap->write_bank = bitmap->read_bank = _stub_bank_switch;
   bitmap->id = 0;
   bitmap->extra = NULL;
   bitmap->x_ofs = 0;
   bitmap->y_ofs = 0;
   bitmap->seg = _default_ds();

   if (height > 0) {
      bitmap->line[0] = bitmap->dat;
      for (i=1; i<height; i++)
         bitmap->line[i] = bitmap->line[i-1] + width * BYTES_PER_PIXEL(color_depth);
   }

   if (system_driver->created_bitmap)
      system_driver->created_bitmap(bitmap);

   return bitmap;
}
Ejemplo n.º 10
0
static int joy_init(void)
{
   JOYSTICK_INFO *j;
   AL_CONST char *device_name = NULL;
   char tmp[128], tmp1[128], tmp2[128];
   unsigned int raw_version;
   struct {
      unsigned char build, minor, major;
   } version;
   char num_axes, num_buttons;
   int throttle;
   int i, s, a, b;

   for (i = 0; i < MAX_JOYSTICKS; i++) {
      /* Check for a user override on the device to use. */
      uszprintf(tmp, sizeof(tmp), uconvert_ascii("joystick_device_%d", tmp1), i);
      device_name = get_config_string(uconvert_ascii("joystick", tmp1), tmp, NULL);

      /* Special case for the first joystick. */
      if (!device_name && (i == 0))
	 device_name = get_config_string(uconvert_ascii("joystick", tmp1),
					 uconvert_ascii("joystick_device", tmp2),
					 NULL);

      if (device_name) {
	 joy_fd[i] = open(uconvert_toascii(device_name, tmp), O_RDONLY|O_NONBLOCK);
	 if (joy_fd[i] == -1)
	    break;
      }
      else {
	 snprintf(tmp, sizeof(tmp), "/dev/input/js%d", i);
	 tmp[sizeof(tmp)-1] = 0;

	 joy_fd[i] = open(tmp, O_RDONLY|O_NONBLOCK);
	 if (joy_fd[i] == -1) {
	    snprintf(tmp, sizeof(tmp), "/dev/js%d", i);
	    tmp[sizeof(tmp)-1] = 0;

	    joy_fd[i] = open(tmp, O_RDONLY|O_NONBLOCK);
	    if (joy_fd[i] == -1) 
	       break;
	 }
      }

      if (ioctl(joy_fd[i], JSIOCGVERSION, &raw_version) < 0) {
         /* NOTE: IOCTL fails if the joystick API is version 0.x */
         uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Your Linux joystick API is version 0.x which is unsupported."));
         return -1; 
      }
      
      version.major = (raw_version & 0xFF0000) >> 16;
      version.minor = (raw_version & 0xFF00) >> 8;
      version.build = (raw_version & 0xFF);
      
      ioctl(joy_fd[i], JSIOCGAXES, &num_axes);
      ioctl(joy_fd[i], JSIOCGBUTTONS, &num_buttons);

      if (num_axes > TOTAL_JOYSTICK_AXES)
	 num_axes = TOTAL_JOYSTICK_AXES;

      if (num_buttons > MAX_JOYSTICK_BUTTONS)
	 num_buttons = MAX_JOYSTICK_BUTTONS;

      /* User is allowed to override our simple assumption of which
       * axis number (kernel) the throttle is located at. */
      uszprintf(tmp, sizeof(tmp), uconvert_ascii("throttle_axis_%d", tmp1), i);
      throttle = get_config_int(uconvert_ascii("joystick", tmp1), tmp, -1);
      if (throttle == -1) {
	 throttle = get_config_int(uconvert_ascii("joystick", tmp1), 
				   uconvert_ascii("throttle_axis", tmp2), -1);
      }

      /* Each pair of axes is assumed to make up a stick unless it 
       * is the sole remaining axis, or has been user specified, in 
       * which case it is a throttle. */

      j = &joy[i];
      j->flags = JOYFLAG_ANALOGUE;

      for (s = 0, a = 0; (s < MAX_JOYSTICK_STICKS) && (a < num_axes); s++) {
	 if ((a == throttle) || (a == num_axes-1)) {
	    /* One axis throttle */
	    j->stick[s].flags = JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED;
	    j->stick[s].num_axis = 1;
	    j->stick[s].axis[0].name = get_config_text("Throttle");
	    j->stick[s].name = ustrdup(j->stick[s].axis[0].name);
	    axis[i][a++] = &j->stick[s].axis[0];
	 }
	 else {
	    /* Two axis stick. */
	    j->stick[s].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED;
	    j->stick[s].num_axis = 2;
	    j->stick[s].axis[0].name = get_config_text("X");
	    j->stick[s].axis[1].name = get_config_text("Y");
	    j->stick[s].name = _AL_MALLOC_ATOMIC(32);
	    ASSERT(j->stick[s].name);
	    uszprintf((char *)j->stick[s].name, 32, get_config_text("Stick %d"), s+1);
	    axis[i][a++] = &j->stick[s].axis[0];
	    axis[i][a++] = &j->stick[s].axis[1];
	 }
      }

      j->num_sticks = s;

      for (b = 0; b < num_buttons; b++) {
	 j->button[b].name = _AL_MALLOC_ATOMIC(16);
	 ASSERT(j->button[b].name);
	 uszprintf((char *)j->button[b].name, 16, uconvert_ascii("%c", tmp), 'A' + b);
      }

      j->num_buttons = num_buttons;
   }

   num_joysticks = i;
   if (num_joysticks == 0) {
      uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to open %s: %s"),
		device_name ? device_name : uconvert_ascii("/dev/js0", tmp), ustrerror(errno));
      return -1;
   }

   return 0;
}
Ejemplo n.º 11
0
/* ljoy_get_joystick: [primary thread]
 *
 *  Returns the address of a ALLEGRO_JOYSTICK structure for the device
 *  number NUM.  The top-level joystick functions will not call this
 *  function if joystick number NUM was already gotten.  If the
 *  device cannot be opened, NULL is returned.
 */
static ALLEGRO_JOYSTICK *ljoy_get_joystick(int num)
{
   ALLEGRO_JOYSTICK_LINUX *joy;
   int fd;

   /* Try to open the device. */
   fd = try_open_joy_device(num);
   if (fd == -1)
      return NULL;

   /* Allocate a structure for the joystick. */
   joy = _AL_MALLOC(sizeof *joy);
   if (!joy) {
      close(fd);
      return NULL;
   }
   memset(joy, 0, sizeof *joy);

   /* Initialise the event source part of it. */
   _al_event_source_init(&joy->parent.es);

   /* Fill in the joystick information fields. */
   {
      /* char tmp[128], tmp1[128], tmp2[128]; */
      char num_axes;
      char num_buttons;
      int throttle;
      int s, a, b;

      ioctl(fd, JSIOCGAXES, &num_axes);
      ioctl(fd, JSIOCGBUTTONS, &num_buttons);

      if (num_axes > TOTAL_JOYSTICK_AXES)
         num_axes = TOTAL_JOYSTICK_AXES;

      if (num_buttons > _AL_MAX_JOYSTICK_BUTTONS)
         num_buttons = _AL_MAX_JOYSTICK_BUTTONS;

      /* XXX use configuration system when we get one */
      throttle = -1;
#if 0
      /* User is allowed to override our simple assumption of which
       * axis number (kernel) the throttle is located at. */
      snprintf(tmp, sizeof(tmp), "throttle_axis_%d", num);
      throttle = get_config_int("joystick", tmp, -1);
      if (throttle == -1) {
         throttle = get_config_int("joystick", 
                                   "throttle_axis", -1);
      }
#endif

      /* Each pair of axes is assumed to make up a stick unless it 
       * is the sole remaining axis, or has been user specified, in 
       * which case it is a throttle. */

      for (s = 0, a = 0;
           s < _AL_MAX_JOYSTICK_STICKS && a < num_axes;
           s++)
      {
         if ((a == throttle) || (a == num_axes-1)) {
            /* One axis throttle. */
            joy->parent.info.stick[s].flags = ALLEGRO_JOYFLAG_ANALOGUE;
            joy->parent.info.stick[s].num_axes = 1;
            joy->parent.info.stick[s].axis[0].name = "Throttle";
            char *name = joy->parent.info.stick[s].axis[0].name;
            joy->parent.info.stick[s].name = _AL_MALLOC_ATOMIC(strlen(name) + 1);
            strcpy(joy->parent.info.stick[s].name, name);
            joy->axis_mapping[a].stick = s;
            joy->axis_mapping[a].axis = 0;
            a++;
         }
         else {
            /* Two axis stick. */
            joy->parent.info.stick[s].flags = ALLEGRO_JOYFLAG_ANALOGUE;
            joy->parent.info.stick[s].num_axes = 2;
            joy->parent.info.stick[s].axis[0].name = "X";
            joy->parent.info.stick[s].axis[1].name = "Y";
            joy->parent.info.stick[s].name = _AL_MALLOC_ATOMIC (32);
            snprintf((char *)joy->parent.info.stick[s].name, 32, "Stick %d", s+1);
            joy->axis_mapping[a].stick = s;
            joy->axis_mapping[a].axis = 0;
            a++;
            joy->axis_mapping[a].stick = s;
            joy->axis_mapping[a].axis = 1;
            a++;
         }
      }

      joy->parent.info.num_sticks = s;

      /* Do the buttons. */

      for (b = 0; b < num_buttons; b++) {
         joy->parent.info.button[b].name = _AL_MALLOC_ATOMIC (32);
         snprintf((char *)joy->parent.info.button[b].name, 32, "B%d", b+1);
      }

      joy->parent.info.num_buttons = num_buttons;
   }

   joy->parent.num = num;

   joy->fd = fd;

   /* Register the joystick with the fdwatch subsystem.  */
   _al_unix_start_watching_fd(joy->fd, ljoy_process_new_data, joy);

   return (ALLEGRO_JOYSTICK *) joy;
}
Ejemplo n.º 12
0
/* alsa_init:
 *  ALSA init routine.
 */
static int alsa_init(int input, int voices)
{
   int ret = 0;
   char tmp1[128], tmp2[128];
   int format = 0;
   unsigned int numfrags = 0;
   snd_pcm_uframes_t fragsize;

   if (input) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
      return -1;
   }

   ALSA9_CHECK(snd_output_stdio_attach(&snd_output, stdout, 0));

   alsa_device = get_config_string(uconvert_ascii("sound", tmp1),
				   uconvert_ascii("alsa_device", tmp2),
				   alsa_device);

   alsa_mixer_device = get_config_string(uconvert_ascii("sound", tmp1),
				   uconvert_ascii("alsa_mixer_device", tmp2),
				   alsa_mixer_device);

   fragsize = get_config_int(uconvert_ascii("sound", tmp1),
			     uconvert_ascii("alsa_fragsize", tmp2), 0);

   numfrags = get_config_int(uconvert_ascii("sound", tmp1),
			     uconvert_ascii("alsa_numfrags", tmp2),
			     ALSA_DEFAULT_NUMFRAGS);

   ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
   if (ret < 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device"));
      return -1;
   }

   snd_mixer_open(&alsa_mixer, 0);

   if (alsa_mixer
       && snd_mixer_attach(alsa_mixer, alsa_mixer_device) >= 0
       && snd_mixer_selem_register (alsa_mixer, NULL, NULL) >= 0
       && snd_mixer_load(alsa_mixer) >= 0) {
      const char *alsa_mixer_elem_name = get_config_string(uconvert_ascii("sound", tmp1),
							   uconvert_ascii("alsa_mixer_elem", tmp2),
							   "PCM");

      alsa_mixer_elem = snd_mixer_first_elem(alsa_mixer);

      while (alsa_mixer_elem) {
	 const char *name = snd_mixer_selem_get_name(alsa_mixer_elem);

	 if (strcasecmp(name, alsa_mixer_elem_name) == 0) {
	    snd_mixer_selem_get_playback_volume_range(alsa_mixer_elem, &alsa_mixer_elem_min, &alsa_mixer_elem_max);
	    alsa_mixer_allegro_ratio = (double) (alsa_mixer_elem_max - alsa_mixer_elem_min) / (double) 255;
	    break;
	 }

	 alsa_mixer_elem = snd_mixer_elem_next(alsa_mixer_elem);
      }
   }

   /* Set format variables. */
   alsa_bits = (_sound_bits == 8) ? 8 : 16;
   alsa_stereo = (_sound_stereo) ? 1 : 0;
   alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100;
   alsa_signed = 0;

   format = ((alsa_bits == 16) ? SND_PCM_FORMAT_U16_NE : SND_PCM_FORMAT_U8);

   switch (format) {

      case SND_PCM_FORMAT_U8:
	 alsa_bits = 8;
	 break;

      case SND_PCM_FORMAT_U16_NE:
	 if (sizeof(short) != 2) {
	    ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
	    goto Error;
	 }
	 break;

      default:
	 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
	 goto Error;
   }

   alsa_sample_size = (alsa_bits / 8) * (alsa_stereo ? 2 : 1);

   if (fragsize == 0) {
      unsigned int size = alsa_rate * ALSA_DEFAULT_BUFFER_MS / 1000 / numfrags;
      fragsize = 1;
      while (fragsize < size)
	 fragsize <<= 1;
   }

   snd_pcm_hw_params_malloc(&hwparams);
   snd_pcm_sw_params_malloc(&swparams);

   ALSA9_CHECK(snd_pcm_hw_params_any(pcm_handle, hwparams));
   ALSA9_CHECK(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED));
   ALSA9_CHECK(snd_pcm_hw_params_set_format(pcm_handle, hwparams, format));
   ALSA9_CHECK(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, alsa_stereo + 1));

   ALSA9_CHECK(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &alsa_rate, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &fragsize, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &numfrags, NULL)); 

   ALSA9_CHECK(snd_pcm_hw_params(pcm_handle, hwparams));

   ALSA9_CHECK(snd_pcm_hw_params_get_period_size(hwparams, &alsa_bufsize, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_get_periods(hwparams, &alsa_fragments, NULL));

   TRACE (PREFIX_I "alsa_bufsize = %ld, alsa_fragments = %d\n", alsa_bufsize, alsa_fragments);

   ALSA9_CHECK(snd_pcm_sw_params_current(pcm_handle, swparams));
   ALSA9_CHECK(snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, alsa_bufsize));
   ALSA9_CHECK(snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, fragsize));
   ALSA9_CHECK(snd_pcm_sw_params_set_xfer_align(pcm_handle, swparams, 1));
   ALSA9_CHECK(snd_pcm_sw_params(pcm_handle, swparams));

   /* Allocate mixing buffer. */
   alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize * alsa_sample_size);
   if (!alsa_bufdata) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
      goto Error;
   }

   /* Initialise mixer. */
   digi_alsa.voices = voices;

   if (_mixer_init(alsa_bufsize * (alsa_stereo ? 2 : 1), alsa_rate,
		   alsa_stereo, ((alsa_bits == 16) ? 1 : 0),
		   &digi_alsa.voices) != 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
      goto Error;
   }

   snd_pcm_prepare(pcm_handle);
   pdc = snd_pcm_poll_descriptors_count (pcm_handle);
   if (pdc <= 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Invalid poll descriptors count"));
      goto Error;
   }

   ufds = _AL_MALLOC(sizeof(struct pollfd) * pdc);
   if (ufds == NULL) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory for poll descriptors"));
      goto Error;
   }
   ALSA9_CHECK(snd_pcm_poll_descriptors(pcm_handle, ufds, pdc));

   poll_next = 0;

   _mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed);

   /* Add audio interrupt. */
   _unix_bg_man->register_func(alsa_update);

   uszprintf(alsa_desc, sizeof(alsa_desc),
	     get_config_text
	     ("Alsa 0.9, Device '%s': %d bits, %s, %d bps, %s"),
	     alsa_device, alsa_bits,
	     uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1),
	     alsa_rate, uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2));

   digi_driver->desc = alsa_desc;
   return 0;

 Error:
   if (pcm_handle) {
      snd_pcm_close(pcm_handle);
      pcm_handle = NULL;
   }

   return -1;
}