Kalliope as your personal DJ

Wednesday, November 15, 2017

kalliopempdmopidy

A quick blog post about how I managed my music via Kalliope :)

The basic idea is simple: I want to ask Kalliope to play music for me, and manage spotify playlist/search and radio

To do this, I need: - Kalliope installed - Kalliope MPD module installed - Mopidy server (to act like a MPD server and manage spotify and radio source)

I wanted to have a simple flow:

    Me: "I want to listen to music"
    Kalliope: "Of course, what do you want to listen to?"
    Me:
      Option 1:
        Me: "My favorite spotify playlist"
        Kalliope: "Ok, starting your favorite playlist"

      Option 2:
        Me: "spotify playlist <Name Of a playlist>"
        Kalliope: "Ok, launching <Name of a playlist>"

      Option 3:
        Me: "I want to listen to the radio"
        Kalliope: Which radio sir?
        Me: "<radio name>"
        Kalliope: "launching radio <radio name>"

      Option 4:
        Me: "music from <artist name>"
        Kalliope: "searching for music of <artist name>"

      Option 5:
        Me: "I'll try some fashion music"
        Kalliope: "Starting some fashion music"

Installation

Kalliope

First, install Kalliope. For this, follow the documentation. Once it’s done and working, install the MPD neuron as indicated on the README.

We’ll get to the brain configuration in the next step.

Mopidy server

Then, you need to install mopidy. Either on the same device as Kalliope or on another one. For this, same as above, follow the documentation :)

If you have the same use cases as me, and want to plug spotify and the radio, you will also need to install mopidy-spotify, tunein, and spotify_tunigo and of corse the core mpd backend.

Mon fichier de conf .config/mopidy/mopidy.conf pour exemple:

    [mpd]
    enabled = true
    hostname = 127.0.0.1
    port = 8080
    password = MyPassword
    max_connections = 10
    connection_timeout = 60
    zeroconf = Mopidy MPD server on $hostname
    command_blacklist = listall,listallinfo
    default_playlist_scheme = m3u

    [core]
    cache_dir = $XDG_CACHE_DIR/mopidy
    config_dir = $XDG_CONFIG_DIR/mopidy
    data_dir = $XDG_DATA_DIR/mopidy
    max_tracklist_length = 10000
    restore_state = false

    [logging]
    color = true
    console_format = %(levelname)-8s %(message)s
    debug_format = %(levelname)-8s %(asctime)s [%(process)d:%(threadName)s] %(name)s\n  %(message)s
    debug_file = mopidy.log
    config_file =

    [spotify]
    username = MyLogin
    password = MyPassword
    enabled = true
    bitrate = 320
    timeout = 100
    client_id = MyClientId
    client_secret = MyClientSecret

    [spotify_tunigo]
    enabled: true

    [tunein]
    timeout = 5000

PS: You need to adapt the hostname if your mopidy server is not installed on the same machine as Kalliope!, see mopidy hostname configuration here.

Configuring the brain

The first question

Let’s create a new brain file called mpd.yml in your brains directory, and configure the first step of the flow:

      - name: "ask-and-play-music"
        signals:
          - order: "I want to listen to music"
        neurons:
          - say:
              message: "Of course, what do you want to listen to?"
          - neurotransmitter:
              from_answer_link:
                - synapse: "play-favorite-spotify-playlist"
                  answers:
                    - "My favorite spotify playlist"
                - synapse: "play-asked-spotify-playlist"
                  answers:
                    - "spotify playlist {{query}}"
                - synapse: "play-fashion-music"
                  answers:
                    - "I'll try some fashion music"
                - synapse: "play-asked-radio"
                  answers:
                    - "I want to listen to the radio"
                - synapse: "play-asked-music"
                  answers:
                    - "search for {{query}}"
              default: "didnt-understand"

So here we have the first step for our full flow. Kalliope is asking what kind of music I want to listen to, and depending on my answer, different synapse will be triggered.

Now I need to define the actions for each of these choices.

Managing options and anwsers

Playing my favorite playlist

That’s easy, just like said in the doc of the neuron:

      - name: "play-favorite-spotify-playlist"
        signals:
          - order: "start my favorite spotify playlist"
        neurons:
          - kalliopempd:
              mpd_action: "playlist"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "1"
              mpd_volume: "50"
              query: "{{favorite_playlist_name}}"
          - say:
              message: "Ok, starting your favorite playlist"

