Skip to content
This repository has been archived by the owner on Dec 26, 2019. It is now read-only.

Commit

Permalink
Here it is
Browse files Browse the repository at this point in the history
  • Loading branch information
azlux committed Jun 22, 2016
1 parent 371138f commit 56ca276
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 6 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
# MumbleRadioPlayer
A Mumble bot that plays radio stream by URL

Time before commit : not long :) (2 days I think)

![Alt progression] (http://progressed.io/bar/70)
![Alt progression] (http://progressed.io/bar/90)

####What the bot can do
commands :
- [x] !play
- [x] from a list of url
- [ ] from a url
- [x] from a url
- [x] !stop
- [x] !joinme (join the user who speak to me)
- [ ] !kill
- [ ] !oust (stop + go into the default channel)
- [x] !kill
- [x] !oust (stop + go into the default channel)
- [x] !v <number> (change volume with a float number between 0 and 1)

#### info
The bot don't speak, it's not implemented into pymumble yet.

#### TODO
- [ ] Make the bot speak into the channel
16 changes: 16 additions & 0 deletions configuration.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[server]
host = mumble.crystalyx.net
user = StreamPlayer
channel = Bots
port = 64738
# password = "password_here"
comment = coucou je suis la pour les stream : <br/>!play <stream> avec au choix : luna, radiobrony ou ponyville ou avec une url valide<br/>!joinme - je te rejoins<br/>!stop - j'arrete de chanter
[stream]
ponyville = http://192.99.131.205:8000/stream.mp3
luna = http://radio.ponyvillelive.com:8002/stream
radiobrony = http://62.210.138.34:8000/live
[bot]
allow_new_url = True
volume = 0.1
189 changes: 189 additions & 0 deletions mumble_stream.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/python
import time
import sys
import signal
import ConfigParser
import urllib2
import json
import re
import audioop

import pymumble
import subprocess as sp


class MumblePlayUrlBot:
def __init__(self):
signal.signal(signal.SIGINT, self.ctrl_caught)

self.config = ConfigParser.SafeConfigParser({'password': ''}, allow_no_value=True)
self.config.read("configuration.ini")

host = self.config.get('server', 'host')
user = self.config.get('server', 'user')
user = " StreamPlayer"
port = self.config.getint('server', 'port')
password = self.config.get('server', 'password')
debug = False

self.channel = self.config.get('server', 'channel')
self.volume = self.config.getfloat('bot', 'volume')

self.playing = False
self.exit = False
self.nbexit = 0
self.mumble = pymumble.Mumble(host, user=user, port=port, password=password, debug=debug)
self.mumble.callbacks.set_callback("text_received", self.message_received)

self.mumble.start() # start the mumble thread
self.mumble.is_ready() # wait for the connection
self.set_comment()
self.mumble.users.myself.unmute() # by sure the user is not muted
self.mumble.channels.find_by_name(self.channel).move_in()
self.mumble.set_bandwidth(200000)
self.thread = None
self.loop()

def ctrl_caught(self, signal, frame):
print("\ndeconnection asked")
self.exit = True
if self.nbexit > 2:
print("Forced Quit")
sys.exit(0)
self.nbexit += 1

def message_received(self, texte):
message = texte.message
if message[0] == '!':
message = message[1:].split(' ', 1)

if len(message) > 0:
command = message[0]
parameter = ''
if len(message) > 1:
parameter = message[1]
else:
return

print(command + ' - ' + parameter)
if command == 'play' and parameter:
self.play(parameter)

elif command == 'stop':
self.stop()

elif command == 'kill':
self.exit = True

elif command == 'oust':
self.stop()
self.mumble.channels.find_by_name(self.channel).move_in()

elif command == 'joinme':
self.mumble.users.myself.move_in(self.mumble.users[texte.actor]['channel_id'])
elif command == 'v':
if parameter and parameter.replace('.', '', 1).isdigit() and parameter >= 0 and parameter <=1 :
print("changement de volume")
self.volume = float(parameter)

def play(self, msg):
if self.config.has_option('stream', msg):
url = self.config.get('stream', msg)
self.launch_play(url)
elif get_url(msg):
self.launch_play(get_url(msg))
else:
print("Bad URL")

def launch_play(self, url):
self.stop()

time.sleep(2)

command = ["ffmpeg", '-v', 'warning', '-nostdin', '-i', url, '-ac', '1', '-f', 's16le', '-ar', '48000', '-']
print(command)
self.thread = sp.Popen(command, stdout=sp.PIPE, bufsize=480)
self.set_comment("Stream from %s" % get_server_description(url))
time.sleep(3)
self.playing = True

def loop(self):
while not self.exit:
if self.playing:
while self.mumble.sound_output.get_buffer_size() > 0.5:
time.sleep(0.01)

self.mumble.sound_output.add_sound(audioop.mul(self.thread.stdout.read(480), 2, self.volume))
else:
time.sleep(1)

while self.mumble.sound_output.get_buffer_size() > 0:
time.sleep(0.01)
time.sleep(0.5)

def stop(self):
if self.thread:
self.thread.kill()
self.playing = False
print("Stop")

def set_comment(self, txt=None):
if txt is None:
txt = ""
self.config.get('server', 'comment')
self.mumble.users.myself.comment(txt + "<p /> " + self.config.get('server', 'comment'))


def get_url(url):
if url.startswith('http'):
return url
p = re.compile('href="(.+)"', re.IGNORECASE)
res = re.search(p, url)
if res:
return res.group(1)
else:
return False


def get_server_description(url):
p = re.compile('(https?\:\/\/[^\/]*)', re.IGNORECASE)
res = re.search(p, url)
base_url = res.group(1)
url_icecast = base_url + '/status-json.xsl'
url_shoutcast = base_url + '/stats?json=1'
request = urllib2.Request(url_icecast)
try:
response = urllib2.urlopen(request)
data = json.loads(response.read())
title_server = data['icestats']['source'][0]['server_name'] + ' - ' + data['icestats']['source'][0][
'server_description']
if not title_server:
request = urllib2.Request(url_shoutcast)
response = urllib2.urlopen(request)
data = json.loads(response.read())
title_server = data['servertitle']
if not title_server:
title_server = url
except:
title_server = url
return title_server


def get_title(url):
request = urllib2.Request(url)
try:
request.add_header('Icy-MetaData', 1)
response = urllib2.urlopen(request)
icy_metaint_header = response.headers.get('icy-metaint')
if icy_metaint_header is not None:
metaint = int(icy_metaint_header)
read_buffer = metaint + 255
content = response.read(read_buffer)
title = content[metaint:].split("'")
print(title)
except:
print('Error')


if __name__ == '__main__':
playbot = MumblePlayUrlBot()
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
opuslib==1.1.0
protobuf==2.6.1

0 comments on commit 56ca276

Please sign in to comment.