-
-
Save GudarJs/91d7c30c0fd4098322694e052318493f to your computer and use it in GitHub Desktop.
Remove Ads from Spotify Linux client by mutting the audio system
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
# -*- coding: utf-8 -*- | |
# 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/>. | |
# Author: Manuel Kaufmann <[email protected]> | |
# Date: 29 October 2016 | |
# Release: 0.5 | |
# DESCRIPTION: | |
# | |
# This program allows you to do not listen to Spotify Ads withuot having a paid | |
# account. It's not too much intelligent right now, so you have to add the | |
# Artists you usually listen to or the name of the Spotify Ads you want to mute. | |
# | |
# How it works? It just mute the sound system when it detects an Ads is being | |
# played. How? By reading the window's title and check against all the known | |
# names and Ads you have defined and using some dumb pre-defined rules that fail | |
# in some cases. | |
from __future__ import division, print_function, unicode_literals | |
import commands | |
import os | |
import sys | |
import time | |
HOSTNAME = commands.getoutput('hostname') | |
TERMINAL_ENCODING = commands.getoutput('locale charmap') | |
WMCTRL_WINDOW_LIST = "wmctrl -l -x | grep 'spotify.Spotify' | grep -v 'grep'" | |
MUTE_COMMAND = "amixer -q -D pulse sset Master mute" | |
UNMUTE_COMMAND = "amixer -q -D pulse sset Master unmute" | |
SPOTIFY_OPEN_COMMAND = "ps -ef | grep Spotify | grep -v grep | wc -l" | |
MUTED = False | |
SPOTIFY_OPENED = False | |
SONGS_PLAYED = [] | |
# Time in seconds | |
SLEEP_BEFORE_UNMUTE = 1.5 | |
SLEEP_BETWEEN_EACH_CHECK = 0.1 | |
SLEEP_WHEN_SPOTIFY_CLOSED = 5 | |
# Define the names of the Artists, Songs, etc you usually listen to here | |
KNOWN_TITLES = ( | |
# Titles that I found with problems matching dumb rules | |
['Emir Kusturica'], | |
['Jarabe De Palo'], | |
['Bob Marley'], | |
['Queen'], | |
['Soda Stereo'], | |
# Titles I want to be sure that are valid | |
map( | |
lambda x: '- {}'.format(x), | |
['Remastered', 'Extended Version', 'En Vivo', 'MTV Unplugged', 'Acoustic', 'Versión Acústica', 'Live', | |
'Directo', 'directo', 'unplugged', 'en directo', 'Unplugged Version', 'Live/Unplugged', 'Instrumental', | |
'Remasterizado', 'BBC'], | |
), | |
# ... | |
) | |
# Define the names of the Ads you usually listen to and want to avoid here | |
ADS_TITLES = ( | |
# ... | |
['REYKON'], | |
) | |
def mute(): | |
global MUTED | |
MUTED = True | |
os.system(MUTE_COMMAND) | |
def unmute(): | |
global MUTED | |
MUTED = False | |
os.system(UNMUTE_COMMAND) | |
def is_spotify_opened(): | |
global SPOTIFY_OPENED | |
output = commands.getoutput(SPOTIFY_OPEN_COMMAND) | |
SPOTIFY_OPENED = bool(int(output)) # 0 is closed | |
return SPOTIFY_OPENED | |
def is_known_title(spotify_title): | |
if spotify_title.isupper(): | |
# most of the ads are upper case | |
return False | |
if len(spotify_title.split()) == 1: | |
# some of the ads are just one word | |
return False | |
# check for known Ads | |
for title in ADS_TITLES: | |
for t in title: | |
if t in spotify_title: | |
return False | |
if len(spotify_title.split(' - ')) == 2: | |
# most of the songs are in the form "Artist - Title" | |
return True | |
# check for known Artists or Songs | |
for title in KNOWN_TITLES: | |
for t in title: | |
if t in spotify_title: | |
return True | |
return False | |
def check_spotify_ads(): | |
output = commands.getoutput(WMCTRL_WINDOW_LIST) | |
try: | |
output = output.decode(TERMINAL_ENCODING) | |
_, spotify_title = output.split(HOSTNAME) | |
except (ValueError, UnicodeDecodeError) as e: | |
print('*** ERROR: {} ***'.format(e)) | |
print('*** Command Output: {} ***'.format(output)) | |
return | |
spotify_title = spotify_title.strip() | |
known_title = is_known_title(spotify_title) | |
if (spotify_title not in SONGS_PLAYED and known_title) or (not MUTED and not known_title): | |
print('Playing:', spotify_title) | |
if spotify_title not in SONGS_PLAYED and known_title: | |
SONGS_PLAYED.append(spotify_title) | |
if known_title: | |
if MUTED: | |
time.sleep(SLEEP_BEFORE_UNMUTE) # the window title changes before the song starts | |
unmute() | |
else: | |
if not MUTED: | |
print('Sound MUTED.') | |
mute() | |
if __name__ == '__main__': | |
try: | |
while True: | |
if not is_spotify_opened(): | |
print('Spotify not running. Sleeping...') | |
time.sleep(SLEEP_WHEN_SPOTIFY_CLOSED) | |
continue | |
check_spotify_ads() | |
time.sleep(SLEEP_BETWEEN_EACH_CHECK) | |
except KeyboardInterrupt: | |
if MUTED: | |
print('\nUnmuting...', end=' ') | |
unmute() | |
print('\nBye.') | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment