aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/plugins/moc.py305
1 files changed, 305 insertions, 0 deletions
diff --git a/src/plugins/moc.py b/src/plugins/moc.py
new file mode 100644
index 0000000..560370a
--- /dev/null
+++ b/src/plugins/moc.py
@@ -0,0 +1,305 @@
+# -*- python -*-
+'''
+xpybar – xmobar replacement written in python
+Copyright © 2014 Mattias Andrée (maandree@member.fsf.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 subprocess
+
+from util import *
+
+
+class MOC:
+ '''
+ Music On Console interface
+
+ @variable state The state of moc, one of: MOC.NOT_RUNNING,
+ MOC.STOPPED, MOC.PAUSED, MOC.PLAYING
+ '''
+
+
+ NOT_RUNNING = None
+ '''
+ The MOC server is not running
+ '''
+
+ STOPPED = 'STOP'
+ '''
+ No file is played
+ '''
+
+ PAUSED = 'PAUSE'
+ '''
+ The current file is paused
+ '''
+
+ PLAYING = 'PLAY'
+ '''
+ The current file is playing
+ '''
+
+
+ def __init__(self):
+ '''
+ Constructor
+ '''
+ self.__info = {}
+ for line in spawn_read('mocp', '--info').split('\n'):
+ if ': ' in line:
+ line = line.split(': ')
+ self.__info[line[0]] = ': '.join(line[1:])
+ self.state = self['State'] if 'State' in self else None
+
+
+ def __contains__(self, key):
+ '''
+ Get whether or not a key is available
+
+ @param key:str The key
+ @return :bool The availability
+ '''
+ return key in self.__info
+
+
+ def __getitem__(self, key):
+ '''
+ Get a detailing
+
+ @param key:str The key
+ @return :str The value associated with the key
+
+ The following are defined (may be empty) if moc is
+ playing or paused: File, Title, Artist, SongTitle,
+ Album, TotalTime, TimeLet, TotalSec, CurrentTime,
+ CurrentSec, Bitrate.
+ '''
+ return self.__info[key]
+
+
+ @staticmethod
+ def __interact(*args):
+ '''
+ Run mocp
+
+ @param args:*str The command line arguments, except the first
+ @return :Popen The spawned process
+ '''
+ command = ['mocp'] + list(args)
+ return subprocess.Popen(command, stderr = sys.stderr, stdout = subprocess.PIPE)
+
+
+ @staticmethod
+ def enqueue(files):
+ '''
+ Add files to the queue
+
+ @param files:itr<str> The files
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--enqueue', '--', *files)
+
+
+ @staticmethod
+ def append(files):
+ '''
+ Append files, directories (recursively) and playlists to the playlist
+
+ @param files:itr<str> The files
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--append', '--', *files)
+
+
+ @staticmethod
+ def clear():
+ '''
+ Clear the playlist
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--clear')
+
+
+ @staticmethod
+ def play():
+ '''
+ Start playing from the first item on the playlist
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--play')
+
+
+ @staticmethod
+ def next():
+ '''
+ Request playing the next song from the server's playlist
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--next')
+
+
+ @staticmethod
+ def previous():
+ '''
+ Request playing the previous song from the server's playlist
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--previous')
+
+
+ @staticmethod
+ def stop():
+ '''
+ Request the server to stop playing
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--stop')
+
+
+ @staticmethod
+ def exit():
+ '''
+ Bring down the server
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--exit')
+
+
+ @staticmethod
+ def pause():
+ '''
+ Request the server to pause playing
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--pause')
+
+
+ @staticmethod
+ def unpause():
+ '''
+ Request the server to resume playing when paused
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--unpause')
+
+
+ @staticmethod
+ def toggle_pause():
+ '''
+ Toggle between play and pause
+
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--toggle-pause')
+
+
+ @staticmethod
+ def seek(seconds):
+ '''
+ Seek forward (positive) or backward (negative) in the file currently being played
+
+ @param seconds:int The number of seconds to seek forward, negative for backwards
+ @return :Popen? The spawned process, `None` if nothing is spawned
+ '''
+ if not seconds == 0:
+ return MOC.__interact('--seek', ('+%i' if seconds > 0 else '%i') % (seconds))
+ return None
+
+
+ @staticmethod
+ def volume(volume, relative = True):
+ '''
+ Adjust the mixer volume
+
+ @param volume:int The volume or volume increment
+ @param relative:bool Whether to adjust, otherwise set
+ @return :Popen The spawned process
+ '''
+ if relative and (not volume == 0):
+ return MOC.__interact('--volume', ('+%i' if volume > 0 else '%i') % (volume))
+ return MOC.__interact('--volume', '%i' % (max(0, volume)))
+
+
+ @staticmethod
+ def jump(position, precents = False):
+ '''
+ Jump to some position in the current file
+
+ @param position:int The position either in seconds or precents
+ @param precents:bool Whether to use precents, otherwise seconds
+ @return :Popen The spawned process
+ '''
+ return MOC.__interact('--jump', '%i%s' % (position, '%' if precents else 's'))
+
+
+ def toggle(shuffle = False, repeat = False, autonext = False):
+ '''
+ Toggle options
+
+ @param shuffle:bool Whether to toggle shuffle
+ @param repeat:bool Whether to toggle repeat
+ @param autonext:bool Whether to toggle autonext
+ @return :Popen? The spawned process, `None` if nothing is spawned
+ '''
+ if any([shuffle, repeat, autonext]):
+ opts = [('shuffle', shuffle), ('repeat', repeat), ('autonext', autonext)]
+ opts = map(lambda opt_val : opt_val[0] if opt_val[1] else None, opts)
+ opts = filter(lambda opt : opt is not None, opts)
+ return MOC.__interact('--toggle', ','.join(opts))
+ return None
+
+
+ def on(shuffle = False, repeat = False, autonext = False):
+ '''
+ Turn on options
+
+ @param shuffle:bool Whether to turn on shuffle
+ @param repeat:bool Whether to turn on repeat
+ @param autonext:bool Whether to turn on autonext
+ @return :Popen? The spawned process, `None` if nothing is spawned
+ '''
+ if any([shuffle, repeat, autonext]):
+ opts = [('shuffle', shuffle), ('repeat', repeat), ('autonext', autonext)]
+ opts = map(lambda opt_val : opt_val[0] if opt_val[1] else None, opts)
+ opts = filter(lambda opt : opt is not None, opts)
+ return MOC.__interact('--on', ','.join(opts))
+ return None
+
+
+ def off(shuffle = False, repeat = False, autonext = False):
+ '''
+ Turn off options
+
+ @param shuffle:bool Whether to turn off shuffle
+ @param repeat:bool Whether to turn off repeat
+ @param autonext:bool Whether to turn off autonext
+ @return :Popen? The spawned process, `None` if nothing is spawned
+ '''
+ if any([shuffle, repeat, autonext]):
+ opts = [('shuffle', shuffle), ('repeat', repeat), ('autonext', autonext)]
+ opts = map(lambda opt_val : opt_val[0] if opt_val[1] else None, opts)
+ opts = filter(lambda opt : opt is not None, opts)
+ return MOC.__interact('--off', ','.join(opts))
+ return None
+