I could give a “no_order” but I might want to fire this playlist directly so I gave a correct order.

Please note that I’m using the brackets because I’m using the variables capability of kalliope

Playing a playlist

      - name: "play-asked-spotify-playlist"
        signals:
          - order: "start playlist {{query}}"
        neurons:
          - kalliopempd:
              mpd_action: "playlist"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "1"
              mpd_volume: "50"
              query: "{{query}}"
          - say:
              message: "Ok, starting the playlist {{query}}"

Asking and playing a radio

First, lets configure kalliope so it ask which radio I want to listen to:

      - name: "play-asked-radio"
        signals:
          - order: "I want to listen to the radio"
        neurons:
          - say:
              message: "Which radio sir?"
          - neurotransmitter:
              from_answer_link:
                - synapse: "play-radio"
                  answers:
                    - "{{query}}"
              default: "didnt-understand"

Then, create the brain that will actually start the radio:

      - name: "play-radio"
        signals:
          - order: "play-radio-no-order"
        neurons:
          - kalliopempd:
              mpd_action: "search"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "0"
              query: "{{query}}"
          - say:
              message: "Launching radio {{query}}"

Please note that I’m using the brackets because I’m using the variables capability of kalliope

Asking and playing any music

Same as the favorite playlist:

      - name: "play-asked-music"
        signals:
          - order: "search music {{query}}"
        neurons:
          - kalliopempd:
              mpd_action: "search"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "0"
              query: "{{query}}"
          - say:
              message: "Launching some music of {{query}}"

Please note that I’m using the brackets because I’m using the variables capability of kalliope

Didn’t understand synapse

This is just to let me know if something went wrong and Kalliope didn’t understand:

      - name: "didnt-understand"
        signals:
          - order: "didnt-understand"
        neurons:
          - say:
              message: "I'm terribly sorry sir, but something went wrong…"

Don’t forget to add your new brain file in the brain.yml via an include and your variable in a loaded file :)

The full brain file:

      - name: "ask-and-play-music"
        signals:
          - order: "I want to listen to music"
        neurons:
          - say:
              message: "Of course, what do you want to listen to?"
          - neurotransmitter:
              from_answer_link:
                - synapse: "play-favorite-spotify-playlist"
                  answers:
                    - "My favorite spotify playlist"
                - synapse: "play-asked-spotify-playlist"
                  answers:
                    - "spotify playlist {{query}}"
                - synapse: "play-fashion-music"
                  answers:
                    - "I'll try some fashion music"
                - synapse: "play-asked-radio"
                  answers:
                    - "I want to listen to the radio"
                - synapse: "play-asked-music"
                  answers:
                    - "search for {{query}}"
              default: "didnt-understand"

      - name: "play-favorite-spotify-playlist"
        signals:
          - order: "start my favorite spotify playlist"
        neurons:
          - kalliopempd:
              mpd_action: "playlist"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "1"
              mpd_volume: "50"
              query: "{{favorite_playlist_name}}"
          - say:
              message: "Ok, starting your favorite playlist"

      - name: "play-asked-spotify-playlist"
        signals:
          - order: "start playlist {{query}}"
        neurons:
          - kalliopempd:
              mpd_action: "playlist"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "1"
              mpd_volume: "50"
              query: "{{query}}"
          - say:
              message: "Ok, starting the playlist {{query}}"

      - name: "play-asked-radio"
        signals:
          - order: "I want to listen to the radio"
        neurons:
          - say:
              message: "Which radio sir?"
          - neurotransmitter:
              from_answer_link:
                - synapse: "play-radio"
                  answers:
                    - "{{query}}"
              default: "didnt-understand"

      - name: "play-radio"
        signals:
          - order: "play-radio-no-order"
        neurons:
          - kalliopempd:
              mpd_action: "search"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "0"
              query: "{{query}}"
          - say:
              message: "Launching radio {{query}}"

      - name: "play-asked-music"
        signals:
          - order: "search music {{query}}"
        neurons:
          - kalliopempd:
              mpd_action: "search"
              mpd_url: "{{mpd_url}}"
              mpd_port: "{{mpd_port}}"
              mpd_password: "{{mpd_password}}"
              mpd_random: "0"
              query: "{{query}}"
          - say:
              message: "Launching some music of {{query}}"

      - name: "didnt-understand"
        signals:
          - order: "didnt-understand"
        neurons:
          - say:
              message: "I'm terribly sorry sir, but something went wrong…"

