summaryrefslogblamecommitdiffstats
path: root/radio/radio.py
blob: b9806ca5c15a540ea3ca8c6a5976eeef53ce6e3d (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
				playstack.append(a.handle.torrent_file().files().file_path(a.index))
				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]:
				continue
			print(f"{type(a)} | {a}")

def stream(playstack, unix=None):
	if type(unix) is str:
		while True:
			# 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)
			a = data.split(b"\r")[0]
			if a == b"":
				komad = playstack.pop()
				sock.sendall(b"request.push " + bytes(komad, encoding="utf-8"))
				print(f"stream: REQUESTING PLAYBACK of {komad}")
				sleep(1)
	else:
		while True:
			if len(playstack) == 0:
				sleep(1)
				continue
			song = AudioSegment.from_file(path.abspath(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()