summaryrefslogblamecommitdiffstats
path: root/radio/radio.py
blob: 5106813bfb02e3e73b1ddce797f09efa0b7ce28c (plain) (tree)
1
2
3
4
5
6
7
8
9
                  
                          
                 



                            
                         
                      


                                                        


















                                                                                          
                                        


                                   
                                                    

                                   
                                              


                                    


                                                                                                                     
                                         

                             
                                                        



                                                                                                                          
                   
 
                                                         



                                                       
                                                                                                                     












                                                                                                
                                                    





                                                                                         
                                                                                
                                                                                                        
                                                
                                                                                                                          
                                                       

                                                                                 





                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       


                                                 

                                 
                           




                                                                        


                                                             
                                          


                                                          
                                                            
                                                
                                                 
                                                       

                                                                                                         
                                                                                
                                        

                                                                                     




                                               
                                                                                


                                  





                                                                                                                                                                                                                     
 


                                                                                                 

                       








                                                                                      
                                                                                 
                                                             
                                                         


                 
                 


                
                
#!/usr/bin/python3
from sys import path, argv
path.append("..")
from travnik import Torrent
import inotify.adapters
from threading import Thread
from random import randrange
from os import stat, path
from time import sleep
from pydub import AudioSegment
from pydub.playback import play
from socket import socket, AF_UNIX, AF_INET, SOCK_STREAM

import libtorrent

def random_file(torrent, save_path, endung=".flac"):
	def get_index_from_endung(chosen):
		for i in range(torrent.torrent_file().files().num_files()):
			if (torrent.torrent_file().files().file_path(i).endswith(endung)):
				if chosen == 0:
					return i
					break
				chosen -= 1
	prios = []
	for i in torrent.get_file_priorities():
		prios.append(0)
	endungs = 0
	for i in range(torrent.torrent_file().files().num_files()):
		if (torrent.torrent_file().files().file_path(i).endswith(endung)):
			endungs += 1
	if endungs == 0:
		print("no more endungs")
		return False
	chosen = randrange(endungs)
	tries_left = endungs
	print(f"there are {endungs} {endung} files")
	while True:
		if tries_left == 0:
			print("no more tries")
			return False
		tries_left -= 1
		try:
			p = save_path + "/" + torrent.torrent_file().files().file_path(get_index_from_endung(chosen))
			print(f"trying path {p} with stat")
			stat(p)
		except FileNotFoundError:
			break
		else:
			chosen = (chosen + 1) % endungs;
			continue
	prios[get_index_from_endung(chosen)] = 4
	torrent.prioritize_files(prios)
	print(f"random file {torrent.torrent_file().files().file_path(get_index_from_endung(chosen))} chosen to download")
	return True

