diff options
| author | Michał Cichoń <michcic@gmail.com> | 2019-05-03 17:02:47 +0200 | 
|---|---|---|
| committer | Michał Cichoń <michcic@gmail.com> | 2019-05-03 17:02:47 +0200 | 
| commit | eaa10a3950ccd8fa2a5acada4c82d6627b6214f7 (patch) | |
| tree | 3012531b45cfbaba4b4c0c66e157ad20795e54ee /src | |
| parent | cb6789b17f81d29c6884c27715c705083e09a5db (diff) | |
| parent | c4b80765185944a5b89f3cc76568ba498bf5f3f4 (diff) | |
| download | pianobar-windows-eaa10a3950ccd8fa2a5acada4c82d6627b6214f7.tar.gz pianobar-windows-eaa10a3950ccd8fa2a5acada4c82d6627b6214f7.tar.bz2 pianobar-windows-eaa10a3950ccd8fa2a5acada4c82d6627b6214f7.zip | |
Merge branch 'release/2019.05.03'2019.05.03
Add support for hotkeys. #20
Hotkeys can be assigned to action in configuration file ex:
hk_<action_name> = g + shift + alt + ctrl
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.h | 2 | ||||
| -rw-r--r-- | src/hotkey.c | 113 | ||||
| -rw-r--r-- | src/hotkey.h | 53 | ||||
| -rw-r--r-- | src/main.c | 52 | ||||
| -rw-r--r-- | src/settings.c | 15 | ||||
| -rw-r--r-- | src/ui_readline.c | 20 | ||||
| -rw-r--r-- | src/ui_readline.h | 3 | 
7 files changed, 246 insertions, 12 deletions
| diff --git a/src/config.h b/src/config.h index a8af710..b066102 100644 --- a/src/config.h +++ b/src/config.h @@ -3,7 +3,7 @@  /* package name */  #define PACKAGE "pianobar" -#define VERSION "2018.10.30" +#define VERSION "2019.05.03"  #define TITLE   "Pianobar" diff --git a/src/hotkey.c b/src/hotkey.c new file mode 100644 index 0000000..b630b88 --- /dev/null +++ b/src/hotkey.c @@ -0,0 +1,113 @@ +/* +Copyright (c) 2019 +    Micha³ Cichoñ <thedmd@interia.pl> + +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 "hotkey.h" +#include <stdio.h> +#include <stdbool.h> +#include <fcntl.h> +#include <io.h> +#include <windows.h> + +static BarHotKey_t* g_HotKeys = NULL; +static int g_HotKeyCapacity = 0; +static int g_HotKeyCount = 0; + +void BarHotKeyInit () +{ +} + +void BarHotKeyDestroy () +{ +} + +void BarHotKeyPool (BarHotKeyHandler handler, void * userData) +{ +    MSG msg = {0}; +    while (PeekMessage(&msg, NULL, WM_HOTKEY, WM_HOTKEY, PM_REMOVE) != 0) +    { +        int id = (int)msg.wParam; +        if (id < 0) +            continue; + +        handler(id, userData); +    } +} + +bool BarHotKeyRegister (BarHotKey_t hk) +{ +    UINT modifiers = 0; +    SHORT mappedVirtualKey = VkKeyScanA(tolower(hk.key)); +    BYTE keyCode = LOBYTE(mappedVirtualKey); +    if (keyCode == 0) +        return false; + +    if (hk.mods & BAR_HK_MOD_SHIFT) +        modifiers |= MOD_SHIFT; +    if (hk.mods & BAR_HK_MOD_ALT) +        modifiers |= MOD_ALT; +    if (hk.mods & BAR_HK_MOD_CTRL) +        modifiers |= MOD_CONTROL; +    if (hk.mods & BAR_HK_MOD_WIN) +        modifiers |= MOD_WIN; + +    modifiers |= /*MOD_NOREPEAT*/0x4000; + +    return RegisterHotKey(NULL, hk.id, modifiers, keyCode); +} + +void BarHotKeyUnregister (int id) +{ +    UnregisterHotKey(NULL, id); +} + +bool BarHotKeyParse (BarHotKey_t* result, const char *value) +{ +    BarHotKey_t parsed = { 0 }; +    const char* p = value; +    size_t s = 0; + +    while ((s = strcspn(p, " +")) > 0) +    { +        if ((s == 4 && strnicmp(p, "ctrl", 4) == 0) || (s == 7 && strnicmp(p, "control", 7) == 0)) +            parsed.mods |= BAR_HK_MOD_CTRL; +        else if ((s == 5 && strnicmp(p, "shift", 5) == 0)) +            parsed.mods |= BAR_HK_MOD_SHIFT; +        else if ((s == 3 && strnicmp(p, "alt", 3) == 0)) +            parsed.mods |= BAR_HK_MOD_ALT; +        else if (s == 1) +            parsed.key = *p; +        else +            return false; + +        p += s; +        p += strspn(p, " +"); +    } + +    if (parsed.key == 0) +        return false; + +    result->key = parsed.key; +    result->mods = parsed.mods; + +    return true; +}
\ No newline at end of file diff --git a/src/hotkey.h b/src/hotkey.h new file mode 100644 index 0000000..fb59bc0 --- /dev/null +++ b/src/hotkey.h @@ -0,0 +1,53 @@ +/* +Copyright (c) 2019 +	Micha³ Cichoñ <thedmd@interia.pl> + +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. +*/ + +# pragma once + +#include "config.h" +#include <stdio.h> +#include <stdarg.h> +#include <stdbool.h> + +typedef enum { +    BAR_HK_MOD_NONE = 0, +    BAR_HK_MOD_SHIFT = 1, +    BAR_HK_MOD_ALT = 2, +    BAR_HK_MOD_CTRL = 4, +    BAR_HK_MOD_WIN = 8 +} BarHotKeyMods_t; + +typedef struct { +    int id; +    char key; +    BarHotKeyMods_t mods; +} BarHotKey_t; + +typedef void (*BarHotKeyHandler)(int, void *); + +void BarHotKeyInit (); +void BarHotKeyDestroy (); +void BarHotKeyPool (BarHotKeyHandler, void *); +bool BarHotKeyRegister (BarHotKey_t); +void BarHotKeyUnregister (int); +bool BarHotKeyParse (BarHotKey_t* result, const char* value); + @@ -28,6 +28,7 @@ THE SOFTWARE.  #include "main.h"  #include "console.h" +#include "hotkey.h"  #include "ui.h"  #include "ui_dispatch.h"  #include "ui_readline.h" @@ -179,17 +180,61 @@ static void BarMainGetInitialStation (BarApp_t *app) {  	}  } +static int BarMainHandleVirtualKey(int virtualKey, void *userData) +{ +    BarApp_t *app = (BarApp_t *)userData; + +    switch (virtualKey) +    { +        case /*VK_VOLUME_MUTE*/         0xAD: return 0; +        case /*VK_VOLUME_DOWN*/         0xAE: return 0;//app->settings.keys[BAR_KS_VOLDOWN]; +        case /*VK_VOLUME_UP*/           0xAF: return 0;//app->settings.keys[BAR_KS_VOLUP]; +        case /*VK_MEDIA_NEXT_TRACK*/    0xB0: return 0;//app->settings.keys[BAR_KS_SKIP]; +        case /*VK_MEDIA_PREV_TRACK*/    0xB1: return 0; +        case /*VK_MEDIA_STOP*/          0xB2: return 0; +        case /*VK_MEDIA_PLAY_PAUSE*/    0xB3: return 0;//app->settings.keys[BAR_KS_PLAYPAUSE]; +        case /*VK_LAUNCH_MAIL*/         0xB4: return 0; +        case /*VK_LAUNCH_MEDIA_SELECT*/ 0xB5: return 0; +        case /*VK_LAUNCH_APP1*/         0xB6: return 0; +        case /*VK_LAUNCH_APP2*/         0xB7: return 0; +        default: return 0; +    } +} + +static void BarMainHotKeyHandler(int hotKeyId, void *userData) +{ +    if (hotKeyId == 0) +        return; + +    BarApp_t *app = (BarApp_t *)userData; + +    BarUiDispatch(app, app->settings.keys[hotKeyId], app->curStation, app->playlist, true, +        BAR_DC_GLOBAL); +} +  /*	wait for user rl   */  static void BarMainHandleUserInput(BarApp_t *app)  {      char buf[2]; -    if (BarReadline(buf, sizeof(buf), NULL, app->rl, -        BAR_RL_FULLRETURN | BAR_RL_NOECHO, 1) > 0) +    size_t readSize = 0; + +    BarReadlineSetVirtualKeyHandler(app->rl, BarMainHandleVirtualKey, app); + +    readSize = BarReadline(buf, sizeof(buf), NULL, app->rl, +        BAR_RL_FULLRETURN | BAR_RL_NOECHO, 1); + +    BarReadlineSetVirtualKeyHandler(app->rl, NULL, NULL); + +    if (readSize > 0)      {          BarUiDispatch(app, buf[0], app->curStation, app->playlist, true,              BAR_DC_GLOBAL);      } +    else +    { +        BarHotKeyPool(BarMainHotKeyHandler, app); +    }  }  /*	fetch new playlist @@ -375,6 +420,8 @@ int main(int argc, char **argv)      BarConsoleSetTitle(TITLE); +    BarHotKeyInit(); +      /* init some things */      BarSettingsInit(&app.settings);      BarSettingsRead(&app.settings); @@ -432,6 +479,7 @@ int main(int argc, char **argv)      HttpDestroy(app.http2);      BarPlayer2Destroy(app.player);      BarSettingsDestroy(&app.settings); +    BarHotKeyDestroy();      BarConsoleDestroy();      return 0; diff --git a/src/settings.c b/src/settings.c index affb7f2..a2ce3fb 100644 --- a/src/settings.c +++ b/src/settings.c @@ -29,6 +29,7 @@ THE SOFTWARE.  #include "config.h"  #include "ui.h"  #include "ui_dispatch.h" +#include "hotkey.h"  #include <stdlib.h>  #include <assert.h>  #include <memory.h> @@ -340,6 +341,20 @@ void BarSettingsRead (BarSettings_t *settings) {  						break;  					}  				} +			} else if (memcmp ("hk_act_", key, 7) == 0) { +				size_t i; +				char* actionKey = key + 3; +				/* keyboard shortcuts */ +				for (i = 0; i < BAR_KS_COUNT; i++) { +					if (streq (dispatchActions[i].configKey, actionKey)) { +						BarHotKey_t hk = { 0 }; +						if (BarHotKeyParse(&hk, val)) { +							hk.id = i; +							BarHotKeyRegister(hk); +						} +						break; +					} +				}  			} else if (streq ("audio_quality", key)) {  				if (streq (val, "low")) {  					settings->audioQuality = PIANO_AQ_LOW; diff --git a/src/ui_readline.c b/src/ui_readline.c index 5d6b7a7..687258a 100644 --- a/src/ui_readline.c +++ b/src/ui_readline.c @@ -75,6 +75,8 @@ static inline int BarReadlineEncodeUtf8 (int codePoint, char* utf8) {  struct _BarReadline_t {  	DWORD  DefaultAttr; +	BarVirtualKeyHandler VirtualKeyHandler; +	void *VirtualKeyHandlerUserData;  };  void BarReadlineInit(BarReadline_t* rl) { @@ -85,6 +87,11 @@ void BarReadlineInit(BarReadline_t* rl) {  void BarReadlineDestroy(BarReadline_t rl) {  } +void BarReadlineSetVirtualKeyHandler(BarReadline_t rl, BarVirtualKeyHandler handler, void *ud) { +    rl->VirtualKeyHandler = handler; +    rl->VirtualKeyHandlerUserData = ud; +} +  /*	return size of previous UTF-8 character   */  static size_t BarReadlinePrevUtf8 (char *ptr) { @@ -248,16 +255,11 @@ size_t BarReadline (char *buf, const size_t bufSize, const char *mask,  							char encodedCodePoint[5];  							int encodedCodePointLength; -							/* -							if (keyCode == VK_MEDIA_PLAY_PAUSE) { -							codePoint = 'p'; -							PlaySoundA("SystemNotification", NULL, SND_ASYNC); -							} -							else if (keyCode == VK_MEDIA_NEXT_TRACK) { -							codePoint = 'n'; -							PlaySoundA("SystemNotification", NULL, SND_ASYNC); +							if (input->VirtualKeyHandler != NULL) { +								int newCodePoint = input->VirtualKeyHandler(keyCode, input->VirtualKeyHandlerUserData); +								if (newCodePoint != 0) +									codePoint = newCodePoint;  							} -							*/  							if (codePoint <= 0x1F)  								break; diff --git a/src/ui_readline.h b/src/ui_readline.h index 83214b9..bb2772a 100644 --- a/src/ui_readline.h +++ b/src/ui_readline.h @@ -36,8 +36,11 @@ typedef enum {  typedef struct _BarReadline_t *BarReadline_t; +typedef int (*BarVirtualKeyHandler)(int, void*); +  void BarReadlineInit(BarReadline_t*);  void BarReadlineDestroy(BarReadline_t); +void BarReadlineSetVirtualKeyHandler(BarReadline_t, BarVirtualKeyHandler, void *);  size_t BarReadline (char *, const size_t, const char *,  		BarReadline_t, const BarReadlineFlags_t, int);  size_t BarReadlineStr (char *, const size_t, | 
