xspf2m3u

simple XSPF to M3U conversion
git clone https://git.ce9e.org/xspf2m3u.git

commit
a9fd607c920be4c97111e2167c62da50b939bb6c
parent
f01110dd2ae907be23b4ed797378b225ecbe6d73
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2022-03-06 16:27
download from youtube if --outdir is given

Diffstat

M xspf2m3u.py 73 +++++++++++++++++++++++++++++++++++++++++++------------------

1 files changed, 52 insertions, 21 deletions


diff --git a/xspf2m3u.py b/xspf2m3u.py

@@ -2,7 +2,10 @@
    2     2 
    3     3 import os
    4     4 import re
   -1     5 import sys
    5     6 import argparse
   -1     7 import subprocess
   -1     8 from time import sleep
    6     9 from xml.etree import ElementTree
    7    10 
    8    11 try:
@@ -23,6 +26,32 @@ CHARS = re.compile('[^a-z0-9 ]')
   23    26 __version__ = '0.0.0'
   24    27 
   25    28 
   -1    29 class DownloadPool(set):
   -1    30 	def log(self, s):
   -1    31 		print(s, file=sys.stderr, end='\r')
   -1    32 
   -1    33 	def download(self, url, path):
   -1    34 		self.add(subprocess.Popen(['curl', url, '-s', '-o', path]))
   -1    35 
   -1    36 	def poll(self):
   -1    37 		for p in list(self):
   -1    38 			if p.poll() is not None:
   -1    39 				self.remove(p)
   -1    40 		return len(self)
   -1    41 
   -1    42 	def __enter__(self):
   -1    43 		return self
   -1    44 
   -1    45 	def __exit__(self, exc_type, exc_value, traceback):
   -1    46 		if exc_type is None:
   -1    47 			while self.poll():
   -1    48 				self.log('{} downloads still active'.format(len(self)))
   -1    49 				sleep(5)
   -1    50 		else:
   -1    51 			for p in self:
   -1    52 				p.kill()
   -1    53 
   -1    54 
   26    55 def iter_files(folder):
   27    56 	for dirpath, dirnames, filenames in os.walk(folder):
   28    57 		for filename in filenames:
@@ -102,28 +131,30 @@ def main():
  102   131 	if args.outdir:
  103   132 		os.makedirs(args.outdir)
  104   133 
  105    -1 	for track in iter_tracks(args.src):
  106    -1 		location = track['location']
  107    -1 
  108    -1 		if location is None:
  109    -1 			context_key = ['creator', 'annotation']
  110    -1 			context = [track[k] for k in context_key if track[k]]
  111    -1 			location = find_by_title(track['title'], context, files)
  112    -1 			if location and args.outdir:
  113    -1 				location = hard_link(location, args.outdir)
  114    -1 
  115    -1 		if location is None and args.youtube and youtube_dl:
  116    -1 			url, filename = search_youtube([q for q in track.values() if q])
  117    -1 			if args.outdir:
  118    -1 				location = os.path.join(args.outdir, filename)
   -1   134 	with DownloadPool() as pool:
   -1   135 		for track in iter_tracks(args.src):
   -1   136 			location = track['location']
   -1   137 
   -1   138 			if location is None:
   -1   139 				context_key = ['creator', 'annotation']
   -1   140 				context = [track[k] for k in context_key if track[k]]
   -1   141 				location = find_by_title(track['title'], context, files)
   -1   142 				if location and args.outdir:
   -1   143 					location = hard_link(location, args.outdir)
   -1   144 
   -1   145 			if location is None and args.youtube and youtube_dl:
   -1   146 				url, filename = search_youtube([q for q in track.values() if q])
   -1   147 				if args.outdir:
   -1   148 					location = os.path.join(args.outdir, filename)
   -1   149 					pool.download(url, location)
   -1   150 				else:
   -1   151 					location = url
   -1   152 
   -1   153 			if location is None:
   -1   154 				s = ' - '.join('{}: {}'.format(k, v) for k, v in track.items())
   -1   155 				print('# Warning: ' + s)
  119   156 			else:
  120    -1 				location = url
  121    -1 
  122    -1 		if location is None:
  123    -1 			s = ' - '.join('{}: {}'.format(k, v) for k, v in track.items())
  124    -1 			print('# Warning: ' + s)
  125    -1 		else:
  126    -1 			print(location)
   -1   157 				print(location)
  127   158 
  128   159 
  129   160 if __name__ == '__main__':