Skip to content

Commit

Permalink
Changed Google Music to have its stream act more like a list, since t…
Browse files Browse the repository at this point in the history
…he URLs expire in 60s
  • Loading branch information
deckerego committed Feb 4, 2017
1 parent c251786 commit f99ae13
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 45 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ home/pi/hack-clock/backups/run_clock.*
home/pi/hack-clock/backups/blocks_clock.*
home/pi/hack-clock/blocks_clock.xml
home/pi/hack-clock/run_clock.py
tests/localsettings.conf
2 changes: 1 addition & 1 deletion etc/default/hack-clock
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ BUTTON_BCM_PIN=(23 24)
SWITCH_BCM_PIN=(25)

# Volume level to feed to ALSA SoftVol
MASTER_VOLUME='75%'
MASTER_VOLUME='65%'
41 changes: 32 additions & 9 deletions lib/hackclock/runapp/Libs/GoogleMusic.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,58 @@
from gmusicapi import Mobileclient
from GStreamer import Speaker
from gmusicapi import exceptions
import logging
from hackclock.config import configuration
import json

logger = logging.getLogger('google_music')

console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setLevel(logging.WARNING)
logger.addHandler(console)

class GoogleMusic:
class AudioStream:
__username = configuration.get('google_username')
__password = configuration.get('google_password')
__track_prefetch = 25
__track_prefetch = 15
__client = None
__playlist = []

def __init__(self):
def __init__(self, station_id = 'IFL'):
self.__client = Mobileclient()
self.__client.login(self.__username, self.__password, Mobileclient.FROM_MAC_ADDRESS)
self.__playlist = self.__fetchTrackIDs(station_id)

def __del__(self):
if self.__client:
self.__client.logout()

def radioPlaylist(self, station_id = 'IFL'):
def __fetchTrackIDs(self, station_id):
if not self.__client or not self.__client.is_authenticated():
logger.error("Client is not authenticated!")
return []

tracklist = self.__client.get_station_tracks(station_id, num_tracks=self.__track_prefetch)
logger.info("Received tracks: %r" % str(tracklist))
logger.info("Received tracks: %r" % json.dumps(tracklist))

trackidlist = [track['id'] for track in tracklist if 'id' in track]
return [self.__client.get_stream_url(trackid, quality='low') for trackid in trackidlist]
songids = [track['id'] for track in tracklist if 'id' in track]
nautids = [track['nid'] for track in tracklist if 'nid' in track]

return songids + nautids

def pop(self):
while self.__playlist:
try:
track_id = self.__playlist.pop()
stream_url = self.__client.get_stream_url(track_id, quality='low')
return stream_url
except(exceptions.CallFailure):
logger.warning("Failed to fetch Stream URL for ID %s" % trackid)

raise IndexError("pop from empty list")

def reverse(self):
# Reverse just returns itself, since the playlist is already chaos
return self

def __len__(self):
return len(self.__playlist)
23 changes: 16 additions & 7 deletions lib/hackclock/webapp/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def python_lesson_event_loop(clock, file_id):
try:
code_file = open(lesson_file, 'r')
python_save_event_loop(clock, code_file)
return template('python/editor', switch_visible=switch_visible, status="Saved")
return template('python/editor', switch_visible=switch_visible, status="Opened")
except:
return template('python/editor', switch_visible=switch_visible, status="Failed")

Expand All @@ -161,7 +161,7 @@ def python_restore_event_loop(clock, file_id):
try:
code_file = open(restored_file, 'r')
python_save_event_loop(clock, code_file)
return template('python/editor', switch_visible=switch_visible, status="Saved")
return template('python/editor', switch_visible=switch_visible, status="Opened")
except:
return template('python/editor', switch_visible=switch_visible, status="Failed")

Expand All @@ -181,7 +181,10 @@ def send_blocks_js(filename):
@application.get('/blocks/edit')
def blocks_edit_event_loop(clock):
switch_visible = not configuration.get('disable_editor_button')
return template('blocks/editor', switch_visible=switch_visible, status="Opened")
google_music = configuration.get('google_username') and configuration.get('google_password')
ifttt_maker = configuration.get('ifttt_maker_key')

return template('blocks/editor', switch_visible=switch_visible, google_music=google_music, ifttt_maker=ifttt_maker, status="Opened")

@application.get('/blocks/read')
def blocks_read_event_loop(clock):
Expand Down Expand Up @@ -258,29 +261,35 @@ def blocks_backup_list(clock):
def blocks_lesson_event_loop(clock, file_id):
lesson_dir = configuration.get('lesson_files')
lesson_file = "%s/%s/blocks_clock.xml" % (lesson_dir, file_id)

switch_visible = not configuration.get('disable_editor_button')
google_music = configuration.get('google_username') and configuration.get('google_password')
ifttt_maker = configuration.get('ifttt_maker_key')

