diff --git a/src/onthespot/gui/qtui/main.ui b/src/onthespot/gui/qtui/main.ui
index 9ea9feb..b0ad50c 100644
--- a/src/onthespot/gui/qtui/main.ui
+++ b/src/onthespot/gui/qtui/main.ui
@@ -656,9 +656,9 @@
0
- -1344
+ -907
627
- 3079
+ 3152
@@ -1707,6 +1707,73 @@
+ -
+
+
+ true
+
+
+
+
+
+ true
+
+
+
-
+
+
+
+
+
+
-
+
+
+ true
+
+
+ EXTINF Seperator
+
+
+
+ -
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+
+
+
+
-
+
+
+ true
+
+
+ EXTINF Path
+
+
+
+ -
+
+
+ true
+
+
+
+
+
+
+
+
+
-
diff --git a/src/onthespot/gui/settings.py b/src/onthespot/gui/settings.py
index b917cb9..10ef235 100644
--- a/src/onthespot/gui/settings.py
+++ b/src/onthespot/gui/settings.py
@@ -61,6 +61,8 @@ def load_config(self):
self.inp_podcast_path_formatter.setText(config.get("podcast_path_formatter"))
self.inp_playlist_path_formatter.setText(config.get("playlist_path_formatter"))
self.inp_m3u_name_formatter.setText(config.get("m3u_name_formatter"))
+ self.inp_ext_seperator.setText(config.get("ext_seperator"))
+ self.inp_ext_path.setText(config.get("ext_path"))
self.inp_album_cover_format.setText(config.get("album_cover_format"))
self.inp_search_thumb_height.setValue(config.get("search_thumb_height"))
self.inp_metadata_seperator.setText(config.get("metadata_seperator"))
@@ -143,6 +145,8 @@ def save_config(self):
config.set_('podcast_path_formatter', self.inp_podcast_path_formatter.text())
config.set_('playlist_path_formatter', self.inp_playlist_path_formatter.text())
config.set_('m3u_name_formatter', self.inp_m3u_name_formatter.text())
+ config.set_('ext_seperator', self.inp_ext_seperator.text())
+ config.set_('ext_path', self.inp_ext_path.text())
config.set_('album_cover_format', self.inp_album_cover_format.text())
config.set_('download_delay', self.inp_download_delay.value())
config.set_('chunk_size', self.inp_chunk_size.value())
diff --git a/src/onthespot/otsconfig.py b/src/onthespot/otsconfig.py
index 33280e9..bb14785 100755
--- a/src/onthespot/otsconfig.py
+++ b/src/onthespot/otsconfig.py
@@ -54,6 +54,8 @@ def __init__(self, cfg_path=None):
"playlist_path_formatter": "Playlists" + os.path.sep + "{playlist_name} by {playlist_owner}" + os.path.sep + "{name} - {artist}", # Playlist path format string
"m3u_name_formatter": "M3U" + os.path.sep + "{playlist_name} by {playlist_owner}", # M3U name format string
"m3u_format": "m3u8", # M3U file format
+ "ext_seperator": "; ", # M3U EXTINF metadata seperator
+ "ext_path": "{playlist_number}. {artist} - {name}", # M3U EXTINF path
"max_search_results": 10, # Number of search results to display of each type
"media_format": "mp3", # Song track media format
"podcast_media_format": "mp3", # Podcast track media format
diff --git a/src/onthespot/utils.py b/src/onthespot/utils.py
index 182aa45..6ece2b8 100644
--- a/src/onthespot/utils.py
+++ b/src/onthespot/utils.py
@@ -494,29 +494,49 @@ def fix_mp3_metadata(filename):
def add_to_m3u_file(item, item_metadata):
logger.info(f"Adding {item['file_path']} to m3u")
+
path = config.get("m3u_name_formatter")
+
m3u_file = path.format(
- playlist_name=sanitize_data(item['playlist_name']),
- playlist_owner=sanitize_data(item['playlist_by']),
+ playlist_name=sanitize_data(item['playlist_name']),
+ playlist_owner=sanitize_data(item['playlist_by']),
)
m3u_file += "." + config.get("m3u_format")
-
dl_root = config.get("download_root")
m3u_path = os.path.join(dl_root, m3u_file)
os.makedirs(os.path.dirname(m3u_path), exist_ok=True)
if not os.path.exists(m3u_path):
- with open(m3u_path, 'w') as m3u_file:
+ with open(m3u_path, 'w', encoding='utf-8') as m3u_file:
m3u_file.write("#EXTM3U\n")
+ EXTINF = config.get('ext_path').format(
+ service=item.get('item_service', '').title(),
+ artist=item_metadata.get('artists', ''),
+ album=item_metadata.get('album_name', ''),
+ album_artist=item_metadata.get('album_artists', ''),
+ name=item_metadata.get('title', ''),
+ year=item_metadata.get('release_year', ''),
+ disc_number=item_metadata.get('disc_number', ''),
+ track_number=item_metadata.get('track_number', ''),
+ genre=item_metadata.get('genre', ''),
+ label=item_metadata.get('label', ''),
+ explicit=str(config.get('explicit_label')) if item_metadata.get('explicit') else '',
+ trackcount=item_metadata.get('total_tracks', ''),
+ disccount=item_metadata.get('total_discs', ''),
+ playlist_name=item.get('playlist_name', ''),
+ playlist_owner=item.get('playlist_by', ''),
+ playlist_number=item.get('playlist_number', ''),
+ ).replace(config.get('metadata_seperator'), config.get('ext_seperator'))
+
# Check if the item_path is already in the M3U file
- with open(m3u_path, 'r') as m3u_file:
- m3u_item_header = f"#EXTINF:{round(int(item_metadata['length'])/1000)}, {item['playlist_number']}. {item_metadata['artists']} - {item_metadata['title']}"
+ with open(m3u_path, 'r', encoding='utf-8') as m3u_file:
+ m3u_item_header = f"#EXTINF:{round(int(item_metadata['length'])/1000)}, {EXTINF}"
m3u_contents = m3u_file.readlines()
if m3u_item_header not in [line.strip() for line in m3u_contents]:
- with open(m3u_path, 'a') as m3u_file:
+ with open(m3u_path, 'a', encoding='utf-8') as m3u_file:
m3u_file.write(f"{m3u_item_header}\n{item['file_path']}\n")
else:
logger.info(f"{item['file_path']} already exists in the M3U file.")