def watcher(session, torrents, s, d, active_torrents=10):
	i = inotify.adapters.Inotify()
	i.add_watch(d)
	for event in i.event_gen(yield_nones=False):
		(_, type_names, path, filename) = event
		if ("IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names) and filename.endswith(".torrent"):
			t = Torrent()
			t.file(path + filename)
			for pth, size in t.paths():
				if pth[-1].endswith(b'.flac'):
					info = libtorrent.torrent_info(path + filename)
					torr = session.add_torrent({"ti": info, "save_path": s})
					random_file(torr, save_path=s);
					torrents.append(torr)
					if len(torrents) > active_torrents:
						session.remove_torrent(torrents[0])
						del torrents[0]
					break

def alerts(session, playstack, save_path, torrents):
	while True:
		session.wait_for_alert(86400*1000*21)
		for a in session.pop_alerts():
			if a.category() & libtorrent.alert.category_t.error_notification:
				print(f"error notification alert from libtorrent: {a}")
			if type(a) == libtorrent.file_completed_alert:
				if a.handle.get_file_priorities()[a.index] != 4:
					print(f"alerts: IT LOOKS LIKE THIS FILE WAS CHECKED FROM CACHE")
					continue
				fname = path.abspath(save_path + "/" + a.handle.torrent_file().files().file_path(a.index))
				playstack.append(fname)
				print(f"alerts: ADDED FILE {fname} to playstack")
				print(playstack)
				if not random_file(a.handle, save_path):
					session.remove_torrent(a.handle)
					torrents.remove(a.handle)
					continue
				else:
					a.handle.resume()
			if type(a) in [libtorrent.external_ip_alert, libtorrent.listen_succeeded_alert, libtorrent.dht_get_peers_alert, libtorrent.dht_outgoing_get_peers_alert, libtorrent.dht_reply_alert, libtorrent.torrent_added_alert, libtorrent.state_changed_alert, libtorrent.torrent_resumed_alert, libtorrent.stats_alert, libtorrent.torrent_checked_alert, libtorrent.peer_connect_alert, libtorrent.alert, libtorrent.peer_disconnected_alert, libtorrent.incoming_connection_alert, libtorrent.block_downloading_alert, libtorrent.dht_bootstrap_alert, libtorrent.dht_announce_alert, libtorrent.block_finished_alert, libtorrent.piece_finished_alert, libtorrent.peer_unsnubbed_alert, libtorrent.peer_snubbed_alert, libtorrent.portmap_error_alert, libtorrent.block_timeout_alert, libtorrent.block_uploaded_alert, libtorrent.performance_alert, libtorrent.cache_flushed_alert, libtorrent.dht_log_alert, libtorrent.portmap_log_alert, libtorrent.dht_pkt_alert, libtorrent.log_alert, libtorrent.peer_log_alert, libtorrent.picker_log_alert, libtorrent.torrent_log_alert, libtorrent.file_prio_alert, libtorrent.torrent_finished_alert, libtorrent.invalid_request_alert]:
				continue
			print(f"{type(a)} | {a}")

def stream(playstack, unix=None):
	if type(unix) is str:
		while True:
			if len(playstack) == 0:
				# print("stream: no songs in playstack")
				print(playstack)
				sleep(1)
				continue
			# sock = socket(AF_INET, SOCK_STREAM)
			# sock.connect("tranzistor", 1234)
			sock = socket(AF_UNIX, SOCK_STREAM)
			sock.connect(unix)
			sock.sendall(b"request.alive\r\n")
			sleep(1)
			data = sock.recv(256)
			print(f"stream: remote said {data}")
			a = data.split(b"\r")[0]
			if a == b"" or a == b"0":
				komad = playstack.pop()
				# komad = "/tmp/o.flac"
				sock.sendall(b"request.push " + bytes(komad, encoding="utf-8") + b"\r\n")
				print(f"stream: REQUESTING PLAYBACK of {komad}")
				sleep(1)
			else:
				print(f"stream: remote returned that {a} is playing")
	else:
		while True:
			if len(playstack) == 0:
				sleep(1)
				continue
			song = AudioSegment.from_file((playstack.pop()), "flac")
			play(song)
			sleep(1)

def progress(session, torrents):
	while True:
		for torr in torrents:
			s = torr.status()
			print(torr.torrent_file().name() + '\t%.2f%% complete (down: %.1f kB/s up: %.1f kB/s peers: %d) %s' % (s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, s.num_peers, s.state))
		sleep(1)

if __name__ == "__main__":
	session = libtorrent.session({"alert_mask": libtorrent.alert.category_t.all_categories});
	torrents = []
	playstack = []
	save_path = "."
	torrents_path = "."
	unix = None
	if len(argv) > 1:
		save_path = argv[1]
	if len(argv) > 2:
		torrents_path = argv[2]
	if len(argv) > 3:
		unix = argv[3]
	w = Thread(target=watcher, args=(session, torrents, save_path, torrents_path))
	a = Thread(target=alerts, args=(session, playstack, save_path, torrents))
	p = Thread(target=progress, args=(session, torrents))
	s = Thread(target=stream, args=(playstack, unix))
	w.start()
	a.start()
	p.start()
	s.start()
	w.join()
	a.join()
	p.join()
	s.join()