try:
code_file = open(lesson_file, 'r')
blocks_save_event_loop(clock, code_file)
return template('blocks/editor', switch_visible=switch_visible, status="Saved")
return template('blocks/editor', switch_visible=switch_visible, google_music=google_music, ifttt_maker=ifttt_maker, status="Opened")
except:
return template('blocks/editor', switch_visible=switch_visible, status="Failed")
return template('blocks/editor', switch_visible=switch_visible, google_music=google_music, ifttt_maker=ifttt_maker, status="Failed")

@application.get('/blocks/restore/<file_id:int>')
def blocks_restore_event_loop(clock, file_id):
version_dir = configuration.get('backup_files')
files = listdir(version_dir)
restored_files = filter(lambda f: f.startswith('blocks_clock.') and int(parser.parse(f.lstrip("blocks_clock.")).strftime("%s")) == file_id, files)
restored_file = "%s/%s" % (version_dir, restored_files[0])

switch_visible = not configuration.get('disable_editor_button')
google_music = configuration.get('google_username') and configuration.get('google_password')
ifttt_maker = configuration.get('ifttt_maker_key')

try:
code_file = open(restored_file, 'r')
blocks_save_event_loop(clock, code_file)
return template('blocks/editor', switch_visible=switch_visible, status="Saved")
return template('blocks/editor', switch_visible=switch_visible, google_music=google_music, ifttt_maker=ifttt_maker, status="Opened")
except:
return template('blocks/editor', switch_visible=switch_visible, status="Failed")
return template('blocks/editor', switch_visible=switch_visible, google_music=google_music, ifttt_maker=ifttt_maker, status="Failed")

# Clock REST API
@application.post('/clock/restart')
Expand Down
4 changes: 4 additions & 0 deletions srv/hackclock/views/blocks/editor.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@
<category name="Audio" colour="240">
<block type="speaker"></block>
<block type="play_list"></block>
% if google_music:
<block type="google_music_radio"></block>
% end
<block type="is_playing"></block>
<block type="audio_stop"></block>
</category>
Expand All @@ -132,9 +134,11 @@
<block type="weather_station"></block>
<block type="current_temp"></block>
</category>
% if ifttt_maker:
<category name="IFTTT" colour="330">
<block type="maker_send"></block>
</category>
% end
<category name="Loops" colour="360">
<block type="controls_repeat_ext">
<value name="TIMES">
Expand Down
6 changes: 3 additions & 3 deletions srv/hackclock/views/blocks/js/generators/audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ Blockly.Python['speaker'] = function(block) {

Blockly.Python['google_music_radio'] = function(block) {
Blockly.Python.definitions_['import_speaker'] = 'from hackclock.runapp.Libs.GStreamer import Speaker';
Blockly.Python.definitions_['import_googlemusic'] = 'from hackclock.runapp.Libs.GoogleMusic import GoogleMusic';
Blockly.Python.definitions_['import_googlemusic'] = 'from hackclock.runapp.Libs.GoogleMusic import AudioStream';
Blockly.Python.definitions_['init_speaker'] = 'speaker = Speaker()';
Blockly.Python.definitions_['init_googlemusic'] = 'google_music = GoogleMusic()';
Blockly.Python.definitions_['init_googlemusic'] = 'audio_stream = AudioStream()';

return ['google_music.radioPlaylist()', Blockly.Python.ORDER_NONE];
return ['audio_stream', Blockly.Python.ORDER_NONE];
};

Blockly.Python['play_list'] = function(block) {
Expand Down
10 changes: 3 additions & 7 deletions tests/googlemusic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#/bin/python

print "Loading Libraries"
from GoogleMusic import GoogleMusic
from GoogleMusic import AudioStream
import pygst
pygst.require('0.10')
import gst
Expand All @@ -13,16 +13,12 @@ def on_tag(bus, msg):
print '\t%s = %s' % (key, taglist[key])

print "Initializing Google Music"
music = GoogleMusic()

print "Fetching Playlist"
playlist = music.radioPlaylist()
print playlist
audio_stream = AudioStream()

print "Initializing Player"
player = gst.element_factory_make("playbin", "player")
player.set_state(gst.STATE_READY)
player.set_property('uri', playlist[0])
player.set_property('uri', audio_stream.pop())
player.set_state(gst.STATE_PLAYING)

print "Monitoring Bus"
Expand Down
16 changes: 0 additions & 16 deletions tests/localsettings.conf

This file was deleted.

5 changes: 3 additions & 2 deletions tests/max_volume.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/sh

amixer set PCM -- 100%
speaker-test -c 2
rm ~/.asoundrc
amixer set Master -- 100%
speaker-test -c2 -twav

0 comments on commit f99ae13

Please sign in to comment.