improved zeemote driver
authorJavier S. Pedro <maemo@javispedro.com>
Sat, 20 Mar 2010 16:57:30 +0000 (17:57 +0100)
committerJavier S. Pedro <maemo@javispedro.com>
Sat, 20 Mar 2010 16:57:30 +0000 (17:57 +0100)
platform/osso.cpp
platform/zeemote.cpp

index a6c9da1..41b1b08 100644 (file)
@@ -41,6 +41,7 @@ static void loadSafeKeymap();
 static void loadPlayer1Keymap(GConfClient* gcc);
 static void loadPlayer2Keymap(GConfClient* gcc);
 
+/** The dbus application service callback. Usually called by the launcher only. */
 static gint ossoAppCallback(const gchar *interface, const gchar *method,
   GArray *arguments, gpointer data, osso_rpc_t *retval)
 {
index 6760af5..a6b85a7 100644 (file)
@@ -27,9 +27,13 @@ static const unsigned short zeemote_mask[] =
        SNES_A_MASK, SNES_B_MASK, SNES_X_MASK, SNES_Y_MASK 
 };
 
-static zeemote_t *zeemote;
-static uint32 prev_buttons;
-static int player;
+typedef struct zeemote_player {
+       /** Pointer to zeemote_t struct. If NULL, zeemote was not enabled for this player. */
+       zeemote_t *zeemote;
+       uint32 prev_buttons;
+} zeemote_player_t;
+
+static zeemote_player_t players[2] = { {0, 0}, {0, 0} };
 
 void ZeeInit()
 {
@@ -39,26 +43,22 @@ void ZeeInit()
        /* Since Zeemote means GConf, we can read our own configuration from it */
        GConfClient *gcc = gconf_client_get_default();
 
-       /* Check which player (if any) enabled Zeemote */
-       player = 0;
-       /* Player 1? */
+       /* Check which players (if any) enabled Zeemote */
        gchar key[kGConfPlayerPathBufferLen];
-       gchar *relKey = key + sprintf(key, kGConfPlayerPath, 1);
+       gchar *relKey;
+       bool enabled[2];
+
+       /* Player 1? */
+       relKey = key + sprintf(key, kGConfPlayerPath, 1);
        strcpy(relKey, kGConfPlayerZeemoteEnable);
-       if (gconf_client_get_bool(gcc, key, NULL)) {
-               player = 1;
-       } else {
-               /* Player 2? */
-               relKey = key + sprintf(key, kGConfPlayerPath, 2);
-               strcpy(relKey, kGConfPlayerZeemoteEnable);
-               if (gconf_client_get_bool(gcc, key, NULL)) {
-                       player = 2;
-               }
-       }
+       enabled[0] = gconf_client_get_bool(gcc, key, NULL);
 
-       if (player) {
-               printf("Zeemote: Enabled for player %d\n", player);
-       } else {
+       /* Player 2? */
+       relKey = key + sprintf(key, kGConfPlayerPath, 2);
+       strcpy(relKey, kGConfPlayerZeemoteEnable);
+       enabled[1] = gconf_client_get_bool(gcc, key, NULL);
+
+       if (!enabled[0] && !enabled[1]) {
                /* No player wanted a zeemote! */
                return;
        }
@@ -70,20 +70,48 @@ void ZeeInit()
        zeemote_scan_result_t *scan_result = 
                zeemote_get_scan_results_from_gconf();
 
-       /* if devices are configured use the first one in the list as this */
-       /* is supposed to be a single player game */
-       if(scan_result && scan_result->number_of_devices > 0) {
-               zeemote = zeemote_connect(&scan_result->device[0].bdaddr);
+       if (!scan_result) {
+               fprintf(stderr, "Zeemote: No scan results\n");
+       }
+
+       /* If we found a zeemote, assign it to the first player. If we found
+        * two zeemotes, assign the first found one to the first player, etc. */
+       /* Since the order comes from gconf, the user could potentially change
+          it */
+       if (enabled[0] && scan_result->number_of_devices > 0) {
+               players[0].zeemote =
+                       zeemote_connect(&scan_result->device[0].bdaddr);
+               if (!players[0].zeemote) {
+                       fprintf(stderr, "Zeemote: Failed to connect for player %d", 1);
+               }
+       }
+       if (enabled[1] && scan_result->number_of_devices > 1) {
+               players[1].zeemote =
+                       zeemote_connect(&scan_result->device[1].bdaddr);
+               if (!players[1].zeemote) {
+                       fprintf(stderr, "Zeemote: Failed to connect for player %d", 2);
+               }
+       }
+
+       if (players[0].zeemote && players[1].zeemote) {
+               printf("Zeemote: enabled for two players\n");
+       } else if (players[0].zeemote) {
+               printf("Zeemote: enabled for player %d\n", 1);
+       } else if (players[1].zeemote) {
+               printf("Zeemote: enabled for player %d\n", 2);
+       } else {
+               printf("Zeemote: disabled because of error\n");
        }
 }
 
-void ZeeRead(uint32* joypads)
+static void read_for_player(zeemote_player_t *player, uint32 *joypad)
 {
-       if (!zeemote) return;
+       if (!player->zeemote) return;
 
-       zeemote_state_t *state = zeemote_get_state(zeemote);
+       zeemote_state_t *state = zeemote_get_state(player->zeemote);
        if (!state) return; // Some error
-       if (state->state != ZEEMOTE_STATE_CONNECTED) return; // Not connected
+        // Zeemote was disconnected
+       if (state->state != ZEEMOTE_STATE_CONNECTED) return;
 
        uint32 buttons = 0;
        int i;
@@ -99,22 +127,37 @@ void ZeeRead(uint32* joypads)
        if (state->axis[0] >  ZEEMOTE_LIMIT) buttons |= SNES_RIGHT_MASK;
        if (state->axis[1] < -ZEEMOTE_LIMIT) buttons |= SNES_UP_MASK;
        if (state->axis[1] >  ZEEMOTE_LIMIT) buttons |= SNES_DOWN_MASK;
+
+       /* check which actual buttons were pressed or released */
+       uint32 buttons_changed = buttons ^ player->prev_buttons;
+       uint32 buttons_pressed = buttons_changed & buttons;
+       uint32 buttons_released = buttons_changed & player->prev_buttons;
+
        /* prevent device screensaver when zeemote state changes */
-       if (buttons != prev_buttons) 
+       if (buttons_changed)
        {
                osso_display_blanking_pause(ossoContext);
-               prev_buttons = buttons;
+               player->prev_buttons = buttons;
        }
 
-       joypads[player-1] |= buttons;
+       *joypad = (*joypad & ~buttons_released) | buttons_pressed;
+}
+
+void ZeeRead(uint32* joypads)
+{
+       read_for_player(&players[0], &joypads[0]);
+       read_for_player(&players[1], &joypads[1]);
 }
 
 void ZeeQuit()
 {
-       if (zeemote) {
-               zeemote_disconnect(zeemote);
-               zeemote = 0;
+       if (players[0].zeemote) {
+               zeemote_disconnect(players[0].zeemote);
+               players[0].zeemote = 0;
+       }
+       if (players[1].zeemote) {
+               zeemote_disconnect(players[1].zeemote);
+               players[1].zeemote = 0;
        }
 }