iTunesのライブラリをfoobar2000に変換


周知の通り、iPodという音楽プレイヤーは、

曲の管理にiTunesを使わざるを得ない仕組みになっています。



普段からiTunesを使っている人にとっては便利なのでしょうが、

私はiTunesが好きではありません。重いし、アンドゥできないし、リストの選択操作が変だし。



そこで、iTunesのプレイリストを、
軽くて、アンドゥが出来て、リスト選択がWindows標準の、foobar2000用に変換してみました。



#encoding:utf-8
#itunes_to_foobar2000.py
from __future__ import with_statement, division, print_function

import sys
from urllib import unquote
from itertools import *

from lxml.etree import *
import dateutil.parser

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

def xdict_to_obj(tree):
    d = {}
    for kxml, vxml in grouper(2, tree):
        k = unicode(kxml.text)
        v = xml_to_obj(vxml)
        d[k] = v
    return d

def xinteger_to_obj(tree):
    return int(tree.text)

def xstring_to_obj(tree):
    return unicode(tree.text)

def xtrue_to_obj(tree):
    return True
    
def xdate_to_obj(tree):
    return dateutil.parser.parse(tree.text)

def xarray_to_obj(tree):
    return list(map(xml_to_obj, tree))

def xdata_to_obj(tree):
    return unicode(tree.text)
    
def xml_to_obj(tree):
    return eval("x{0}_to_obj".format(tree.tag))(tree)

def itunes_to_foobar2000(path):
    with open(path, "r") as fp:
        tree = fromstring(fp.read())
    
    obj = xml_to_obj(tree[0])
    
    tracks = dict()
    from urlparse import urlparse
    for k, v in obj["Tracks"].iteritems():
        o = urlparse(v["Location"])
        if o.scheme == "file":
            tracks[int(k)] = unicode(unquote(str(o.path[1:])), "utf-8")
    
    for p in obj["Playlists"]:
        name = p["Name"]
        print(name.center(60, "-"))
        with open("{0}.m3u8".format(name), "w") as fp:
            for item in p.get('Playlist Items', []):
                id = item["Track ID"]
                try:
                    path = tracks[id]
                except KeyError as e:
                    print(e)
                else:
                    print(path.encode("utf-8"), file=fp)
    
def main():
    for path in sys.argv[1:]:
        itunes_to_foobar2000(path)
    
if __name__ == "__main__":
    main()


言うまでも無く、必ず動く保障はありません。

将来の仕様変更で使えなくなる可能性大です。