coderholic / pyradio

Curses based internet radio player
www.coderholic.com/pyradio
MIT License
944 stars 129 forks source link

next/prev keys for quick station change in playlist mode #135

Open jirikrepl opened 3 years ago

jirikrepl commented 3 years ago

Hi @coderholic @s-n-g ,

thanks for this great app. It would be nice if there were two keyboard shortcuts for playing next/previous station in a playlist.

It would be great if mvp or another player could use these shortcuts. I mean I have next/prev pause/play physical keys on my keyboard which works in many apps which are playing in the background e.g. Spotify.

I also noticed that the pause/play key on my keyboard already works (only) with mvp player.

If you agree and can give me some info. I can create a PR.

s-n-g commented 3 years ago

hi @jirikrepl

Let us just see what these keys are. Please use this python program to get the keycodes

import curses
import os

def main(stdscr):
    stdscr.nodelay(False)
    key=""
    stdscr.clear()
    while 1:
        try:
            key = stdscr.getch()
            #stdscr.clear()
            stdscr.addstr("Detected key: ")
            stdscr.addstr('{0} - {1}\n'.format(key, chr(key)))
            if key == os.linesep:
                break
        except Exception as e:
            # No input
            pass

curses.wrapper(main)

Please press all the keys you are interested in (make a note which is which)

As far as I can see the following keys are already defined:

KEY_NEXT = 367
KEY_PREVIOUS = 370

You can see the definitions of KEY_ constants here: https://docs.python.org/3/library/curses.html#curses.window.getch

To see key names - keycodes, execute

python
import curses
help(curses)

and look for the KEY_* constants

jirikrepl commented 3 years ago

great! thanks for the tips.

but this next/prev functionality is not yet implemented in console UI, or is it? I only saw random select with r

If I want to select next radio I need to do it with down and enter (I did not see a single key command)

s-n-g commented 3 years ago

Yeah, I see now I was not clear... Sorry, about that...

So, please save this as detect-codes.py

import curses
import os

def main(stdscr):
    stdscr.nodelay(False)
    key=""
    stdscr.clear()
    while 1:
        try:
            key = stdscr.getch()
            #stdscr.clear()
            stdscr.addstr("Detected key: ")
            stdscr.addstr('{0} - {1}\n'.format(key, chr(key)))
            if key == os.linesep:
                break
        except Exception as e:
            # No input
            pass

curses.wrapper(main)

Open a console (terminal) and type

python detect-codes.py

Press the keys you are interested in (next/prev, pause/play), the program will print the keycodes. Post the keycoed back here and then we'll see how we proceed

s-n-g commented 3 years ago

I got some time to work on it, so

Open a terminal and type

pyradio -U --sng-devel

This will download and install my devel branch from https://github.com/s-n-g/pyradio

Now, when you play a station you can press ^N (Ctrl-N) and ^P (Ctrl-P) to play the next / previous station. I have tested this one on linux, win10 and macOS Catalina and it works.

If your next key sends a curses.KEY_NEXT code, it will be the same as pressing ^N. And of course, if your previous key sends a curses.KEY_PREVOUS code, it will be the same as pressing ^P. I do not have these key here, so I cannot test them...

Just test it out and tell me if your next/previous keys work. If not, run the program I previously posted to get their keycodes and see what can be done. S.

jirikrepl commented 3 years ago

Hi @s-n-g

sorry for my late answer. I tested your code and ^N and ^P works great! But what I meant was if pyradio could do prev next even when terminal is out of focus.

On my keyboard when using media keys I can do prev/next, play/pause Spotify, even if Spotify does not have focus

Currently I can do play/pause when using pyradio with mplayer and terminal does not focus. prev next does not work

Here is my keyboard layout where there are those media keys https://configure.zsa.io/ergodox-ez/layouts/gYqMN/latest/1

Here are some screenshots with keycodes

Screen Shot 2021-08-02 at 10 14 47 Screen Shot 2021-08-02 at 10 18 03 Screen Shot 2021-08-02 at 10 18 24 Screen Shot 2021-08-02 at 10 18 10

I tested your script but it will not print anything if I press media keys. It works only fine with single letter keys

Screen Shot 2021-08-02 at 10 21 16

I used karabiner event view to print keycodes for those media keys (there are keydown and keyup events):

Screen Shot 2021-08-02 at 10 31 39 Screen Shot 2021-08-02 at 10 31 53 Screen Shot 2021-08-02 at 10 32 04
s-n-g commented 3 years ago

Oh, I see what you mean!

I do not think this can be done with pyradio at this time, though... You see, it just reads keyboard input from the terminal, which means that the terminal has to be focused to do that

Now, there is a way to do it: a keyboard listener Try this out:

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

You will have to install the following python module beforehand: pynput

Save the program as keyb_listener.py and execute

python keyb_listener.py

Focus any other window and start typing. You should be able to see the keys you type. You should also be able to see your "extra" keys (next / previous / play / 'pause', etc)

Please do tell me how that goes!

Finally, I may be able to incorporete this functionality to pyradio (not sure how, thought), but in any case this is something for the future.

I will leave this issue open, so that I do not forget about it :)