]> kaliko git repositories - mpd-goodies.git/blob - bin/mfade
Fixed protocol version check for mlast
[mpd-goodies.git] / bin / mfade
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 # SPDX-FileCopyrightText: 2009,2010,2012,2019 kaliko <kaliko@azylum.org>
4 # SPDX-FileCopyrightText: 2007 Joey Hess <joey@kitenet.net>
5 # SPDX-License-Identifier: GPL-3.0-or-later
6 """
7 DOC:
8     heavily borrowed from perl script mpdtoys and converted to python.
9     mpdtoys © 2007 Joey Hess <joey@kitenet.net>
10     http://kitenet.net/~joey/code/mpdtoys
11 """
12
13 import argparse
14 import sys
15
16 from time import sleep
17 from os.path import basename
18
19 import musicpd
20
21
22 VERSION = '0.2'
23 DESC = """Fade in/out to <final volume level> over <time>.
24 Defaults are from 0% to 50% when paused or stopped
25 and from current volume to 10th of it if playing,
26 both over 10 minutes."""
27 DESC = """Fade in/out to <final volume level> over <time>.
28 Defaults are from 0% to 50% when paused or stopped and from current volume to 10th of it if playing, both over 10 minutes."""
29 EPILOG = """You might need to set your audio_output with "always_on yes" for
30 this command to work properly.
31
32 Set MPD host/port in env. var"""
33
34
35 class Sleep(musicpd.MPDClient):
36     """"""
37     script_info = dict({
38         'prog': basename(__file__),
39         'description': DESC,
40         'epilog': EPILOG,
41         'formatter_class': argparse.RawDescriptionHelpFormatter,
42     })
43
44     def __init__(self):
45         """"""
46         musicpd.MPDClient.__init__(self)
47         self.tempo = 600
48         self.volum = None
49         self._get_args()
50         self._run()
51
52     def _test_volume_access(self):
53         status = self.status()
54         if 'volume' not in status:
55             print('Mixer not available!')
56             print('Try to set the always_on audio_output option on.')
57             sys.exit(1)
58
59     def _get_args(self):
60         """"""
61         parser = argparse.ArgumentParser(**self.__class__.script_info)
62         parser.add_argument('--version', action='version',
63                             version='v%s' % VERSION)
64         group = parser.add_mutually_exclusive_group()
65         group.add_argument('-m', '--minutes', type=int,
66                            help='duration to fade in/out over')
67         group.add_argument('-s', '--seconds', type=int,
68                            help='duration to fade in/out over')
69         parser.add_argument('volume', type=int, nargs='?',
70                             help='final volume level')
71         args = parser.parse_args()
72         if args.minutes:
73             self.tempo = args.minutes*60
74         if args.seconds:
75             self.tempo = args.seconds
76         if args.volume:
77             self.volum = args.volume
78
79     def _run(self):
80         """"""
81         self.connect()
82         self.mpd_state = str(self.status().get('state'))
83         if self.mpd_state == 'play':
84             self.mpd_vol = int(self.status().get('volume'))
85             if not self.volum:
86                 self.volum = self.mpd_vol // 10
87             if self.volum >= self.mpd_vol:
88                 print('Error: specified min volume (%d%%) >= to current volume (%d%%)' % (
89                     self.volum, self.mpd_vol))
90                 sys.exit(1)
91             print('fading down from %d%% to %d%% over %ss' % (self.mpd_vol, self.volum, self.tempo), file=sys.stdout)
92             if self.fade(self.mpd_vol, self.volum):
93                 self.stop()
94         elif self.mpd_state in ['stop', 'pause']:
95             self._test_volume_access()
96             if not self.volum:
97                 self.volum = int(50)
98             print('fading up from 0%% to %d%% over %ss' % (self.volum, self.tempo), file=sys.stdout)
99             self.mpd_vol = 0
100             self.setvol(0)
101             self.play()
102             self.fade(self.mpd_vol, self.volum)
103
104     def fade(self, mpd_vol, target):
105         """"""
106         # TODO: handle possible lost connections
107         resolution = 5
108         span = target - mpd_vol
109         step = span / (resolution*self.tempo)
110         vol = mpd_vol
111         if step == 0:
112             return True
113         while True:
114             vol += step
115             self.setvol(round(vol))
116             # monitor external volume change
117             # print(vol, round(vol), self.status().get('volume'))
118             if abs(vol - target) < 1.1*abs(step):
119                 self.setvol(target)
120                 return True
121             sleep(1/resolution)
122
123
124 # Script starts here
125 if __name__ == '__main__':
126     try:
127         Sleep()
128     except KeyboardInterrupt:
129         sys.stdout.write('exit')
130
131 # VIM MODLINE
132 # vim: ai ts=4 sw=4 sts=4 expandtab