#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Create a ``.pls`` playlist from music filenames.
Specify a path to be recursively searched for music files.
Requires Python 3.3 and the `pathlib` module, or Python 3.4+.
According to an `unofficial PLS format specification`__, the attribute
``NumberOfEntries`` can be placed *after* all entries. This allows to
iterate through filenames without keeping details for each entry in
memory.
__ http://forums.winamp.com/showthread.php?threadid=65772
:Copyright: 2007-2016 Jochen Kupperschmidt
:Date: 2016-03-28 (original release: 09-Feb-2007)
:License: MIT
:Website: http://homework.nwsnet.de/releases/1a02/#create-pls-playlists
"""
from argparse import ArgumentParser
from itertools import count
import os.path
from pathlib import Path
import re
from sys import stdout
PATTERN = re.compile('\.(mp3|ogg)$', re.I)
def parse_args():
"""Parse command line arguments."""
parser = ArgumentParser()
parser.add_argument('path', type=Path)
return parser.parse_args()
def find_files(path):
"""Return all matching files beneath the path."""
for root, dirs, files in os.walk(str(path)):
for fn in filter(PATTERN.search, files):
filename = os.path.join(root, fn)
yield Path(filename)
def generate_playlist(filenames):
"""Generate a PLS playlist from filenames."""
yield '[playlist]\n\n'
total = 0
entry_template = (
'File{number:d}={file}\n'
'Title{number:d}={title}\n'
'Length{number:d}=-1\n\n')
for track_entry in generate_track_entries(filenames):
total += 1
yield entry_template.format(**track_entry)
yield (
'NumberOfEntries={:d}\n'
'Version=2\n').format(total)
def generate_track_entries(filenames, start_number=1):
"""Generate track entries."""
numbers = count(start_number)
for number, filename in zip(numbers, filenames):
yield create_track_entry(number, filename)
def create_track_entry(number, path):
"""Create a track entry."""
title = path.stem
return {
'number': number,
'file': path,
'title': title,
}
if __name__ == '__main__':
args = parse_args()
paths = find_files(args.path)
stdout.writelines(generate_playlist(paths))