Last active
August 29, 2015 14:03
-
-
Save ztmr/7ee289a9d0957714996e to your computer and use it in GitHub Desktop.
Spotify AdKiller written in Perl. It will simply mute Spotify's PulseAudio sink once the current track is about to end (= running over its official length) and unmute once a new track has started playing. What a naive solution to cut the advertisement injected at the end of the track!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# | |
# $Id: $ | |
# | |
# Module: spotify-adkiller -- Naive Spotify AdKiller | |
# Created: 03-JUL-2014 19:54 | |
# Author: tmr | |
# | |
# TODO: | |
# - listen for Seeked and PlayPause signals to freeze/boost countdown | |
# (not easy in Perl since it is no multithreaded by default) | |
# - since the Spotify app does not seem to implement Position | |
# method (it is always zero), we should Seek(0) right after | |
# we start to ensure that we have started countdown from the beginning | |
# of the track | |
use strict; | |
use warnings; | |
use Net::DBus; | |
use IO::Handle; | |
my $bus = Net::DBus->session (); | |
my $service = $bus->get_service ("org.mpris.MediaPlayer2.spotify"); | |
my $object = $service->get_object ("/"); | |
my $spotifySinkCmd = <<EOF; | |
pactl list \\ | |
| grep -E '(^Sink Input)|(media.name = \\"Spotify\\"\$)' \\ | |
| awk '/Spotify/ {print a} {a = \$0}' \\ | |
| cut -c 13- | tr -d '\\n' | |
EOF | |
my $spotifySinkId = `$spotifySinkCmd`; | |
my $muteCmd = "pactl set-sink-input-mute $spotifySinkId yes"; | |
my $unMuteCmd = "pactl set-sink-input-mute $spotifySinkId no"; | |
my $position = 0; | |
my $prevTrack = undef; | |
my %COLOR = (); | |
$COLOR{'OK'} = "\033[1;49;34m"; | |
$COLOR{'WARN'} = "\033[33;01m"; | |
$COLOR{'NO'} = "\033[0m"; | |
$COLOR{'STD'} = $COLOR{'NO'}."\033[38;5;242m"; | |
autoflush STDOUT 1; | |
while (1) { | |
my $metadata = $object->GetMetadata (); | |
# xesam:title | |
# String: The track title. | |
# http://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata/#index18h4 | |
my $title = $metadata->{'xesam:title'} || ''; | |
# mpris:length | |
# 64-bit integer: The duration of the track in microseconds. | |
# http://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata/#index2h4 | |
my $length = ($metadata->{'mpris:length'} || 0) / (1000 * 1000); | |
# The track has just changed -- the original track with | |
# possibly injected advertisement has ended, so we can unmute | |
# and continue playing the new track. | |
if (defined ($prevTrack) and ($title ne $prevTrack)) { | |
printf $COLOR{'STD'}."INFO: The track has changed: [%s] -> [%s]...\n", | |
$prevTrack, $title; | |
$position = -1; | |
`$unMuteCmd`; | |
} | |
# If the original track is over it's time, we expect there is | |
# an advertisement injected -- no matter if it really is, | |
# we mute the channel preventively | |
# Otherwise, we just pass the track counting down its end. | |
if (++$position >= $length) { | |
printf $COLOR{'WARN'}."DROP: '%s' %d/%d\r", | |
$title, $position, $length; | |
`$muteCmd`; | |
} | |
else { | |
printf $COLOR{'OK'}."PASS: '%s' for %d/%d\r", | |
$title, $position, $length; | |
#`$unMuteCmd`; | |
} | |
sleep (1); | |
$prevTrack = $title; | |
} | |
# vim: fdm=syntax:fdn=3:tw=74:ts=2:syn=perl |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment