lunes, abril 09, 2018

Applescript y Spotify: Uso del API para hacer un sistema de notificaciones

En MacOS X, el cliente de Spotify tiene un API accesible a través de Applescript, que permite controlar el reproductor y obtener información sobre las pistas que están sonando (álbum, artista, portada, etc). Está un poco limitado: no permite gestionar las listas de reproducción de manera sencilla.

Mi idea original era utilizar algún tipo de script que me permitiera gestinar mis listas de reproducción y hacer una copia de seguridad de la misma, así como ver la posibilidad de sincronización con otras aplicaciones. Sin embargo, el API no permite esta funcionalidad - al menos, de manera directa - , así que por hacer una prueba con el mismo, he implementado un pequeño script que se ejecuta desde los launch agents, comprobando cada cierto tiempo si está corriendo Spotify, en caso de que así sea, cuál es la canción que está reproduciendo y se compara con la anterior. En caso de que sea nueva, se muestra una notificación con la nueva canción que se ha empezado.

El script que implementa eso es el siguiente:

-- This script will loop if Spotify is running, showing a notification each time a new 
-- track is playing
use framework "Foundation"
use scripting additions
on getCurrentlyPlayingTrack()
  tell application "Spotify"
    set currentArtist to artist of current track as string
    set currentTrack to name of current track as string
    set currentAlbum to album of current track as string
    set theText to currentArtist & " - " & ¬
      currentAlbum & " - " & ¬
      currentTrack
    return theText
  end tell
end getCurrentlyPlayingTrack

on run
  set currentTrackID to ""
  repeat
    if application "Spotify" is running then
      tell application "Spotify"
        if player state is stopped or player state is paused then
          current application's NSThread's sleepForTimeInterval:2
        else
          set tmpTrackID to id of current track
          if tmpTrackID = currentTrackID then
            current application's NSThread's sleepForTimeInterval:2
          else
            display notification my getCurrentlyPlayingTrack()
            set currentTrackID to tmpTrackID
          end if
        end if
      end tell
    end if
    current application's NSThread's sleepForTimeInterval:2
  end repeat
end run

Las dos partes más interesantes de este script son aquellas partes que interaccionan con Spotify y la técnica usada para realizar una espera activa.

La interacción a través del API, nos permite saber cual es el estado actual del player, player state, que puede ser playing, paused o stoped:

tell application "Spotify"
  if player state is playing then
    display dialog "Player running"
  else if player state is paused then
    display dialog "Player paused"
  else if player is stopped then
    display dialog "Player is stopped"
  else
    display dialog "Unknow state"
  end if
end tell

Por otra parte, se obtiene información de la pista actual seleccionada en el reproductos con current track:

tell application "Spotify"
  set currentArtist to artist of current track as string
  set currentTrack to name of current track as string
  set currentAlbum to album of current track as string
  set theText to currentArtist & " - " & ¬
    currentAlbum & " - " & ¬
    currentTrack
  display dialog theText
end tell

El resto de las propiedades pueden verse añadiendo la aplicación al Editor de Script y viend las propiedades del objeto: Se puede controlar el volumen, la pista que se está reproduciendo, pasar a la siguiente pista, a la anterior...

Puede que nos interese que este script siempre se esté ejecutando, pero claro, no nos interesa estar haciendo espera activa, usar la funcionalidad presente en las versiones de AppleScript incluidas a partir de Yosemite, de llamar a clases de Objective-C, en vez de usar el comando delay, hago un sleep para que el control se ceda a otro hilo:

use framework "Foundation"
use scripting additions
current application's NSThread's sleepForTimeInterval:2

Para que nuestro pequeño script se arranque cada vez que entremos en el ordenador, lo ideal es implementarlo como un un Launch Agente. Si nuestro script está grabado en la ruta ~/Library/Scripts/spotify.scpt, se puede crear un fichero XML en ~/Library/LaunchAgents y cargarlo en el sistema con ayuda de launctl. Si creamos en el directorio de agentes un fichero que podemos llamar local.spotify.nexttrack.plist con el siguiente contenido:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>local.spotify.nexttrack</string>
  <key>ProgramArguments</key>
  <array>
    <string>sh</string>
    <string>-c</string>
    <string>osascript "$HOME/Library/Scripts/spotifyon.scpt"</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Y ahora, lo ponemos bajo supervisión del launchd, que lo lanzará cada vez que nos loguemos en el sistema:

cd ~/Library/LaunchAgents
launchctl load local.spotify.nexttrack.plist

Tal como está desarrollado el script, este hará un bucle, comprobará si está Spotify ejecutándose. De ser así, mirará el estado del reproductos, y si está reproduciendo y la pista es distinta a la anterior, mostrará una notificación.

No hay comentarios: