Skip to content

Commit

Permalink
version bump, fixing issues #46 and #47
Browse files Browse the repository at this point in the history
  • Loading branch information
Max Demian committed Jul 11, 2015
1 parent 31b2c50 commit 9d271b4
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 78 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ http://skyserver5.skydisc.net:8000
You can use relative and absolute paths as well as basically any audio source/format, as long as you have the respective gstreamer codec installed.

## Changelog
- v1.8.8 (2015-07-11): Fix [issue #46](https://github.com/mikar/blockify/issues/46) and [issue #47](https://github.com/mikar/blockify/issues/47)
- v1.8.7 (2015-06-11): Pressing play will now properly pause interlude music before resuming spotify playback.
- v1.8.6 (2015-05-10): Minor refactoring and removed incomplete "fix" for [issue #44](https://github.com/mikar/blockify/issues/44).
- v1.8.5 (2015-05-09): Signal cleanups and [issue #44](https://github.com/mikar/blockify/issues/44) again.
Expand Down
75 changes: 43 additions & 32 deletions blockify/blockify.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

class Blockify(object):


def __init__(self, blocklist):
self.blocklist = blocklist
self.orglist = blocklist[:]
Expand All @@ -43,7 +44,7 @@ def __init__(self, blocklist):
self._automute = util.CONFIG["general"]["automute"]
self.update_interval = util.CONFIG["cli"]["update_interval"]
self.unmute_delay = util.CONFIG["cli"]["unmute_delay"]
self.pacmd_muted_value = util.CONFIG["general"]["pacmd_muted_value"]
self.pulse_unmuted_value = ""
self.env = os.environ.copy()
self.env["LC_ALL"] = "en_US"
self.found = False
Expand All @@ -63,8 +64,12 @@ def __init__(self, blocklist):
# Determine if we can use sinks or have to use alsa.
try:
devnull = open(os.devnull)
subprocess.check_output(["pacmd", "list-sink-inputs"], stderr=devnull)
pacmd_out = subprocess.check_output(["pacmd", "list-sink-inputs"], stderr=devnull)
self.mutemethod = self.pulsesink_mute
# Properly initialize unmuted state, i.e. self.pulse_unmuted_value
self.toggle_mute(2)
sink_status = self.extract_pulse_sink_status(pacmd_out)
self.pulse_unmuted_value = sink_status[1]
log.debug("Mute method is pulse sink.")
except (OSError, subprocess.CalledProcessError):
log.info("No pulse sinks found, falling back to system mute via alsa.")
Expand All @@ -77,6 +82,7 @@ def __init__(self, blocklist):

log.info("Blockify initialized.")


def check_for_blockify_process(self):
try:
pid = subprocess.check_output(["pgrep", "-f", "python.*blockify"])
Expand Down Expand Up @@ -115,6 +121,7 @@ def init_dbus(self):

def start(self):
self.bind_signals()
# Force unmute to properly initialize unmuted state
self.toggle_mute()

gtk.timeout_add(self.update_interval, self.update)
Expand Down Expand Up @@ -285,48 +292,52 @@ def pulse_mute(self, mode):
for channel in self.channels:
subprocess.Popen(["amixer", "-qD", "pulse", "set", channel, state])

def pulsesink_mute(self, mode):
"Finds spotify's audio sink and toggles its mute state."
try:
pacmd_out = subprocess.check_output(["pacmd", "list-sink-inputs"], env=self.env)
except subprocess.CalledProcessError:
log.error("Spotify sink not found. Is Pulse running? Resorting to pulse amixer as mute method.")
self.mutemethod = self.pulse_mute # Fall back to amixer mute.
self.use_interlude_music = False
return

# Match muted and application.process.id values.
def extract_pulse_sink_status(self, pacmd_out):
sink_status = ("", "")
# Match muted_value and application.process.id values.
pattern = re.compile(r"(?: index|muted|application\.process\.id).*?(\w+)")
# Put valid spotify PIDs in a list
output = pacmd_out.decode("utf-8")

spotify_sink_list = [" index: " + i for i in output.split("index: ") if "spotify" in i]

if not len(spotify_sink_list):
return
if len(spotify_sink_list) and self.spotify_pids:
sink_infos = [pattern.findall(sink) for sink in spotify_sink_list]
# Every third element per sublist is a key, the value is the preceding
# two elements in the form of a tuple - {pid : (index, muted_value)}
idxd = {sink_status[2]: (sink_status[0], sink_status[1]) for sink_status in sink_infos if len(sink_status) == 3}

pid = [k for k in idxd.keys() if k in self.spotify_pids][0]
sink_status = idxd[pid] # tuple of 2 elements: (index, muted_value)

sink_infos = [pattern.findall(sink) for sink in spotify_sink_list]
# Every third element per sublist is a key, the value is the preceding
# two elements in the form of a tuple - {pid : (index, muted)}
idxd = {info[2]: (info[0], info[1]) for info in sink_infos if len(info) == 3}
return sink_status


def pulsesink_mute(self, mode):
"Finds spotify's audio sink and toggles its mute state."
try:
pid = [k for k in idxd.keys() if k in self.spotify_pids][0]
index, muted = idxd[pid]
self.is_sink_muted = True if muted == self.pacmd_muted_value else False
except IndexError as e:
log.debug("Could not match spotify pid to sink pid: {}".format(e))
pacmd_out = subprocess.check_output(["pacmd", "list-sink-inputs"], env=self.env)
except subprocess.CalledProcessError:
log.error("Spotify sink not found. Is Pulse running? Resorting to pulse amixer as mute method.")
self.mutemethod = self.pulse_mute # Fall back to amixer mute.
self.use_interlude_music = False
return

if self.is_sink_muted and (mode == 2 or not self.current_song):
log.info("Forcing unmute.")
subprocess.call(["pacmd", "set-sink-input-mute", index, "0"])
elif not self.is_sink_muted and mode == 1:
log.info("Muting {}.".format(self.current_song))
subprocess.call(["pacmd", "set-sink-input-mute", index, "1"])
elif self.is_sink_muted and not mode:
log.info("Unmuting.")
subprocess.call(["pacmd", "set-sink-input-mute", index, "0"])
index, muted_value = self.extract_pulse_sink_status(pacmd_out)

self.is_sink_muted = False if muted_value == self.pulse_unmuted_value else True

if index:
if self.is_sink_muted and (mode == 2 or not self.current_song):
log.info("Forcing unmute.")
subprocess.call(["pacmd", "set-sink-input-mute", index, "0"])
elif not self.is_sink_muted and mode == 1:
log.info("Muting {}.".format(self.current_song))
subprocess.call(["pacmd", "set-sink-input-mute", index, "1"])
elif self.is_sink_muted and not mode:
log.info("Unmuting.")
subprocess.call(["pacmd", "set-sink-input-mute", index, "0"])

def prev(self):
self.dbus.prev()
Expand Down
65 changes: 32 additions & 33 deletions blockify/blockifyui.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,35 +236,35 @@ def create_tray(self):
def create_traymenu(self, event_button, event_time):
menu = gtk.Menu()

toggleblock = gtk.MenuItem("Toggle Block")
toggleblock.show()
menu.append(toggleblock)
toggleblock.connect("activate", self.on_toggle_block_btn)

toggleplay = gtk.MenuItem("Toggle Play")
toggleplay.show()
toggleplay.connect("activate", self.on_toggleplay_btn)
menu.append(toggleplay)

prevsong = gtk.MenuItem("Previous Song")
prevsong.show()
prevsong.connect("activate", self.on_prev_btn)
menu.append(prevsong)

nextsong = gtk.MenuItem("Next Song")
nextsong.show()
nextsong.connect("activate", self.on_next_btn)
menu.append(nextsong)

about = gtk.MenuItem("About")
about.show()
menu.append(about)
about.connect("activate", self.show_about_dialogue)

exit = gtk.MenuItem("Exit")
exit.show()
menu.append(exit)
exit.connect("activate", self.on_exit_btn)
toggleblock_menuitem = gtk.MenuItem("Toggle Block")
toggleblock_menuitem.show()
menu.append(toggleblock_menuitem)
toggleblock_menuitem.connect("activate", self.on_toggle_block_btn)

toggleplay_menuitem = gtk.MenuItem("Toggle Play")
toggleplay_menuitem.show()
toggleplay_menuitem.connect("activate", self.on_toggleplay_btn)
menu.append(toggleplay_menuitem)

prevsong_menuitem = gtk.MenuItem("Previous Song")
prevsong_menuitem.show()
prevsong_menuitem.connect("activate", self.on_prev_btn)
menu.append(prevsong_menuitem)

nextsong_menuitem = gtk.MenuItem("Next Song")
nextsong_menuitem.show()
nextsong_menuitem.connect("activate", self.on_next_btn)
menu.append(nextsong_menuitem)

about_menuitem = gtk.MenuItem("About")
about_menuitem.show()
menu.append(about_menuitem)
about_menuitem.connect("activate", self.show_about_dialogue)

exit_menuitem = gtk.MenuItem("Exit")
exit_menuitem.show()
menu.append(exit_menuitem)
exit_menuitem.connect("activate", self.on_exit_btn)

menu.popup(None, None, gtk.status_icon_position_menu,
event_button, event_time, self.status_icon)
Expand Down Expand Up @@ -397,12 +397,11 @@ def create_layout(self):
self.add(main)

def set_states(self):

checkboxes = [self.autodetect_chk, self.automute_chk, self.autoresume_chk, self.autohide_cover_chk]
checkboxes = [self.autodetect_chk, self.automute_chk, self.autohide_cover_chk, self.autoresume_chk]
values = [util.CONFIG["general"]["autodetect"], util.CONFIG["general"]["automute"],
util.CONFIG["interlude"]["autoresume"], util.CONFIG["gui"]["autohide_cover"]]
util.CONFIG["gui"]["autohide_cover"], util.CONFIG["interlude"]["autoresume"]]

for i in range(len(checkboxes)):
for i in range(len(checkboxes) - 1):
checkboxes[i].set_active(values[i])

# Pretend that a song is playing to keep disable_interlude_box() from pausing playback.
Expand Down
9 changes: 3 additions & 6 deletions blockify/data/example_blockify.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ automute = True
# By default blockify matches blocklist entries by reading the current song from
# left to right, meaning to block "Bloodhound Gang - Yvan Eht Nioj", the blocklist
# entry needs to (at least) start with B.
# If you want to be able to block that song by adding "Eht" or any other substring
# If you want to be able to block that song by adding "Gang" or any other substring
# within that song, set this option to True. Beware of false positives though as
# the string "Eth" could appear in a number of other songs.
# the string "Gang" could appear in a number of other songs, e.g. the track
# "Gangnam Style" would be blocked, too. Which might not be that bad, actually.
substring_search = False
# Blockify parses the output of pacmd list-sink-inputs. That output CAN be
# localized in which case you'd need to put your translation of "yes" here.
# For polish it'd be "tak" instead of "yes".
pacmd_muted_value = yes

[cli]
# Update frequency for the CLI in seconds. Lower means quicker detection
Expand Down
14 changes: 12 additions & 2 deletions blockify/interludeplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ class InterludePlayer(object):
def __init__(self, blockify):
self.gst = gst
self.b = blockify
self._index = 0
self.manual_control = False
self.temp_autoresume = False
self.temp_disable = False
self._index = 0
self._autoresume = util.CONFIG["interlude"]["autoresume"]
self.playback_delay = util.CONFIG["interlude"]["playback_delay"]
# Automatically resume spotify playback after n seconds.
self.radio_timeout = util.CONFIG["interlude"]["radio_timeout"]
self.autoresume = util.CONFIG["interlude"]["autoresume"]
self.uri_rx = re.compile("[A-Za-z]+:\/\/")
self.formats = ["mp3", "mp4", "flac", "wav", "wma", "ogg", "avi", "mov", "mpg", "flv", "wmv", \
"spx", "3gp", "b-mtp", "aac", "aiff", "raw", "midi", "ulaw", "alaw", "gsm" ]
Expand Down Expand Up @@ -260,6 +260,16 @@ def set_uri(self):
log.debug("Setting interlude to: {0}".format(uri))
self.player.set_property("uri", uri)


@property
def autoresume(self):
return self._autoresume

@autoresume.setter
def autoresume(self, autoresume):
log.debug("Setting autoresume to: {0}".format(autoresume))
self._autoresume = autoresume

@property
def index(self):
return self._index
Expand Down
9 changes: 4 additions & 5 deletions blockify/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
except ImportError:
log.error("ImportError: Please install docopt to use the CLI.")

VERSION = "1.8.7"
VERSION = "1.8.8"
CONFIG = None
CONFIG_DIR = os.path.join(os.path.expanduser("~"), ".config/blockify")
CONFIG_FILE = os.path.join(CONFIG_DIR, "blockify.ini")
Expand Down Expand Up @@ -83,9 +83,8 @@ def get_default_options():
"general": {
"autodetect": True,
"automute": True,
"substring_search": False,
"pacmd_muted_value":"yes"
},
"substring_search": False
},
"cli": {
"update_interval": 200,
"unmute_delay": 700
Expand Down Expand Up @@ -118,7 +117,7 @@ def load_options():
except Exception as e:
log.error("Could not read config file: {}. Using default options.".format(e))
else:
option_tuples = [("general", "autodetect", "bool"), ("general", "automute", "bool"), ("general", "substring_search", "bool"), ("general", "pacmd_muted_value", "str"),
option_tuples = [("general", "autodetect", "bool"), ("general", "automute", "bool"), ("general", "substring_search", "bool"),
("cli", "update_interval", "int"), ("cli", "unmute_delay", "int"),
("gui", "use_cover_art", "bool"), ("gui", "autohide_cover", "bool"), ("gui", "update_interval", "int"), ("gui", "unmute_delay", "int"),
("interlude", "use_interlude_music", "bool"), ("interlude", "start_shuffled", "bool"), ("interlude", "autoresume", "bool"),
Expand Down

0 comments on commit 9d271b4

Please sign in to comment.