summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c27
-rw-r--r--src/settings.c25
-rw-r--r--src/settings.h3
-rw-r--r--src/ui_act.c258
-rw-r--r--src/ui_act.h7
-rw-r--r--src/ui_dispatch.c71
-rw-r--r--src/ui_dispatch.h105
7 files changed, 293 insertions, 203 deletions
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 <stdlib.h>
#include <stdio.h>
#include <limits.h>
+#include <assert.h>
#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 ("</3");
+ for (size_t i = 0; i < BAR_KS_COUNT; i++) {
+ settings->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 <piano.h>
#include <waitress.h>
-/* 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 <string.h>
#include <unistd.h>
#include <pthread.h>
+#include <assert.h>
#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 <piano.h>
+
#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 <lars@6xq.net>
+
+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 <assert.h>
+
+#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 <lars@6xq.net>
+
+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 <piano.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+BarKeyShortcutId_t BarUiDispatch (BarApp_t *, const char, PianoStation_t *, PianoSong_t *,
+ const bool, BarUiDispatchContext_t);
+
+#endif /* _UI_DISPATCH_H */
+