Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/moc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Controlling the playback

.. autofunction:: increase_volume
.. autofunction:: decrease_volume
.. autofunction:: get_volume
.. autofunction:: set_volume

.. autofunction:: moc.next
.. autofunction:: moc.previous
Expand Down
83 changes: 67 additions & 16 deletions moc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
#!/usr/bin/env python
from __future__ import with_statement
import os
import os, os.path
import subprocess
import socket
import struct
import ConfigParser
import StringIO

class Cli:
extra_arguments = []
configfile = "~/.moc/config"
socketfile = "~/.moc/socket2"

STATE_NOT_RUNNING = -1
STATE_STOPPED = 0
Expand All @@ -21,24 +30,27 @@ class MocNotRunning(MocError):
""" Raised if a command failed because the moc server does not run """

# Helper functions
def _quote_file_args(files):
def _check_file_args(files):
"""
Checks if every element from dictonary passed in parameter is a valid
filepath, is a http or ftp url.

Raises TypeError if parameter is a string or OSError if any of files
in dictonary does not exist.
"""
if isinstance(files, str):
raise TypeError("Argument must be a list/iterable, not str")
quoted = []
for file in files:
if os.path.exists(file) or file.startswith(('http://', 'ftp://')):
if not os.path.exists(file) and not file.startswith(('http://', 'ftp://')):
# MOC only supports HTTP and FTP, not even HTTPS.
# (See `is_url` in `files.c`.)
quoted.append('"%s"' % file)
else:
raise OSError("File %r does not exist" % file)
return ' '.join(quoted)

def _exec_command(command, parameters=''):
def _exec_command(command, parameters=[]):
cmd = subprocess.Popen(
['mocp --%s %s' %(command, parameters)],
["mocp", "--%s" % command] + parameters + Cli.extra_arguments,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
shell=True, close_fds=True
close_fds=True
)
stdout, stderr = cmd.communicate()
if cmd.returncode:
Expand All @@ -49,9 +61,33 @@ def _exec_command(command, parameters=''):
raise MocError(errmsg)
return stdout

def set_config_file(config_file_path):
if not os.path.exists(config_file_path):
raise OSError("Configuration file '%r' does not exists" % config_file_path)

Cli.configfile = config_file_path
Cli.extra_arguments = Cli.extra_arguments + ["--config", config_file_path]
update_moc_dir()

def update_moc_dir():
"""
Reads configuration file and searches for mocdir
"""

configF = StringIO.StringIO()
configF.write('[dummysection]')
configF.write(open(os.path.expanduser(Cli.configfile), 'r').read())
configF.seek(0, os.SEEK_SET)

config = ConfigParser.RawConfigParser()
config.readfp(configF)
if config.get('dummysection', 'MOCDir'):
Cli.socketfile = config.get('dummysection','MOCDir') + '/socket2'

def start_server():
""" Starts the moc server. """
_exec_command('server')
update_moc_dir()

def stop_server():
""" Shuts down the moc server. """
Expand Down Expand Up @@ -124,7 +160,8 @@ def quickplay(files):

Raises an :exc:`OSError` if any of the `files` can not be found.
"""
_exec_command('playit', _quote_file_args(files))
_check_file_args(files)
_exec_command('playit', files)


def _moc_output_to_dict(output):
Expand Down Expand Up @@ -183,25 +220,38 @@ def increase_volume(level=5):
"""
Aliases: ``increase_volume()``, ``volume_up()``, ``louder()``, ``upper_volume()``
"""
_exec_command('volume', '+%d' % level)
_exec_command('volume', ['+%d' % level])
louder = upper_volume = volume_up = increase_volume

def decrease_volume(level=5):
"""
Aliases: ``decrease_volume()``, ``volume_down()``, ``lower()``, ``lower_volume()``
"""
_exec_command('volume', '-%d' % level)
_exec_command('volume', ['-%d' % level])
lower = lower_volume = volume_down = decrease_volume

def get_volume():
s = socket.socket( socket.AF_UNIX, socket.SOCK_STREAM )
s.connect(os.path.expanduser(Cli.socketfile))
s.send(struct.pack('i', 0x1a))
unpacker = struct.Struct('i i')
data = s.recv(unpacker.size)
s.close()

return unpacker.unpack(data)[1]

def set_volume(level):
_exec_command('volume', ['%d' % level])

def seek(n):
"""
Moves the current playback seed forward by `n` seconds
(or backward if `n` is negative).
"""
_exec_command('seek', n)
_exec_command('seek', [n])

def _controls(what):
makefunc = lambda action: lambda: _exec_command(action, what) and None or None
makefunc = lambda action: lambda: _exec_command(action, [what]) and None or None
return (makefunc(action) for action in ('on', 'off', 'toggle'))

enable_repeat, disable_repeat, toggle_repeat = _controls('repeat')
Expand Down Expand Up @@ -260,7 +310,8 @@ def playlist_append(files_directories_playlists):
Appends the files, directories and/or in `files_directories_playlists` to
moc's playlist.
"""
_exec_command('append', _quote_file_args(files_directories_playlists))
_check_file_args(files_directories_playlists)
_exec_command('append', files_directories_playlists)
append_to_playlist = playlist_append

def playlist_clear():
Expand Down