From a79a0c3fb812efac3370c6ed73d37bb8fd1d318e Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sat, 4 Dec 2010 15:25:15 +0100 Subject: Rewrite input processing --- Makefile | 3 +- src/main.c | 27 +----- src/settings.c | 25 ++---- src/settings.h | 3 +- src/ui_act.c | 258 ++++++++++++++++++++---------------------------------- src/ui_act.h | 7 +- src/ui_dispatch.c | 71 +++++++++++++++ src/ui_dispatch.h | 105 ++++++++++++++++++++++ 8 files changed, 295 insertions(+), 204 deletions(-) create mode 100644 src/ui_dispatch.c create mode 100644 src/ui_dispatch.h diff --git a/Makefile b/Makefile index c600272..632ad00 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,8 @@ PIANOBAR_SRC=\ ${PIANOBAR_DIR}/terminal.c \ ${PIANOBAR_DIR}/ui_act.c \ ${PIANOBAR_DIR}/ui.c \ - ${PIANOBAR_DIR}/ui_readline.c + ${PIANOBAR_DIR}/ui_readline.c \ + ${PIANOBAR_DIR}/ui_dispatch.c PIANOBAR_HDR=\ ${PIANOBAR_DIR}/player.h \ ${PIANOBAR_DIR}/settings.h \ diff --git a/src/main.c b/src/main.c index 412faed..3104898 100644 --- a/src/main.c +++ b/src/main.c @@ -50,11 +50,9 @@ THE SOFTWARE. #include "terminal.h" #include "config.h" #include "ui.h" -#include "ui_act.h" +#include "ui_dispatch.h" #include "ui_readline.h" -typedef void (*BarKeyShortcutFunc_t) (BarApp_t *app); - /* copy proxy settings to waitress handle */ static void BarMainLoadProxy (const BarSettings_t *settings, @@ -154,26 +152,9 @@ static void BarMainHandleUserInput (BarApp_t *app) { char buf[2]; if (BarReadline (buf, sizeof (buf), NULL, &app->input, BAR_RL_FULLRETURN | BAR_RL_NOECHO, 1) > 0) { - for (size_t i = 0; i < BAR_KS_COUNT; i++) { - if (app->settings.keys[i] != BAR_KS_DISABLED && - app->settings.keys[i] == buf[0]) { - static const BarKeyShortcutFunc_t idToF[] = {BarUiActHelp, - BarUiActLoveSong, BarUiActBanSong, - BarUiActAddMusic, BarUiActCreateStation, - BarUiActDeleteStation, BarUiActExplain, - BarUiActStationFromGenre, BarUiActHistory, - BarUiActSongInfo, BarUiActAddSharedStation, - BarUiActMoveSong, BarUiActSkipSong, BarUiActPause, - BarUiActQuit, BarUiActRenameStation, - BarUiActSelectStation, BarUiActTempBanSong, - BarUiActPrintUpcoming, BarUiActSelectQuickMix, - BarUiActDebug, BarUiActBookmark, BarUiActVolDown, - BarUiActVolUp}; - idToF[i] (app); - break; - } - } /* end for */ - } /* end if */ + BarUiDispatch (app, buf[0], app->curStation, app->playlist, true, + BAR_DC_GLOBAL); + } } /* append current song to history list and move to the next song diff --git a/src/settings.c b/src/settings.c index a7a26a6..dddc05c 100644 --- a/src/settings.c +++ b/src/settings.c @@ -30,9 +30,11 @@ THE SOFTWARE. #include #include #include +#include #include "settings.h" #include "config.h" +#include "ui_dispatch.h" #define streq(a, b) (strcmp (a, b) == 0) @@ -93,20 +95,9 @@ void BarSettingsDestroy (BarSettings_t *settings) { void BarSettingsRead (BarSettings_t *settings) { char configfile[PATH_MAX], key[256], val[256]; FILE *configfd; - /* _must_ have same order as in BarKeyShortcutId_t */ - static const char defaultKeys[] = {'?', '+', '-', 'a', 'c', 'd', 'e', 'g', - 'h', 'i', 'j', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'x', '$', - 'b', '(', ')', - }; - static const char *shortcutFileKeys[] = { - "act_help", "act_songlove", "act_songban", "act_stationaddmusic", - "act_stationcreate", "act_stationdelete", "act_songexplain", - "act_stationaddbygenre", "act_history", "act_songinfo", - "act_addshared", "act_songmove", "act_songnext", "act_songpause", - "act_quit", "act_stationrename", "act_stationchange", - "act_songtired", "act_upcoming", "act_stationselectquickmix", - "act_debug", "act_bookmark", "act_voldown", "act_volup", - }; + + assert (sizeof (settings->keys) / sizeof (*settings->keys) == + sizeof (dispatchActions) / sizeof (*dispatchActions)); /* apply defaults */ #ifdef ENABLE_FAAD @@ -119,9 +110,11 @@ void BarSettingsRead (BarSettings_t *settings) { settings->history = 5; settings->volume = 0; settings->sortOrder = BAR_SORT_NAME_AZ; - memcpy (settings->keys, defaultKeys, sizeof (defaultKeys)); settings->loveIcon = strdup ("<3"); settings->banIcon = strdup ("keys[i] = dispatchActions[i].defaultKey; + } BarGetXdgConfigDir (PACKAGE "/config", configfile, sizeof (configfile)); if ((configfd = fopen (configfile, "r")) == NULL) { @@ -149,7 +142,7 @@ void BarSettingsRead (BarSettings_t *settings) { size_t i; /* keyboard shortcuts */ for (i = 0; i < BAR_KS_COUNT; i++) { - if (streq (shortcutFileKeys[i], key)) { + if (streq (dispatchActions[i].configKey, key)) { if (streq (val, "disabled")) { settings->keys[i] = BAR_KS_DISABLED; } else { diff --git a/src/settings.h b/src/settings.h index f529a81..58ff3d1 100644 --- a/src/settings.h +++ b/src/settings.h @@ -27,8 +27,7 @@ THE SOFTWARE. #include #include -/* keep in mind that you have to update several arrays in main.c/ui_act.c too, - * if you're adding new shortcuts */ +/* update structure in ui_dispatch.h if you add shortcuts here */ typedef enum { BAR_KS_HELP = 0, BAR_KS_LOVE = 1, diff --git a/src/ui_act.c b/src/ui_act.c index f8c9879..a57cb01 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -26,18 +26,11 @@ THE SOFTWARE. #include #include #include +#include #include "ui.h" -#include "ui_act.h" #include "ui_readline.h" - -#define RETURN_IF_NO_STATION if (app->curStation == NULL) { \ - BarUiMsg (MSG_ERR, "No station selected.\n"); \ - return; } - -#define RETURN_IF_NO_SONG if (app->curStation == NULL || app->playlist == NULL) { \ - BarUiMsg (MSG_ERR, "No song playing.\n"); \ - return; } +#include "ui_dispatch.h" /* standard eventcmd call */ @@ -54,6 +47,8 @@ THE SOFTWARE. * @param player handle */ static inline void BarUiDoSkipSong (struct audioPlayer *player) { + assert (player != NULL); + player->doQuit = 1; pthread_mutex_unlock (&player->pauseMutex); } @@ -67,6 +62,8 @@ static int BarTransformIfShared (BarApp_t *app, PianoStation_t *station) { PianoReturn_t pRet; WaitressReturn_t wRet; + assert (station != NULL); + /* shared stations must be transformed */ if (!station->isCreator) { BarUiMsg (MSG_INFO, "Transforming station... "); @@ -81,38 +78,13 @@ static int BarTransformIfShared (BarApp_t *app, PianoStation_t *station) { /* print current shortcut configuration */ BarUiActCallback(BarUiActHelp) { - static const char *idToDesc[] = { - NULL, - "love current song", - "ban current song", - "add music to current station", - "create new station", - "delete current station", - "explain why this song is played", - "add genre station", - "song history", - "print information about current song/station", - "add shared station", - "move song to different station", - "next song", - "pause/continue", - "quit", - "rename current station", - "change station", - "tired (ban song for 1 month)", - "upcoming songs", - "select quickmix stations", - NULL, - "bookmark song/artist", - "decrease volume", - "increase volume", - }; - size_t i; - BarUiMsg (MSG_NONE, "\r"); - for (i = 0; i < BAR_KS_COUNT; i++) { - if (idToDesc[i] != NULL && app->settings.keys[i] != BAR_KS_DISABLED) { - BarUiMsg (MSG_LIST, "%c %s\n", app->settings.keys[i], idToDesc[i]); + for (size_t i = 0; i < BAR_KS_COUNT; i++) { + if (dispatchActions[i].helpText != NULL && + (context & dispatchActions[i].context) == dispatchActions[i].context && + app->settings.keys[i] != BAR_KS_DISABLED) { + BarUiMsg (MSG_LIST, "%c %s\n", app->settings.keys[i], + dispatchActions[i].helpText); } } } @@ -124,14 +96,14 @@ BarUiActCallback(BarUiActAddMusic) { WaitressReturn_t wRet; PianoRequestDataAddSeed_t reqData; - RETURN_IF_NO_STATION; + assert (selStation != NULL); reqData.musicId = BarUiSelectMusicId (app, app->playlist->musicId); if (reqData.musicId != NULL) { - if (!BarTransformIfShared (app, app->curStation)) { + if (!BarTransformIfShared (app, selStation)) { return; } - reqData.station = app->curStation; + reqData.station = selStation; BarUiMsg (MSG_INFO, "Adding music to station... "); BarUiActDefaultPianoCall (PIANO_REQUEST_ADD_SEED, &reqData); @@ -148,18 +120,20 @@ BarUiActCallback(BarUiActBanSong) { PianoReturn_t pRet; WaitressReturn_t wRet; - RETURN_IF_NO_SONG; + assert (selStation != NULL); + assert (selSong != NULL); - if (!BarTransformIfShared (app, app->curStation)) { + if (!BarTransformIfShared (app, selStation)) { return; } PianoRequestDataRateSong_t reqData; - reqData.song = app->playlist; + reqData.song = selSong; reqData.rating = PIANO_RATE_BAN; BarUiMsg (MSG_INFO, "Banning song... "); - if (BarUiActDefaultPianoCall (PIANO_REQUEST_RATE_SONG, &reqData)) { + if (BarUiActDefaultPianoCall (PIANO_REQUEST_RATE_SONG, &reqData) && + selSong == app->playlist) { BarUiDoSkipSong (&app->player); } BarUiActDefaultEventcmd ("songban"); @@ -207,14 +181,14 @@ BarUiActCallback(BarUiActDeleteStation) { PianoReturn_t pRet; WaitressReturn_t wRet; - RETURN_IF_NO_STATION; + assert (selStation != NULL); BarUiMsg (MSG_QUESTION, "Really delete \"%s\"? [yN] ", app->curStation->name); if (BarReadlineYesNo (false, &app->input)) { BarUiMsg (MSG_INFO, "Deleting station... "); if (BarUiActDefaultPianoCall (PIANO_REQUEST_DELETE_STATION, - app->curStation)) { + selStation) && selStation == app->curStation) { BarUiDoSkipSong (&app->player); PianoDestroyPlaylist (app->playlist); app->playlist = NULL; @@ -231,9 +205,9 @@ BarUiActCallback(BarUiActExplain) { WaitressReturn_t wRet; PianoRequestDataExplain_t reqData; - RETURN_IF_NO_STATION; + assert (selSong != NULL); - reqData.song = app->playlist; + reqData.song = selSong; BarUiMsg (MSG_INFO, "Receiving explanation... "); if (BarUiActDefaultPianoCall (PIANO_REQUEST_EXPLAIN, &reqData)) { @@ -253,20 +227,21 @@ BarUiActCallback(BarUiActStationFromGenre) { /* print verbose song information */ BarUiActCallback(BarUiActSongInfo) { - RETURN_IF_NO_SONG; + assert (selStation != NULL); + assert (selSong != NULL); - BarUiPrintStation (app->curStation); + BarUiPrintStation (selStation); /* print real station if quickmix */ - BarUiPrintSong (&app->settings, app->playlist, - app->curStation->isQuickMix ? - PianoFindStationById (app->ph.stations, app->playlist->stationId) : + BarUiPrintSong (&app->settings, selSong, + selStation->isQuickMix ? + PianoFindStationById (app->ph.stations, selSong->stationId) : NULL); } /* print some debugging information */ BarUiActCallback(BarUiActDebug) { - RETURN_IF_NO_SONG; + assert (selSong != NULL); /* print debug-alike infos */ BarUiMsg (MSG_NONE, @@ -283,15 +258,19 @@ BarUiActCallback(BarUiActDebug) { "testStrategy:\t%i\n" "title:\t%s\n" "userSeed:\t%s\n", - app->playlist->album, app->playlist->artist, - app->playlist->audioFormat, - app->playlist->audioUrl, - app->playlist->coverArt, - app->playlist->fileGain, - app->playlist->musicId, app->playlist->rating, - app->playlist->songType, app->playlist->stationId, - app->playlist->testStrategy, app->playlist->title, - app->playlist->userSeed); + selSong->album, + selSong->artist, + selSong->audioFormat, + selSong->audioUrl, + selSong->coverArt, + selSong->fileGain, + selSong->musicId, + selSong->rating, + selSong->songType, + selSong->stationId, + selSong->testStrategy, + selSong->title, + selSong->userSeed); } /* rate current song @@ -300,14 +279,15 @@ BarUiActCallback(BarUiActLoveSong) { PianoReturn_t pRet; WaitressReturn_t wRet; - RETURN_IF_NO_SONG; + assert (selStation != NULL); + assert (selSong != NULL); - if (!BarTransformIfShared (app, app->curStation)) { + if (!BarTransformIfShared (app, selStation)) { return; } PianoRequestDataRateSong_t reqData; - reqData.song = app->playlist; + reqData.song = selSong; reqData.rating = PIANO_RATE_LOVE; BarUiMsg (MSG_INFO, "Loving song... "); @@ -328,9 +308,9 @@ BarUiActCallback(BarUiActMoveSong) { WaitressReturn_t wRet; PianoRequestDataMoveSong_t reqData; - reqData.step = 0; + assert (selSong != NULL); - RETURN_IF_NO_SONG; + reqData.step = 0; reqData.to = BarUiSelectStation (&app->ph, "Move song to station: ", app->settings.sortOrder, &app->input); @@ -338,7 +318,7 @@ BarUiActCallback(BarUiActMoveSong) { /* find original station (just is case we're playing a quickmix * station) */ reqData.from = PianoFindStationById (app->ph.stations, - app->playlist->stationId); + selSong->stationId); if (reqData.from == NULL) { BarUiMsg (MSG_ERR, "Station not found\n"); return; @@ -349,8 +329,9 @@ BarUiActCallback(BarUiActMoveSong) { return; } BarUiMsg (MSG_INFO, "Moving song to \"%s\"... ", reqData.to->name); - reqData.song = app->playlist; - if (BarUiActDefaultPianoCall (PIANO_REQUEST_MOVE_SONG, &reqData)) { + reqData.song = selSong; + if (BarUiActDefaultPianoCall (PIANO_REQUEST_MOVE_SONG, &reqData) && + selSong == app->playlist) { BarUiDoSkipSong (&app->player); } BarUiActDefaultEventcmd ("songmove"); @@ -373,16 +354,16 @@ BarUiActCallback(BarUiActRenameStation) { WaitressReturn_t wRet; char lineBuf[100]; - RETURN_IF_NO_STATION; + assert (selStation != NULL); BarUiMsg (MSG_QUESTION, "New name: "); if (BarReadlineStr (lineBuf, sizeof (lineBuf), &app->input, BAR_RL_DEFAULT) > 0) { PianoRequestDataRenameStation_t reqData; - if (!BarTransformIfShared (app, app->curStation)) { + if (!BarTransformIfShared (app, selStation)) { return; } - reqData.station = app->curStation; + reqData.station = selStation; reqData.newName = lineBuf; BarUiMsg (MSG_INFO, "Renaming station... "); @@ -411,10 +392,11 @@ BarUiActCallback(BarUiActTempBanSong) { PianoReturn_t pRet; WaitressReturn_t wRet; - RETURN_IF_NO_SONG; + assert (selSong != NULL); BarUiMsg (MSG_INFO, "Putting song on shelf... "); - if (BarUiActDefaultPianoCall (PIANO_REQUEST_ADD_TIRED_SONG, app->playlist)) { + if (BarUiActDefaultPianoCall (PIANO_REQUEST_ADD_TIRED_SONG, selSong) && + selSong == app->playlist) { BarUiDoSkipSong (&app->player); } BarUiActDefaultEventcmd ("songshelf"); @@ -423,9 +405,9 @@ BarUiActCallback(BarUiActTempBanSong) { /* print upcoming songs */ BarUiActCallback(BarUiActPrintUpcoming) { - RETURN_IF_NO_SONG; + assert (selSong != NULL); - PianoSong_t *nextSong = app->playlist->next; + PianoSong_t *nextSong = selSong->next; if (nextSong != NULL) { BarUiListSongs (&app->settings, nextSong); } else { @@ -440,14 +422,14 @@ BarUiActCallback(BarUiActSelectQuickMix) { PianoReturn_t pRet; WaitressReturn_t wRet; - RETURN_IF_NO_STATION; + assert (selStation != NULL); - if (app->curStation->isQuickMix) { - PianoStation_t *selStation; - while ((selStation = BarUiSelectStation (&app->ph, + if (selStation->isQuickMix) { + PianoStation_t *toggleStation; + while ((toggleStation = BarUiSelectStation (&app->ph, "Toggle quickmix for station: ", app->settings.sortOrder, &app->input)) != NULL) { - selStation->useQuickMix = !selStation->useQuickMix; + toggleStation->useQuickMix = !toggleStation->useQuickMix; } BarUiMsg (MSG_INFO, "Setting quickmix stations... "); BarUiActDefaultPianoCall (PIANO_REQUEST_SET_QUICKMIX, NULL); @@ -467,81 +449,36 @@ BarUiActCallback(BarUiActQuit) { /* song history */ BarUiActCallback(BarUiActHistory) { - PianoReturn_t pRet; - WaitressReturn_t wRet; - char selectBuf[2], allowedBuf[4]; - PianoSong_t *selectedSong; + char buf[2]; + PianoSong_t *histSong; if (app->songHistory != NULL) { - selectedSong = BarUiSelectSong (&app->settings, app->songHistory, + histSong = BarUiSelectSong (&app->settings, app->songHistory, &app->input); - if (selectedSong != NULL) { - /* use user-defined keybindings */ - allowedBuf[0] = app->settings.keys[BAR_KS_LOVE]; - allowedBuf[1] = app->settings.keys[BAR_KS_BAN]; - allowedBuf[2] = app->settings.keys[BAR_KS_TIRED]; - allowedBuf[3] = '\0'; - - BarUiMsg (MSG_QUESTION, "%s - %s: love[%c], ban[%c] or tired[%c]? ", - selectedSong->artist, selectedSong->title, - app->settings.keys[BAR_KS_LOVE], - app->settings.keys[BAR_KS_BAN], - app->settings.keys[BAR_KS_TIRED]); - BarReadline (selectBuf, sizeof (selectBuf), allowedBuf, - &app->input, BAR_RL_FULLRETURN, -1); - - if (selectBuf[0] == app->settings.keys[BAR_KS_LOVE] || - selectBuf[0] == app->settings.keys[BAR_KS_BAN] || - selectBuf[0] == app->settings.keys[BAR_KS_TIRED]) { - /* make sure we're transforming the _original_ station (not - * curStation) */ - PianoStation_t *songStation = - PianoFindStationById (app->ph.stations, - selectedSong->stationId); - - if (songStation == NULL) { - BarUiMsg (MSG_ERR, "Station does not exist any more.\n"); - return; + if (histSong != NULL) { + BarKeyShortcutId_t action; + PianoStation_t *songStation = PianoFindStationById (app->ph.stations, + histSong->stationId); + + if (songStation == NULL) { + BarUiMsg (MSG_ERR, "Station does not exist any more.\n"); + return; + } + + do { + action = BAR_KS_COUNT; + + BarUiMsg (MSG_QUESTION, "What to do with this song? "); + + if (BarReadline (buf, sizeof (buf), NULL, &app->input, + BAR_RL_FULLRETURN, -1) > 0) { + /* actions assume that selStation is the song's original + * station */ + action = BarUiDispatch (app, buf[0], songStation, histSong, + false, BAR_DC_UNDEFINED); } - - if (!BarTransformIfShared (app, songStation)) { - return; - } - - if (selectBuf[0] == app->settings.keys[BAR_KS_LOVE]) { - /* FIXME: copy&waste */ - PianoRequestDataRateSong_t reqData; - reqData.song = selectedSong; - reqData.rating = PIANO_RATE_LOVE; - - BarUiMsg (MSG_INFO, "Loving song... "); - BarUiActDefaultPianoCall (PIANO_REQUEST_RATE_SONG, - &reqData); - - BarUiStartEventCmd (&app->settings, "songlove", songStation, - selectedSong, &app->player, app->ph.stations, - pRet, wRet); - } else if (selectBuf[0] == app->settings.keys[BAR_KS_BAN]) { - PianoRequestDataRateSong_t reqData; - reqData.song = selectedSong; - reqData.rating = PIANO_RATE_BAN; - - BarUiMsg (MSG_INFO, "Banning song... "); - BarUiActDefaultPianoCall (PIANO_REQUEST_RATE_SONG, - &reqData); - BarUiStartEventCmd (&app->settings, "songban", songStation, - selectedSong, &app->player, app->ph.stations, - pRet, wRet); - } else if (selectBuf[0] == app->settings.keys[BAR_KS_TIRED]) { - BarUiMsg (MSG_INFO, "Putting song on shelf... "); - BarUiActDefaultPianoCall (PIANO_REQUEST_ADD_TIRED_SONG, selectedSong); - - BarUiStartEventCmd (&app->settings, "songshelf", songStation, - selectedSong, &app->player, app->ph.stations, - pRet, wRet); - } /* end if */ - } /* end if selectBuf[0] */ - } /* end if selectedSong != NULL */ + } while (action == BAR_KS_HELP); + } /* end if histSong != NULL */ } else { BarUiMsg (MSG_INFO, (app->settings.history == 0) ? "History disabled.\n" : "No history yet.\n"); @@ -555,19 +492,18 @@ BarUiActCallback(BarUiActBookmark) { WaitressReturn_t wRet; char selectBuf[2]; - RETURN_IF_NO_SONG; + assert (selSong != NULL); BarUiMsg (MSG_QUESTION, "Bookmark [s]ong or [a]rtist? "); BarReadline (selectBuf, sizeof (selectBuf), "sa", &app->input, BAR_RL_FULLRETURN, -1); if (selectBuf[0] == 's') { BarUiMsg (MSG_INFO, "Bookmarking song... "); - BarUiActDefaultPianoCall (PIANO_REQUEST_BOOKMARK_SONG, app->playlist); + BarUiActDefaultPianoCall (PIANO_REQUEST_BOOKMARK_SONG, selSong); BarUiActDefaultEventcmd ("songbookmark"); } else if (selectBuf[0] == 'a') { BarUiMsg (MSG_INFO, "Bookmarking artist... "); - BarUiActDefaultPianoCall (PIANO_REQUEST_BOOKMARK_ARTIST, - app->playlist); + BarUiActDefaultPianoCall (PIANO_REQUEST_BOOKMARK_ARTIST, selSong); BarUiActDefaultEventcmd ("artistbookmark"); } } diff --git a/src/ui_act.h b/src/ui_act.h index b1dce62..ca67c63 100644 --- a/src/ui_act.h +++ b/src/ui_act.h @@ -24,9 +24,14 @@ THE SOFTWARE. #ifndef _UI_ACT_H #define _UI_ACT_H +#include + #include "main.h" +#include "ui_dispatch.h" -#define BarUiActCallback(name) void name (BarApp_t *app) +#define BarUiActCallback(name) void name (BarApp_t *app, \ + PianoStation_t *selStation, PianoSong_t *selSong, \ + BarUiDispatchContext_t context) BarUiActCallback(BarUiActHelp); BarUiActCallback(BarUiActAddMusic); diff --git a/src/ui_dispatch.c b/src/ui_dispatch.c new file mode 100644 index 0000000..ddcf60c --- /dev/null +++ b/src/ui_dispatch.c @@ -0,0 +1,71 @@ +/* +Copyright (c) 2010-2011 + Lars-Dominik Braun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include + +#include "ui_dispatch.h" +#include "settings.h" +#include "ui.h" + +/* handle global keyboard shortcuts + * @return BAR_KS_* if action was performed or BAR_KS_COUNT on error/if no + * action was performed + */ +BarKeyShortcutId_t BarUiDispatch (BarApp_t *app, const char key, PianoStation_t *selStation, + PianoSong_t *selSong, const bool verbose, + BarUiDispatchContext_t context) { + assert (app != NULL); + assert (sizeof (app->settings.keys) / sizeof (*app->settings.keys) == + sizeof (dispatchActions) / sizeof (*dispatchActions)); + + if (selStation != NULL) { + context |= BAR_DC_STATION; + } + if (selSong != NULL) { + context |= BAR_DC_SONG; + } + + for (size_t i = 0; i < BAR_KS_COUNT; i++) { + if (app->settings.keys[i] != BAR_KS_DISABLED && + app->settings.keys[i] == key) { + if ((dispatchActions[i].context & context) == dispatchActions[i].context) { + assert (dispatchActions[i].function != NULL); + + dispatchActions[i].function (app, selStation, selSong, + context); + return i; + } else if (verbose) { + if (dispatchActions[i].context & BAR_DC_SONG) { + BarUiMsg (MSG_ERR, "No song playing.\n"); + } else if (dispatchActions[i].context & BAR_DC_STATION) { + BarUiMsg (MSG_ERR, "No station selected.\n"); + } else { + assert (0); + } + return BAR_KS_COUNT; + } + } + } + return BAR_KS_COUNT; +} + diff --git a/src/ui_dispatch.h b/src/ui_dispatch.h new file mode 100644 index 0000000..c5aecc5 --- /dev/null +++ b/src/ui_dispatch.h @@ -0,0 +1,105 @@ +/* +Copyright (c) 2010-2011 + Lars-Dominik Braun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef _UI_DISPATCH_H +#define _UI_DISPATCH_H + +/* bit-mask */ +typedef enum { + BAR_DC_UNDEFINED = 0, + BAR_DC_GLOBAL = 1, /* top-level action */ + BAR_DC_STATION = 2, /* station selected */ + BAR_DC_SONG = 4, /* song selected */ +} BarUiDispatchContext_t; + +#include "settings.h" +#include "main.h" + +typedef void (*BarKeyShortcutFunc_t) (BarApp_t *, PianoStation_t *, + PianoSong_t *, BarUiDispatchContext_t); + +typedef struct { + BarUiDispatchContext_t context; + BarKeyShortcutFunc_t function; + char *helpText; + char defaultKey; + char *configKey; +} BarUiDispatchAction_t; + +#include "ui_act.h" + +/* see settings.h */ +static const BarUiDispatchAction_t dispatchActions[BAR_KS_COUNT] = { + {BAR_DC_UNDEFINED, BarUiActHelp, NULL, '?', "act_help"}, + {BAR_DC_SONG, BarUiActLoveSong, "love song", '+', + "act_songlove"}, + {BAR_DC_SONG, BarUiActBanSong, "ban song", '-', "act_songban"}, + {BAR_DC_STATION, BarUiActAddMusic, "add music to station", 'a', + "act_stationaddmusic"}, + {BAR_DC_GLOBAL, BarUiActCreateStation, "create new station", 'c', + "act_stationcreate"}, + {BAR_DC_STATION, BarUiActDeleteStation, "delete station", 'd', + "act_stationdelete"}, + {BAR_DC_SONG, BarUiActExplain, "explain why this song is played", 'e', + "act_songexplain"}, + {BAR_DC_GLOBAL, BarUiActStationFromGenre, "add genre station", 'g', + "act_stationaddbygenre"}, + {BAR_DC_GLOBAL, BarUiActHistory, "song history", 'h', "act_history"}, + {BAR_DC_GLOBAL | BAR_DC_STATION | BAR_DC_SONG, BarUiActSongInfo, + "print information about song/station", 'i', + "act_songinfo"}, + {BAR_DC_GLOBAL, BarUiActAddSharedStation, "add shared station", 'j', + "act_addshared"}, + {BAR_DC_SONG, BarUiActMoveSong, "move song to different station", 'm', + "act_songmove"}, + {BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActSkipSong, "next song", 'n', "act_songnext"}, + {BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActPause, "pause/continue", 'p', "act_songpause"}, + {BAR_DC_GLOBAL, BarUiActQuit, "quit", 'q', "act_quit"}, + {BAR_DC_STATION, BarUiActRenameStation, "rename station", 'r', + "act_stationrename"}, + {BAR_DC_GLOBAL, BarUiActSelectStation, "change station", 's', + "act_stationchange"}, + {BAR_DC_SONG, BarUiActTempBanSong, "tired (ban song for 1 month)", 't', + "act_songtired"}, + {BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActPrintUpcoming, "upcoming songs", 'u', + "act_upcoming"}, + {BAR_DC_STATION, BarUiActSelectQuickMix, "select quickmix stations", + 'x', "act_stationselectquickmix"}, + {BAR_DC_GLOBAL, BarUiActDebug, NULL, '$', "act_debug"}, + {BAR_DC_SONG, BarUiActBookmark, "bookmark song/artist", 'b', + "act_bookmark"}, + {BAR_DC_GLOBAL, BarUiActVolDown, "decrease volume", '(', + "act_voldown"}, + {BAR_DC_GLOBAL, BarUiActVolUp, "increase volume", ')', + "act_volup"}, + }; + +#include +#include +#include + +BarKeyShortcutId_t BarUiDispatch (BarApp_t *, const char, PianoStation_t *, PianoSong_t *, + const bool, BarUiDispatchContext_t); + +#endif /* _UI_DISPATCH_H */ + -- cgit v1.2.3