Kalliope reminder with snooze kalliopereminder

Quick blog post to talk about how I setup Kalliope to remind me stuff, but with a snooze feature.

The default setup of the neurotimer let you ask Kalliope to remind you stuff after some time (minutes or hours).

I really like it because I have a poor short term memory, so when I have something to do in 30min, I use the kalliope neurotimer module to help me remember… But sometime, I want Kalliope to remind me again after 5 min because I didn’t have the time to do at the time Kalliope reminded me.

Let’s take a real life use case:

Let’s say I am in a game (starcraft2 fan here ^^) and someone is calling me. When in a game, I can’t (don’t want to) pick up the phone, but I want to remember to call back the person. For this I’m using the neurotimer to do so, with a sentence like "Remind me in XX minutes to YYY".

This is the default setup explained in the neurotimer README file here.

But that is not enough for me, because I may be still in game when being reminded by Kalliope, so I want to have the ability to tell kalliope to remind me again in X minutes, without re-asking the full order like before.

The workflow I want:

    Me: "Kalliope… remind me in 10 minutes to call back dad"
    Kalliope: "I'll remind you in 10 minutes to call back dad"
    [… 10minutes later …]
    Kalliope: "You asked me to remind you call back dad"
    Kalliope: "Do you want me to remind you again?"
      option1: (I want another reminder)
        Me: "Yes"
        Kalliope: "When?"
        Me: "In 5 minutes"
        [… 5 minutes later …]
        Kalliope: "You asked me to remind you to call back dad"

          *Option: Again, I'm in a sort of a loop here, so as long as I say "yes", it will remind me again until I say no (or anything other than yes).*

      Option2:
        Me: "No"
        Kalliope: "Ok, I won't remind you again."

So how does it work? I’m using the Neurotimer module, with the Neurotransmitter and the Kalliope memory to do so.

It does bring a limitation though, as you can’t have multi reminder with “snooze” as the memory will only remember the last one.

My configuration to do so is the following:

Brain file:

      {% raw %}
      ---
        - name: "reminder-synapse"
          signals:
            - order: "remind me to {{ remember }} in {{ time }} minutes"
          neurons:
            - neurotimer:
                minutes: "{{ time }}"
                synapse: "reminder-todo"
                forwarded_parameters:
                  remember: "{{ remember }}"
                kalliope_memory:
                  reminder_2: "{{ remember }}"
            - say:
                message:
                  - "Ok sir, reminder setup"

        - name: "reminder-todo"
          signals:
            - order: "reminder_todo_no_order"
          neurons:
            - say:
                message:
                  - "Sir, you asked me to remind you to {{ remember }}"
            - say:
                message: "Do you want me to remind you again ?"
            - neurotransmitter:
                from_answer_link:
                  - synapse: "reminder2"
                    answers:
                      - "oui"
                  - synapse: "no-response"
                    answers:
                      - "non"
                default: "no-response"

        - name: "reminder2"
          signals:
            - order: "reminder2-no-order"
          neurons:
            - say:
                message: "When do I have to remind you to {{ kalliope_memory['reminder_2'] }} ?"
            - neurotransmitter:
                from_answer_link:
                  - synapse: "reminder-via-memory"
                    answers:
                      - "in {{time}} minutes"
                  - synapse: "reminder-via-memory"
                    answers:
                      - "dans {{time}} minutes"
                default: "no-response"

        - name: "reminder-via-memory"
          signals:
            - order: "reminder-via-memory-no-order"
          neurons:
            - neurotimer:
                minutes: "{{ time }}"
                synapse: "reminder-todo"
                forwarded_parameters:
                  remember: "{{ kalliope_memory['reminder_2'] }}"
            - say:
                message:
                  - "Ok, I'll remind you in {{time}} minutes to {{ kalliope_memory['reminder_2'] }}"

      {% endraw %}

Nota: The “no-response” is a default synapse I created that simply answer “ok sir” or something like this :).

And voilà :)


Contact

If you find any issue or have any question about this article, feel free to reach out to me via email, mastodon, matrix or even IRC, see the About Me page for details.

See Also

2018 is here

Kalliope reminder with snooze