--- /dev/null
+dist
+build
+mpd_goodies.egg-info
+__pycache__
--- /dev/null
+mpd-goodies (0.1.0)
+
+Initial release.
+
+ * Convert previous code to python3
+ * Switch to python-musicpd
+ * Move to git
+
+UNRELEASED
+++ /dev/null
-Default installation in /usr/{bin,share/,share/man}.
-
-Makefile supports both DESTDIR and PREFIX GNU standards.
-
-Just call install target to have mpd-goodies installed within /usr
-
- make install
-
-If you need to install it somewhere else use PREFIX variable.
-For instance installing in /usr/local directory:
-
- make PREFIX=/usr/local install
-
-Run uninstall target to remove.
--- /dev/null
+include CHANGELOG.md
+++ /dev/null
-SHELL = /bin/sh
-PREFIX = /usr
-#DESTDIR = /tmp/mpd-goodies
-LIBDIR = $(DESTDIR)$(PREFIX)/lib
-BIN = $(DESTDIR)$(PREFIX)/bin
-ETC = $(DESTDIR)$(PREFIX)/etc
-DATADIR = $(DESTDIR)$(PREFIX)/share
-LOCALEDIR = $(DATADIR)/locale
-MANDIR = $(DATADIR)/man
-PKGNAME = mpd-goodies
-
-all: man bin
-#clean:
-# rm -f mpd-goodies.1.gz
-
-mpd-goodies.1.gz:
- cat data/mpd-goodies.1 | gzip > mpd-goodies.1.gz
-
-bash_completion:
- install -d $(ETC)/bash_completion.d
- install -m644 data/mpd-goodies.sh $(ETC)/bash_completion.d/
- mv $(ETC)/bash_completion.d/mpd-goodies.sh $(ETC)/bash_completion.d/$(PKGNAME)
-
-man: mpd-goodies.1.gz
-
-install:
- install -d $(BIN) $(DATADIR)/$(PKGNAME) #$(MANDIR)/man1
-
- #install -m644 mpd-goodies.1.gz $(MANDIR)/man1
-
- # listing all sub folder to install (prevent a remaining .svn directory to be install)
- for sourcedir in `find src/ -name .svn -prune -o -type d -print | sed 's:src/::g'` ; do \
- install -d $(DATADIR)/$(PKGNAME)/$$sourcedir; \
- for sourcefile in `find src/$$sourcedir -maxdepth 1 -name *pyc -o -name .svn -prune -o -print` ; do \
- install -m644 $$sourcefile $(DATADIR)/$(PKGNAME)/$$sourcedir; \
- done \
- done
- # listing all command in ./src
- for command in `find src/ -maxdepth 1 -name .svn -prune -o -type f -print` ; do \
- install -m 755 $$command $(DATADIR)/$(PKGNAME)/ ;\
- done
- for command in `find $(DATADIR)/$(PKGNAME)/ -maxdepth 1 -name .svn -prune -o -type f -print` ; do \
- ln -sf $$command $(BIN) ;\
- done
-
-uninstall:
- for command in `find $(DATADIR)/$(PKGNAME)/ -maxdepth 1 -name .svn -prune -o -type f -print` ; do \
- rm -rf $(BIN)/$$(basename $$command) ;\
- done
- rm -f $(MANDIR)/man1/mpd-goodies.1.gz
- rm -f $(ETC)/bash_completion.d/$(PKGNAME)
- rm -rf $(DATADIR)/$(PKGNAME)
--- /dev/null
+# MPD-GOODIES
+
+A collection of small commands to play with MusicPlayerDaemon:
+
+ * Fading in/out over a specified time
+ * Jumping to next album en queue.
+ * Last modified artist/album
+ * Crop the queue
+
+[MusicPlayerDaemon]: https://www.musicpd.org/
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- coding: utf-8 -*-
-# Copyright (c) 2009, 2010, 2012 Kaliko Jack <efrim@azylum.org>
+# Copyright (c) 2009,2010,2012,2019 kaliko <kaliko@azylum.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+import argparse
import sys
-from lib.goodies import Goodie
+from os.path import basename
-NAME = 'crop'
-VERSION = '0.1'
-USAGE = 'USAGE: %prog [--help] | [ <n> ]'
+import musicpd
+VERSION = '0.2'
-class Crop(Goodie):
- """
- """
+
+class Crop(musicpd.MPDClient):
script_info = dict({
- 'version': VERSION,
- 'prog_name': NAME,
+ 'prog': basename(__file__),
'description': 'Keep <n> tracks before currently played, removed others. Default is to keep 6 tracks.',
- 'usage': USAGE,
- })
+ 'epilog': 'Set MPD host/port in env. var'
+ })
def __init__(self):
""""""
- Goodie.__init__(self, self.__class__.script_info)
+ musicpd.MPDClient.__init__(self)
self.nb_tracks = 6
- self._get_arg()
+ self._get_args()
self._run()
- def _get_arg(self):
+ def _get_args(self):
""""""
- if not self.cli_args:
- return True
- try:
- self.nb_tracks = int(self.cli_args[0])
- except ValueError, err:
- self.parser.error('invalid argument, not a natural number? (%s)' % err)
+ parser = argparse.ArgumentParser(**self.__class__.script_info)
+ parser.add_argument('--version', action='version',
+ version='v%s' % VERSION)
+ parser.add_argument('n', type=int, nargs='?',
+ help='how many titles to crop')
+ args = parser.parse_args()
+ if args.n:
+ self.nb_tracks = args.n
def _run(self):
""""""
- print 'Connecting %s:%i' % (self.cli_options.host, self.cli_options.port)
- print 'Keeping %i tracks' % self.nb_tracks
- self.mpdConnect()
- current_pos = int(self.client.currentsong().get('pos', 0))
+ self.connect()
+ current_pos = int(self.currentsong().get('pos', 0))
if current_pos <= self.nb_tracks:
- self.client.disconnect()
+ self.disconnect()
sys.exit(0)
+ print('Keeping %i tracks' % self.nb_tracks)
while current_pos > self.nb_tracks:
- self.client.delete(0)
- current_pos = int(self.client.currentsong().get('pos', 0))
- self.client.disconnect()
+ self.delete(0)
+ current_pos = int(self.currentsong().get('pos', 0))
+ self.disconnect()
sys.exit(0)
--- /dev/null
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009,2010,2012,2019 kaliko <kaliko@azylum.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""
+DOC:
+ heavily borrowed from perl script mpdtoys and converted to python.
+ mpdtoys © 2007 Joey Hess <joey@kitenet.net>
+ http://kitenet.net/~joey/code/mpdtoys
+"""
+
+import argparse
+import sys
+
+from time import sleep
+from os.path import basename
+
+import musicpd
+
+
+VERSION = '0.2'
+DESC = """Fade in/out to <final volume level> over <time>.
+Defaults are from 0% to 50% when paused or stopped
+and from current volume to 10th of it if playing,
+both over 10 minutes."""
+DESC = """Fade in/out to <final volume level> over <time>.
+Defaults are from 0% to 50% when paused or stopped and from current volume to 10th of it if playing, both over 10 minutes."""
+EPILOG = """You might need to set your audio_output with "always_on yes" for
+this command to work properly.
+
+Set MPD host/port in env. var"""
+
+class Sleep(musicpd.MPDClient):
+ """"""
+ script_info = dict({
+ 'prog': basename(__file__),
+ 'description': DESC,
+ 'epilog': EPILOG,
+ 'formatter_class': argparse.RawDescriptionHelpFormatter,
+ })
+
+ def __init__(self):
+ """"""
+ musicpd.MPDClient.__init__(self)
+ self.tempo = 600
+ self.volum = None
+ self._get_args()
+ self._run()
+
+ def _test_volume_access(self):
+ status = self.status()
+ if 'volume' not in status:
+ print('Mixer not available!')
+ print('Try to set the always_on audio_output option on.')
+ sys.exit(1)
+
+ def _get_args(self):
+ """"""
+ parser = argparse.ArgumentParser(**self.__class__.script_info)
+ parser.add_argument('--version', action='version',
+ version='v%s' % VERSION)
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument('-m', '--minutes', type=int,
+ help='duration to fade in/out over')
+ group.add_argument('-s', '--seconds', type=int,
+ help='duration to fade in/out over')
+ parser.add_argument('volume', type=int, nargs='?',
+ help='final volume level')
+ args = parser.parse_args()
+ if args.minutes:
+ self.tempo = args.minutes*60
+ if args.seconds:
+ self.tempo = args.seconds
+ if args.volume:
+ self.volum = args.volume
+
+ def _run(self):
+ """"""
+ self.connect()
+ self.mpd_state = str(self.status().get('state'))
+ if self.mpd_state == 'play':
+ self.mpd_vol = int(self.status().get('volume'))
+ if not self.volum:
+ self.volum = self.mpd_vol // 10
+ if self.volum > self.mpd_vol:
+ print('Error: specified min volume (%d%%) > to current volume (%d%%)' % (
+ self.volum, self.mpd_vol))
+ sys.exit(1)
+ print('fading down from %d%% to %d%% over %ss' % (self.mpd_vol, self.volum, self.tempo), file=sys.stdout)
+ if self.fade(self.mpd_vol, self.volum):
+ self.stop()
+ elif self.mpd_state in ['stop', 'pause']:
+ self._test_volume_access()
+ if not self.volum:
+ self.volum = int(50)
+ print('fading up from 0%% to %d%% over %ss' % (self.volum, self.tempo), file=sys.stdout)
+ self.mpd_vol = 0
+ self.setvol(0)
+ self.play()
+ self.fade(self.mpd_vol, self.volum)
+
+ def fade(self, mpd_vol, target):
+ """"""
+ # TODO: handle possible lost connections
+ span = target - mpd_vol
+ step = span / (10*self.tempo)
+ vol = mpd_vol
+ if step == 0:
+ return True
+ while True:
+ if int(vol) != int(self.status().get('volume')):
+ sys.stderr.write(
+ 'Warning: external volume change, aborting!\n')
+ return False
+ vol += step
+ self.setvol(int(vol))
+ if abs(vol - target) < 1.1*abs(step):
+ self.setvol(target)
+ return True
+ sleep(.1)
+
+
+# Script starts here
+if __name__ == '__main__':
+ try:
+ Sleep()
+ except KeyboardInterrupt:
+ sys.stdout.write('exit')
+
+# VIM MODLINE
+# vim: ai ts=4 sw=4 sts=4 expandtab
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- coding: utf-8 -*-
-# Copyright (c) 2009, 2010, 2012 Kaliko Jack <kaliko.jack@azylum.org>
+# Copyright (c) 2009,2010,2012,2019 kaliko <kaliko@azylum.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-
+import argparse
import sys
-
from datetime import timedelta
+import musicpd
-from lib.goodies import Goodie
-
+VERSION = '0.2'
-NAME = 'mtime'
-VERSION = '0.1'
-NALBUM_OPTS = list([
- {
- 'sw': ['-r', '--remaining'],
- 'action': 'store_true',
- 'dest': 'remaining',
- 'metavar': 'r',
- 'help': 'print remaining play time (only relevant when paused or playing).'},
- {
- 'sw': ['-H', '--human'],
- 'action': 'store_true',
- 'dest': 'human',
- 'metavar': 'h',
- 'help': 'print duration in human readable format.'},
- ])
-
-
-class Nalbum(Goodie):
- """
- """
+class Mtime(musicpd.MPDClient):
script_info = dict({
- 'version': VERSION,
- 'prog_name': NAME,
+ 'prog': 'mtime',
'description': 'Print current playlist duration.',
- })
+ 'epilog': 'Set MPD host/port in env. var'
+ })
def __init__(self):
- """"""
- Goodie.__init__(self, self.__class__.script_info,
- extra_options=NALBUM_OPTS)
+ 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('-r', '--remaining', action='store_true', dest='remaining',
+ help='print remaining play time (only relevant when paused or playing).',)
+ parser.add_argument('-H', '--human', action='store_true', dest='human',
+ help='print duration in human readable format.',)
+ args = parser.parse_args()
+ return args
+
def _print_time(self, duration):
- if self.cli_options.human:
+ if self.args.human:
print(timedelta(seconds=duration))
else:
print(duration)
def _run(self):
- """"""
- self.mpdConnect()
- status = self.client.status()
- plinfo = self.client.playlistinfo()
+ self.connect()
+ status = self.status()
+ plinfo = self.playlistinfo()
total_time = 0
- if self.cli_options.remaining:
+ if self.args.remaining:
if status.get('state') in ['play', 'pause']:
- total_time = sum(int(trk.get('time')) for trk in plinfo if int(trk.get('pos')) > int(status.get('song')))
+ total_time = sum(int(trk.get('time')) for trk in plinfo if int(
+ trk.get('pos')) > int(status.get('song')))
# add remaining time from current song
curr_elapsed = status.get('time').split(':')
total_time += int(curr_elapsed[1]) - int(curr_elapsed[0])
else:
total_time = sum(int(trk.get('time')) for trk in plinfo)
self._print_time(total_time)
- self.client.disconnect()
+ self.disconnect()
sys.exit(0)
# Script starts here
if __name__ == '__main__':
try:
- Nalbum()
+ Mtime()
except KeyboardInterrupt:
sys.stdout.write('exit')
--- /dev/null
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009,2010,2012,2019 kaliko <kaliko@azylum.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+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
--- /dev/null
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009,2010,2012,2019 kaliko <kaliko@azylum.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import argparse
+import sys
+
+from random import choice
+from os.path import basename
+
+import musicpd
+
+
+VERSION = '0.2'
+
+
+class WakeUp(musicpd.MPDClient):
+ script_info = dict({
+ 'prog': basename(__file__),
+ 'description': 'Queues and plays an album chosen at random from a list. Albums list provided from CLI or text file.',
+ 'epilog': 'Set MPD host/port in env. var'
+ })
+
+ def __init__(self):
+ musicpd.MPDClient.__init__(self)
+ 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('-f', type=argparse.FileType('r'), dest='albumf',
+ help='text file, one album per line', nargs='?')
+ parser.add_argument('album', type=str,
+ nargs='*', help='album name')
+ args = parser.parse_args()
+ if args.albumf:
+ args.album.extend([line.rstrip(' \n')
+ for line in args.albumf.readlines()])
+ if not args.album:
+ # parser.print_help()
+ print(
+ 'No album names found on CLI, run "{} -h" for usage'.format(sys.argv[0]))
+ sys.exit(1)
+ return args.album
+
+ def _run(self):
+ albums_list = self._get_args()
+ album = choice(albums_list)
+ print('Queueing "%s"' % album)
+ self.connect()
+ tracks = self.search('album', album)
+ if not tracks:
+ print('No tracks found for "%s"' % album)
+ self.disconnect()
+ sys.exit(1)
+ self.searchadd('album', album)
+ self.disconnect()
+ sys.exit(0)
+
+
+# Script starts here
+if __name__ == '__main__':
+ try:
+ WakeUp()
+ except KeyboardInterrupt:
+ print('exit')
+
+# VIM MODLINE
+# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-File within this directory (ie. misc) are not really part of mpd-goodies in the
-sens there are not integrated in the framework. There are stand alone scripts.
+++ /dev/null
-# -*- coding: utf-8 -*-
-# This config is python script
-
-## SETTINGS
-#
-## MPD
-#
-# The default are localhost:6600 / no password
-#
-# To set different MPD host/port/password please use environment variables.
-#
-# You may set MPD_HOST/MPD_PORT in your shell rc file
-# or
-# You can launch the script with leading environment variables:
-# $> MPD_HOST=pass@my_mpd_host script.py
-#
-# More details about MPD's environment variables in mpc manual (cf. man 1 mpc),
-# options --host/--port.
-
-## Set JINGLE_TAG here.
-#
-# Set JINGLE_TAG with any combinations of key, value with keys in :
-# artist , album , title , track, filename, […] (cf. man 1 mpc).
-#
-# Uncomment/change one of the following examples
-#
-## Some examples:
-#
-#JINGLE_TAG = {
-# 'filename' : '/radio/jingles/',
-# 'artist' : 'Steve Albini'
-# }
-#JINGLE_TAG = {'comment': 'jingle'}
-#TODO: remove following to release
-JINGLE_TAG = {'artist': 'Magma'}
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-#! /usr/bin/env python\r
-# -*- coding: utf-8 -*-\r
-\r
-# Copyright (c) 2009 Efrim <efrim@azylum.org> {{{\r
-#\r
-# This program is free software: you can redistribute it and/or modify\r
-# it under the terms of the GNU General Public License as published by\r
-# the Free Software Foundation, either version 3 of the License, or\r
-# (at your option) any later version.\r
-#\r
-# This program is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-# GNU General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU General Public License\r
-# along with this program. If not, see <http://www.gnu.org/licenses/>.\r
-#\r
-# }}}\r
-\r
-DOC = """\r
-DOC:\r
-\r
- The script randomly pick up a song to queue from the library.\r
- JINGLE_TAG variable allows you to filter the list of songs the\r
- choice is made from.\r
-\r
- Adjust MPD settings and TAG filtering editing config.py.\r
-\r
- JINGLE_TAG is a dictionary, ie. a list of "key:value" couples, keys\r
- among "artist", "title", "genre", "comment" and many others (cf.\r
- man 1 mpc).\r
-\r
- The search made is a non exact search (search vs. find MPD command),\r
- it allows you /some/ fuzziness in JINGLE_TAG settings.\r
-\r
- To retrieve easily jingles with this script you may set the\r
- "comment" tag to "my jingle" for all your jingle sound files (or\r
- anything else you want as long it is a unique identifier for your\r
- jingles). Then set up JINGLE_TAG to fit this choice:\r
- JINGLE_TAG = {'comment': 'my jingle'}\r
-\r
- PAY ATTENTION:\r
- Be sure tags your using in JINGLE_TAG are among tag types being\r
- extracted during audio track discovery in your MPD server settings.\r
- Refer to “metadata_to_use” option in MPD server configuration.\r
-\r
- An alternate way is to pick up songs from a specific directory\r
- setting "filename" key in JINGLE_TAG:\r
- JINGLE_TAG = {'filename': 'partial/path/to/my jingle'}\r
- JINGLE_TAG = {'filename': 'jingle'}\r
- …etc.\r
-\r
- Refer to config.py file for some examples.\r
-\r
-BUGS:\r
- MPD 0.15 is not correctly updating file tags, so you migth set\r
- comment or another tag to filter jingles and not been able to get\r
- files queued with this script because of that. Please check your\r
- tag is known in MPD database running something like that:\r
-\r
- mpc search <tag> <my value>\r
-\r
- Issue fixed in MPD 0.16\r
- MPD bugs: http://musicpd.org/mantis/view.php?id=498\r
-"""\r
-\r
-__version__ = u'0.3'\r
-__author__ = u'$Author: kaliko $'\r
-__date__ = u'$LastChangedDate: 2009-11-17 19:23:34 +0100 (mar. 17 nov. 2009) $'[18:28]\r
-\r
-\r
-# IMPORTS {{{\r
-import sys\r
-\r
-from random import choice\r
-try:\r
- from mpd import (CommandError)\r
-except ImportError, err:\r
- print 'ERROR: "%s"\n\nPlease install python-mpd module.\n' % err\r
- sys.exit(1)\r
-\r
-try:\r
- from config import JINGLE_TAG\r
-except ImportError, err:\r
- print 'ERROR: "%s"\n' % err\r
- print '\tPlease set JINGLE_TAG in config.py'\r
- sys.exit(1)\r
-\r
-from lib.mpdutils import (mconnect)\r
-#}}}\r
-\r
-\r
-def search(tags):#{{{\r
- """\r
- Construct search string for MPD search function.\r
- """\r
- search_str = list()\r
- for k, v in tags.iteritems():\r
- search_str.extend([str(k), str(v)])\r
- return search_str#}}}\r
-\r
-\r
-def main():\r
- client = mconnect()\r
- ## List tracks matching JINGLE_TAG and randomly chose one.\r
- try:\r
- trk = choice(client.search(*search(JINGLE_TAG)))\r
- except CommandError, err:\r
- print 'Wrong search command, check JINGLE_TAG settings: %s' % err\r
- sys.exit(1)\r
- except IndexError, err:\r
- print ('Search for "%s" returned nothing: %s' %\r
- (' '.join(search(JINGLE_TAG)), err))\r
- sys.exit(1)\r
-\r
- ## Uncomment to print out file added to playlist\r
- #print 'add "%s"' % trk.get('file')\r
-\r
- client.add(trk.get('file', None))\r
- client.disconnect()\r
- sys.exit(0)\r
-\r
-# Script starts here\r
-if __name__ == "__main__":\r
- if len(sys.argv) > 1:\r
- print DOC\r
- sys.exit(0)\r
- main()\r
-\r
-# VIM MODLINE\r
-# vim: ai ts=4 sw=4 sts=4 expandtab\r
--- /dev/null
+[metadata]
+author = 'kaliko',
+author_email = 'kaliko@azylum.org',
+name = mpd-goodies
+version = 0.1.0
+description = A Collection of goodies for MPD Music Player
+download_url = 'http://git.kaliko.me/?p=mpd-goodies.git'
+url = 'http://kaliko.me/code/mpd-goodies'
+long_description = file: README.md
+keywords = MPD
+license = GPLv3
+classifiers =
+ Development Status :: 5 - Production/Stable
+ Environment :: Console
+ Environment :: No Input/Output (Daemon)
+ Intended Audience :: End Users/Desktop
+ License :: OSI Approved :: GNU General Public License (GPL)
+ Operating System :: POSIX
+ Topic :: Multimedia :: Sound/Audio
+ Topic :: Utilities
+ Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.5
+ Programming Language :: Python :: 3.6
+ Programming Language :: Python :: 3.7
+
+[options]
+install_requires = python-musicpd
+
+[sdist]
+formats=gztar,zip
+
+[bdist_wheel]
+universal = 0
--- /dev/null
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import glob
+
+from setuptools import setup
+
+# cf. setup.cfg
+setup(
+ scripts=glob.glob('bin/*'),
+)
+
+# VIM MODLINE
+# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2012 Kaliko Jack <kaliko.jack@azylum.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-"""
-DOC:
- All goodies inherit from Goodie which in turn inherits from StartOpt and
- MPDClass.
-
- StartOpt deals with command line argument and options, it will look for env.
- var. $MPD_HOST and $MPD_PORT as well
-
- MPDClass is a plain MPD client
-"""
-
-from lib.mpdclass import MPDClass
-from lib.startop import StartOpt
-
-
-class Goodie(StartOpt, MPDClass):
- """"""
-
- def __init__(self, script_info, extra_options=[]):
- """"""
- StartOpt.__init__(self, script_info, extra_options)
- self.con_id = dict({'host': self.cli_options.host,
- 'port': self.cli_options.port})
- MPDClass.__init__(self)
-
-
-# Script starts here
-if __name__ == '__main__':
- pass
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009, 2010, 2012 Kaliko Jack <kaliko.jack@azylum.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-
-import sys
-from socket import error as SocketError
-
-try:
- from mpd import (MPDClient, CommandError)
-except ImportError, err:
- print 'ERROR: "%s"\n\nPlease install python-mpd module.\n' % err
- sys.exit(1)
-
-
-class MPDClass(object):
- """Connect to MPD server
- """
-
- def __init__(self):
- self.client = MPDClient()
-
- def mpdConnect(self):
- """
- Simple wrapper to connect MPD.
- """
- try:
- self.client.connect(**self.con_id)
- except SocketError:
- return False
- return True
-
- def mpdAuth(self, secret):
- """ Authenticate"""
- try:
- self.client.password(secret)
- except CommandError:
- return False
- return True
-
-
-def main():
- pass
-
-# Script starts here
-if __name__ == '__main__':
- main()
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-# -*- coding: utf-8 -*-
-
-from locale import getpreferredencoding
-from optparse import (OptionParser, OptionValueError, SUPPRESS_HELP)
-from os import environ
-
-# Options list
-# pop out 'sw' value before creating OptionParser object.
-OPTS = list([
- {
- 'sw': ['-S', '--hostname'],
- 'type': 'string',
- 'dest': 'host',
- 'help': 'Hostname MPD in running on (default: localhost or MPD_HOST if set)'},
- {
- 'sw': ['-P', '--port'],
- 'type': 'int',
- 'dest': 'port',
- 'help': 'Port MPD in listening on (default: 6600 or MPD_PORT if set)'},
-])
-
-USAGE = u"""USAGE: %prog [--help] [options]"""
-
-
-def get_mpd_environ():
- """
- Retrieve MPD env. var.
- """
- con_id = dict({'host': 'localhost',
- 'port': int(6600)})
- passwd = None
- mpd_host_env = environ.get('MPD_HOST')
- mpd_port = environ.get('MPD_PORT')
- if mpd_host_env:
- # If password is set:
- # mpd_host_env = ['pass', 'host'] because MPD_HOST=pass@host
- mpd_host_env = mpd_host_env.split('@')
- mpd_host_env.reverse()
- if len(mpd_host_env[0]) > 0:
- con_id.update({'host': mpd_host_env[0]})
- if len(mpd_host_env) > 1:
- print 'passwd set in MPD_HOST'
- passwd = mpd_host_env[1]
- con_id.update({'passwd': passwd})
- if mpd_port:
- con_id.update({'port': int(mpd_port)})
- return (con_id, passwd)
-
-
-class StartOpt(object):
- """
- """
-
- def __init__(self, script_info, child_options):
- # Strong assumption?
- self.localencoding = 'utf8'
- self.parser = None
- self.cli_options = dict({})
- # TODO: dict ?!!? isn't it a list instead?
- self.cli_args = dict({})
- self.info = dict(script_info)
- # options allows to add new cli options within child objects calling
- # parent __init__()
- self.options = list(child_options + OPTS)
- self.main()
-
- def _get_encoding(self):
- """Get local encoding"""
- self.localencoding = getpreferredencoding()
-
- def _u8_convert(self, string):
- """Convert CLI input string to UTF8 (mpd standart)"""
- return unicode(string, self.localencoding).encode('UTF-8')
-
- def declare_opts(self):
- """
- Declare options in OptionParser object.
- """
- version = self.info.get('version')
- prog = self.info.get('prog_name')
- des = self.info.get('description')
- if 'usage' in self.info:
- usage = self.info.get('usage')
- else:
- usage = USAGE
- self.parser = OptionParser(version=version,
- usage=usage,
- prog=prog,
- description=des)
- con_id, passwd = get_mpd_environ()
- # Add all options declare in OPTS
- for opt in self.options:
- opt_names = opt.pop('sw')
- self.parser.add_option(*opt_names, **opt)
- #set defaults for host/port according to env var
- dest = opt.get('dest')
- if dest in ['host']:
- self.parser.set_defaults(host=con_id.get('host'))
- if dest in ['port']:
- self.parser.set_defaults(port=con_id.get('port'))
-
- def main(self):
- """declare options, parse command line"""
- self.declare_opts()
- self._get_encoding()
- (self.cli_options, self.cli_args) = self.parser.parse_args()
-
-
-def main():
- pass
-
-# Script starts here
-if __name__ == '__main__':
- main()
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009, 2010, 2012 Kaliko Jack <kaliko.jack@azylum.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-"""
-DOC:
- heavily borrowed from perl script mpdtoys and converted to python.
- mpdtoys © 2007 Joey Hess <joey@kitenet.net>
- http://kitenet.net/~joey/code/mpdtoys
-"""
-
-import sys
-
-from time import sleep
-
-from lib.goodies import Goodie
-
-
-NAME = 'mfade'
-VERSION = '0.1'
-USAGE = 'USAGE: %prog [--help] | [ <time> [<final volume level>] ]'
-DESC = """Fade in/out to <final volume level> over <time>. Defaults are from 0%
-to 50% when paused or stopped and from current volume to 10th of it if playing,
-both over 10 minutes."""
-
-
-class Sleep(Goodie):
- """"""
- script_info = dict({
- 'version': VERSION,
- 'prog_name': NAME,
- 'description': DESC,
- 'usage': USAGE,
- })
-
- def __init__(self):
- """"""
- Goodie.__init__(self, self.__class__.script_info)
- self.tempo = int(10)
- self.volum = None
- self._consume_args()
- self._run()
-
- def _consume_args(self):
- """"""
- if (len(self.cli_args) < 1 or
- len(self.cli_args) > 2):
- self.parser.error('need at least an argument and no more than two!')
- try:
- self.tempo = int(self.cli_args[0])
- self.volum = int(self.cli_args[1])
- except IndexError:
- pass
- except ValueError, err:
- self.parser.error('wrong option passed (%s)' % err)
-
- def _run(self):
- """"""
- self.mpdConnect()
- self.mpd_state = str(self.client.status().get('state'))
- self.mpd_vol = int(self.client.status().get('volume'))
- if self.mpd_state == 'play':
- if not self.volum:
- self.volum = self.mpd_vol / 10
- if self.volum > self.mpd_vol:
- self.parser.error('Error: specified min volume (%d%%) > to current volume (%d%%)' % (self.volum, self.mpd_vol))
- print >> sys.stdout, 'fading down from %d%% to %d%% over %smin' % (self.mpd_vol, self.volum, self.tempo)
- if self.fade():
- self.client.stop()
- if self.mpd_state in ['stop', 'pause']:
- if not self.volum:
- self.volum = int(50)
- print >> sys.stdout, 'fading up from 0%% to %d%% over %smin' % (self.volum, self.tempo)
- self.client.setvol(0)
- self.mpd_vol = 0
- self.client.play()
- self.fade()
- sleep(1)
-
- def fade(self):
- """"""
- # TODO: handle possible lost connections
- span = float(self.volum - self.mpd_vol)
- step = span / float(60 * self.tempo)
- vol = self.mpd_vol
- while 42:
- if int(vol) != int(self.client.status().get('volume')):
- sys.stderr.write('Warning: external volume change, aborting!\n')
- return False
- vol += step
- self.client.setvol(int(vol))
- if abs(vol - self.volum) < 1:
- self.client.setvol(self.volum)
- return True
- sleep(1)
-
-
-# Script starts here
-if __name__ == '__main__':
- try:
- Sleep()
- except KeyboardInterrupt:
- sys.stdout.write('exit')
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009, 2010, 2012 Kaliko Jack <kaliko.jack@azylum.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-
-import sys
-
-from os import(access, W_OK)
-from os.path import (dirname, isfile, basename)
-
-from lib.goodies import Goodie
-
-
-NAME = 'mtopls'
-VERSION = '0.1'
-USAGE = 'USAGE: %prog [--help] | /path/to/the/playlist/file/'
-
-
-class MtoPls(Goodie):
- """
- """
- script_info = dict({
- 'version': VERSION,
- 'prog_name': NAME,
- 'description': 'Save currently played track into your playlists',
- 'usage': USAGE,
- })
-
- def __init__(self):
- """"""
- Goodie.__init__(self, self.__class__.script_info)
- self.playlist = None
- self._run()
-
- def _get_opt(self):
- """"""
- if len(self.cli_args) != 1:
- self.parser.error('need at least a playlist file name!')
- self.playlist = self.cli_args[0]
- if (isfile(self.playlist) and
- access(self.playlist, W_OK)):
- return
- if not access(dirname(self.playlist), W_OK):
- self.parser.error('not writable: %s' % dirname(self.playlist))
-
- def _check_dupes(self):
- """Controls the file is not already in the playlist"""
- fd = open(self.playlist)
- lines = fd.readlines()
- fd.close()
- if self.current_song.get('file') + '\n' in lines:
- print 'File already in the playlist.'
- sys.exit(0)
-
- def _write(self):
- """"""
- if not isfile(self.playlist):
- # TODO: add M3U header
- print >> sys.stdout, ('Create new playlist: %s' % self.playlist)
- open(self.playlist, 'a').close()
- else:
- self._check_dupes()
- fd = open(self.playlist, 'a')
- fd.write(self.current_song.get('file') + '\n')
- fd.close()
-
- def _run(self):
- """"""
- print 'Connecting %s:%i' % (self.cli_options.host,
- self.cli_options.port)
- self.mpdConnect()
- self.current_song = self.client.currentsong()
- self.client.disconnect()
- self._get_opt()
- print 'Will try to add "%s" to "%s"' % (
- basename(self.current_song.get('file')),
- self.playlist)
- self._write()
- print 'Done...'
- sys.exit(0)
-
-
-# Script starts here
-if __name__ == '__main__':
- try:
- MtoPls()
- except KeyboardInterrupt:
- sys.stdout.write('exit')
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009, 2010, 2012 Kaliko Jack <kaliko.jack@azylum.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-
-import sys
-
-from time import sleep
-
-from lib.goodies import Goodie
-
-
-NAME = 'nalbum'
-VERSION = '0.1'
-
-NALBUM_OPTS = list([
- {
- 'sw': ['-c', '--crossfade'],
- 'type': 'int',
- 'dest': 'time',
- 'metavar': 't',
- 'help': 'fade out/fade in over t seconds.'},
- ])
-
-
-class Nalbum(Goodie):
- """
- """
- script_info = dict({
- 'version': VERSION,
- 'prog_name': NAME,
- 'description': 'Jump to next album in playlist.',
- })
-
- def __init__(self):
- """"""
- Goodie.__init__(self, self.__class__.script_info,
- extra_options=NALBUM_OPTS)
- self._run()
-
- def _fade(self, io='out'):
- """
- end_volum => End volume value
- mpd_vol => Start volume value
- """
- mpd_vol = int(self.init_vol)
- if io == 'out':
- end_volum = mpd_vol / 10
- mpd_vol = self.init_vol
- if io == 'in':
- end_volum = int(self.init_vol)
- mpd_vol = int(self.init_vol) / 10
- span = float(end_volum - mpd_vol)
- step = span / float(10*self.cli_options.time)
- while 42:
- mpd_vol += step
- self.client.setvol(int(mpd_vol))
- if abs(mpd_vol - end_volum) < 1:
- self.client.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.client.status():
- print "No current song set in MPD!"
- self.client.disconnect()
- sys.exit(0)
- current_album = str(self.client.currentsong().get('album', 'TAG MISSING'))
- current_song_pos = int(self.client.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.client.status().get('playlistlength')) - 1
- if pl_length < next_album_pos:
- print 'Next album not found in the playlitst!'
- self.client.disconnect()
- sys.exit(0)
- album = self.client.playlistinfo(next_album_pos)[0].get('album', 'TAG MISSING')
- print 'Next album appears to be: "%s"' % album
- return next_album_pos
-
- def _run(self):
- """"""
- print 'Connecting %s:%i' % (self.cli_options.host, self.cli_options.port)
- self.mpdConnect()
- nalbum = self._get_next()
- self.init_vol = int(self.client.status().get('volume'))
- if self.cli_options.time:
- print 'Cross fading next album'
- self._fade()
- self.client.play(nalbum)
- if self.cli_options.time:
- self._fade(io='in')
- self.client.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
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009, 2010, 2012 Kaliko Jack <kaliko.jack@azylum.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-
-import sys
-
-from random import choice
-
-from lib.goodies import Goodie
-
-
-NAME = 'wakeup'
-VERSION = '0.1'
-USAGE = 'USAGE: %prog --help | AlbumA AlbumB "The Album C" | -f file'
-
-WAKEUP_OPTS = list([
- {
- 'sw': ['-f', '--file'],
- 'type': 'str',
- 'dest': 'file',
- 'metavar': 'filename',
- 'help': 'filemame to read album list from. An album name on each line'},
- ])
-
-
-class WakeUp(Goodie):
- """
- """
- script_info = dict({
- 'version': VERSION,
- 'prog_name': NAME,
- 'description': 'Queue and play an album chosen at random from a list. Albums list provided from CLI or text file.',
- 'usage': USAGE,
- })
-
- def __init__(self):
- """"""
- Goodie.__init__(self, self.__class__.script_info,
- extra_options=WAKEUP_OPTS)
- self._get_arg()
- self._run()
-
- def _get_arg(self):
- """"""
- if self.cli_options.file:
- # TODO: handle encoding reading file!
- print 'reading from file, assuming %s encoding' % self.localencoding
- try:
- with open(self.cli_options.file) as f:
- self.albums_list = [line.rstrip('\n') for line in f.readlines()]
- return True
- except IOError, err:
- print 'ERROR: "%s": %s' % (self.cli_options.file, err[1])
- sys.exit(1)
- if self.cli_args:
- print 'WARNING: ignoring "%s"' % self.cli_args
- return True
- if self.cli_args:
- self.albums_list = self.cli_args
- return True
- self.parser.print_usage()
- print "ERROR: Need at least an argument!"
- sys.exit(1)
-
- def _run(self):
- """"""
- print 'Connecting %s:%i' % (self.cli_options.host, self.cli_options.port)
- self.mpdConnect()
- album = choice(self.albums_list)
- print 'Queueing "%s"' % album
- tracks = self.client.find('album', self._u8_convert(album))
- if not tracks:
- print 'No tracks found for "%s"' % album
- self.client.disconnect()
- sys.exit(1)
- for track in tracks:
- self.client.add(track.get('file'))
- self.client.disconnect()
- sys.exit(0)
-
-
-# Script starts here
-if __name__ == '__main__':
- try:
- WakeUp()
- except KeyboardInterrupt:
- sys.stdout.write('exit')
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab