def get_my_library_artists(self, from_cache=True): _cache = os.path.join(utils.get_cache_dir(['library']), 'artists.json') artists = [] if os.path.exists(_cache) and from_cache: with open(_cache, 'r') as f: artists = json.loads(f.read()) else: songs = self.get_my_library_songs() songs = self._uniquify(songs, 'albumArtist') for song in songs: if ('artistId' not in song or 'title' not in song): utils.log('Skipping broken entry:', json.dumps(song), lvl=xbmc.LOGERROR) continue _art = thumbs.IMG_ARTIST if 'artistArtRef' in song and len(song['artistArtRef']) > 0: _art = song['artistArtRef'][0]['url'] artist = { 'artistId': song['artistId'][0], 'name': song['albumArtist'], 'artistArtRef': _art } artists.append(artist) artists = sorted(artists, key=itemgetter('name')) with open(_cache, 'w+') as f: f.write(json.dumps(artists)) return artists
def on_call_started(data): utils.log('Received call start event') addon = xbmcaddon.Addon() player = xbmc.Player() data = utils.execute_jsonrpc('Application.GetProperties', {'properties': ['volume']}) if data and 'volume' in data: volume = data['volume'] addon.setSetting('saved_volume', str(volume)) action = Action.NOTHING volume = 0 if player.isPlayingAudio(): action = int(addon.getSetting('music.on_call')) volume = int(addon.getSetting('music.volume')) elif player.isPlayingVideo(): action = int(addon.getSetting('video.on_call')) volume = int(addon.getSetting('video.volume')) if action == Action.MUTE: if not xbmc.getCondVisibility('Player.Muted'): xbmc.executebuiltin('Mute') elif action == Action.PAUSE: if not xbmc.getCondVisibility('Player.Paused'): player.pause() elif action == Action.VOLUME and volume: xbmc.executebuiltin('XBMC.SetVolume({}, showvolumebar)'.format(volume)) return True
def _serve(self): utils.log('Server started, handling requests now') while not self._exit.is_set(): self._is_alive.set() self.handle_request() self._is_alive.clear()
def is_authorized(self): try: addon = xbmcaddon.Addon() except RuntimeError: # When the addon gets disabled and the dummy request get sent, # this will happen return False is_auth_enabled = addon.getSetting('server.auth_enabled') if is_auth_enabled == 'false': return True username = addon.getSetting('server.username') password = addon.getSetting('server.password') if 'Authorization' in self.headers: auth = self.headers['Authorization'].split()[1].decode('base64') user = auth.split(':')[0] pwd = auth.split(':')[1] if user == username and pwd == password: return True utils.log('Not authorized') return False
def _make_call(self, protocol, *args, **kwargs): try: return super(GMusic, self)._make_call(protocol, *args, **kwargs) except: utils.notify(utils.translate(30050), utils.translate(30051)) utils.log(traceback.format_exc(), lvl=xbmc.LOGERROR) return None
def serve_forever(self): if self.is_alive(): utils.log('Server already running. Skipping!') return t = threading.Thread(target=self._serve) t.daemon = True t.start()
def on_notification_posted(data): utils.log('Received new notification') # Get title and message title = data['title'] message = '' if data['bigText']: message = data['bigText'] elif data['text']: message = data['text'] elif data['tickerText']: message = data['tickerText'] if data['subText']: message = '{} {}'.format(message, data['subText']) message = message.replace('\n', ' ').replace('\r', ' ') # Get an icon to display large_icon_data = data['largeIcon']['data'] app_icon_data = data['appIcon']['data'] small_icon_data = data['smallIcon']['data'] icon = None icon_path = None if large_icon_data: icon = large_icon_data icon_path = os.path.join(CACHE_DIR, hashlib.md5(large_icon_data).hexdigest()) elif app_icon_data: icon = app_icon_data icon_path = os.path.join(CACHE_DIR, hashlib.md5(app_icon_data).hexdigest()) elif small_icon_data: icon = small_icon_data icon_path = os.path.join(CACHE_DIR, hashlib.md5(small_icon_data).hexdigest()) if not os.path.exists(icon_path): with open(icon_path, 'wb') as f: f.write(icon.decode('base64')) addon = xbmcaddon.Addon() play_sound = addon.getSetting('notification.play_sound') == 'true' display_time = int(addon.getSetting('notification.display_time')) * 1000 xbmcgui.Dialog().notification(title, message, icon_path, display_time, play_sound) return True
def list_shows_schedule(network, page=1): aa = addict.AudioAddict.get(PROFILE_DIR, network) xbmcplugin.setPluginCategory(HANDLE, aa.name) shows = aa.get_upcoming() shows = sorted(shows, key=lambda s: s['start_at']) # Shows for "get_upcoming" have "following" always set to False # Have to work around this for now :/ followed_shows = aa.get_shows_followed() followed_slugs = [s.get('slug') for s in followed_shows] now = addict.datetime_now() active = utils.get_playing() or {} utils.log('active item', active) items = [] for show in shows: end_at = addict.parse_datetime(show.get('end_at')) if end_at < now: continue start_at = addict.parse_datetime(show.get('start_at')) show = show.get('show', {}) channel = show.get('channels', [])[0] item = utils.build_show_item(network, show, followed_slugs) item.setPath( utils.build_path('play', 'channel', network, channel.get('key'), live=show.get('now_playing', False))) if show.get('now_playing', False): label_prefix = utils.translate(30333) # Live now item.setProperty('IsPlayable', 'false') if (active.get('is_live', False) and active.get('channel') == channel.get('key')): item.select(True) else: label_prefix = '{} - {}'.format(start_at.strftime('%H:%M'), end_at.strftime('%H:%M')) item.setLabel('[B]{}[/B] - {} [I]({})[/I]'.format( label_prefix, _enc(show.get('name')), _enc(channel.get('name')))) items.append((item.getPath(), item, False)) utils.list_items(items)
def on_call_ended(data): utils.log('Received call end event') addon = xbmcaddon.Addon() player = xbmc.Player() action = Action.NOTHING reset_vol = False if player.isPlayingAudio(): action = int(addon.getSetting('music.on_call')) unmute = addon.getSetting('music.unmute') == 'true' play_after = addon.getSetting('music.play_after') == 'true' reset_vol = addon.getSetting('music.reset_volume') == 'true' elif player.isPlayingVideo(): action = int(addon.getSetting('video.on_call')) unmute = addon.getSetting('video.unmute') == 'true' play_after = addon.getSetting('video.play_after') == 'true' reset_vol = addon.getSetting('video.reset_volume') == 'true' if action == Action.MUTE and unmute: if xbmc.getCondVisibility('Player.Muted'): xbmc.executebuiltin('Mute') elif action == Action.PAUSE and play_after: if xbmc.getCondVisibility('Player.Paused'): player.pause() elif action == Action.VOLUME and reset_vol: try: volume = int(addon.getSetting('saved_volume')) xbmc.executebuiltin( 'XBMC.SetVolume({}, showvolumebar)'.format(volume)) except Exception: pass return True
def exit(self): utils.log('Exit requested') self._exit.set() self._exit.wait() utils.log('Exit flag was set') try: addr = 'http://{}:{}'.format(self.server_address[0], self.server_address[1]) utils.log('Sending dummy request to:', addr) xmlrpclib.Server(addr).ping() except Exception: pass utils.log('Shutdown complete')
def on_notification_removed(data): utils.log('Received notification delete event') return True
def get_my_library_songs(self, from_cache=True): _cache = os.path.join(utils.get_cache_dir(['library']), 'songs.json') _song_cache_path = utils.get_cache_dir(['library', 'songs']) songs = None if os.path.exists(_cache) and from_cache: with open(_cache, 'r') as f: songs = json.loads(f.read()) else: generator = self.get_all_songs(incremental=True, include_deleted=False) tmp = [] for songs in generator: tmp += songs songs = tmp # Generate artistId and albumId in case they are # missing (applies to user uploaded songs without # a matching entry in googles database) for i, song in enumerate(songs): if ('title' not in song or 'album' not in song or 'artist' not in song): utils.log('Skipping broken entry:', json.dumps(song), lvl=xbmc.LOGERROR) continue if 'artistId' not in song: songs[i]['artistId'] = [str(uuid.uuid4())] if 'albumId' not in song: songs[i]['albumId'] = str(uuid.uuid4()) with open(_cache, 'w+') as f: f.write(json.dumps(songs)) # Save each song as separate file # for easier and quicker access for song in songs: # Main id file _target = os.path.join(_song_cache_path, song['id']) with open(os.path.join(_target), 'w+') as f: f.write(json.dumps(song)) # Other available ids which we create symlinks for for _id in ['trackId', 'storeId']: if _id not in song: continue _link = os.path.join(_song_cache_path, song[_id]) if os.path.exists(_link) and os.path.islink(_link): continue try: # On unix systems we simply create a symlink os.symlink(_target, _link) except: # On other systems (*cough* windows *cough*) we just # write another version of the file with open(os.path.join(_link), 'w+') as f: f.write(json.dumps(song)) return songs
def get_new_releases(self, num_items=25, genre=None): res = self._make_call(mobileclient.GetNewReleases, num_items, genre) utils.log(json.dumps(res, indent=2), lvl=xbmc.LOGERROR) for tabs in res['tabs']: if tabs['tab_type'] == 'NEW_RELEASES': return tabs['groups'][0]['entities']
def monitor_live(skip_shows=None): if not skip_shows: skip_shows = [] now = addict.datetime_now() addon = xbmcaddon.Addon() for network in addict.NETWORKS.keys(): aa = addict.AudioAddict.get(PROFILE_DIR, network) if not aa.is_active or not aa.network['has_shows']: continue followed = [s.get('slug') for s in aa.get_shows_followed()] shows = aa.get_live_shows() live_show_ids = [s.get('id') for s in shows] # Remove shows which are not live anymore skip_shows = [i for i in skip_shows if i in live_show_ids] for show in shows: if show.get('id') in skip_shows: continue end_at = addict.parse_datetime(show.get('end_at')) if end_at < now: continue skip_shows.append(show.get('id')) _show = show.get('show') if _show.get('slug') in followed and addon.getSettingBool( 'addon.notify_live'): utils.notify('[B]{}[/B] is live!'.format(_show.get('name'))) if addon.getSettingBool('addon.tune_in_live'): filename = xbmc.getInfoLabel('Player.Filenameandpath') if not filename: continue playing = utils.get_playing() if not playing: continue chan = _show.get('channels', [])[0] if (playing['network'] != network or playing['channel'] != chan.get('key')): utils.logd( 'Different network/channel playing, not tuning in.') continue if playing['live']: utils.logd('Live stream already playing.') break time_left = (end_at - now).seconds if time_left < 2: utils.log('Less than 2 minutes left, not tuning in.') break utils.log('Tuning in to live stream...') xbmc.executebuiltin('RunPlugin({})'.format( utils.build_path('play', network, playing['channel'], live=True))) return skip_shows
def on_call_missed(data): utils.log('Received call missed event') return True
def log_message(self, format, *args): utils.log("{} - - [{}] {}\n".format(self.address_string(), self.log_date_time_string(), format % args))