#!/usr/bin/env python3 # -*- coding: utf-8 -*- # SPDX-FileCopyrightText: 2009,2010,2012,2019 kaliko # SPDX-License-Identifier: GPL-3.0-or-later import sys import argparse from time import sleep from os.path import basename import musicpd VERSION = '0.2' class Nalbum(musicpd.MPDClient): script_info = dict({ 'prog': basename(__file__), 'description': 'Jump to next album in playlist.', 'epilog': 'Set MPD host/port in env. var' }) def __init__(self): musicpd.MPDClient.__init__(self) self.args = self._get_args() self._run() def _get_args(self): parser = argparse.ArgumentParser(**self.__class__.script_info) parser.add_argument('--version', action='version', version='v%s' % VERSION) parser.add_argument('-c', '--cross-fade', type=int, dest='time', help='fade out/fade in over t seconds.',) args = parser.parse_args() return args def _setvol(self, vol): """ Sometimes while fading in on next album, MPD fails. Log shows : "exception: Failed to set mixer for 'My Pulse Output': disconnected" python-musicpd then raises "[52@0] {setvol} problems setting volume" """ try: self.setvol(int(vol)) except musicpd.CommandError as err: print('MPD raised "%s"' % err) print('Try to set the output with \'always_on "yes"\'') if 'problems setting volume' in str(err): sleep(.1) self._setvol(int(vol)) def _fade(self, mpd_vol, io='out'): """ end_volum => End volume value start_vol => Start volume value """ if io == 'out': end_volum = mpd_vol // 10 start_vol = mpd_vol if io == 'in': end_volum = mpd_vol start_vol = mpd_vol // 10 # print(start_vol, end_volum) span = float(end_volum - start_vol) step = span / float(10*self.args.time) if step == 0: return True while True: start_vol += step self._setvol(int(start_vol)) if abs(start_vol - end_volum) < 1.1*abs(step): self._setvol(end_volum) return True sleep(0.1) def _get_next(self): """Retrieve playlist from current song to the end.""" if 'song' not in self.status(): print('No current song set in MPD!') self.disconnect() sys.exit(0) current_album = str(self.currentsong().get('album', 'TAG MISSING')) current_song_pos = int(self.currentsong().get('pos')) print('Current album: "%s"' % current_album) next_album_pos = current_song_pos album = current_album while album == current_album: next_album_pos += 1 pl_length = int(self.status().get('playlistlength')) - 1 if pl_length < next_album_pos: print('Next album not found in the playlitst!') self.disconnect() sys.exit(0) album = self.playlistinfo(next_album_pos)[ 0].get('album', 'TAG MISSING') print('Next album appears to be: "%s"' % album) return next_album_pos def _run(self): self.connect() nalbum = self._get_next() init_vol = int(self.status().get('volume', 0)) if self.args.time: print('Cross fading next album') self._fade(init_vol) self.play(nalbum) if self.args.time: self._fade(init_vol, io='in') self.disconnect() sys.exit(0) # Script starts here if __name__ == '__main__': try: Nalbum() except KeyboardInterrupt: sys.stdout.write('exit') # VIM MODLINE # vim: ai ts=4 sw=4 sts=4 expandtab