LINUX.ORG.RU

Ткните носом в косяки


0

0

Нацарапано не профита ради, но языка освоения для, так что интересует мнение знающих людей. Вроде работает и тэги должным образом проставляет.

#!/usr/bin/env python
#_*_coding: utf-8_*_
"""splits .iso.wv images to .flack tracks"""
import sys, os, subprocess, shutil

class DstDir:
    def __init__ (self, path, img, cue='', src='', dirs=None, other=None):
        self.path = path
        self.img = img
        self.cue = cue
        self.src = src
        if dirs == None:
            self.dirs = []
        else:
            self.dirs = dirs
        if other == None:
            self.other = []
        else:
            self.other = other
        self.tracks = []
        self.album = ''

    def makeFlac (self):
        cuebreakpoints = subprocess.Popen(["cuebreakpoints", self.cue],
                stdout=subprocess.PIPE)
        cmd = ["shnsplit", "-O", "always", "-i", "wv", "-o",
                "flac flac -V -8 -e -p -o %f -",
                "-t", "-%n", self.src]
        shnsplit = subprocess.Popen(cmd,
                stdin=cuebreakpoints.stdout,
                stdout=subprocess.PIPE,
                cwd=self.path)
        shnsplit.wait()

    def tagFlack (self):
        subprocess.Popen(["recode", "cp1251..utf8"],
                stdin=open(self.cue),
                stdout=open(self.path + "/tmp.cue", "w")).wait()
        self.cue = self.path + "/tmp.cue"
        cmd = ["cueprint", "-n", "1", "-t", "%T", self.cue]
        self.album = subprocess.Popen(cmd,
                stdout=subprocess.PIPE).communicate()[0]

        try:
            year = subprocess.Popen(["grep", "REM DATE", self.cue],
                    stdout=subprocess.PIPE).communicate()[0].split()[2]
        except IndexError:
            year = "0000"

        tag_names = ("ARRANGER=%A\nCOMPOSER=%C\nGENRE=%G\nMESSAGE=%M\n" +
                "TRACKNUMBER=%n\nARTIST=%p\nTITLE=%t\nALBUM=%T\nDATE=" + 
                str(year) + "\n\n")
        cmd = ["cueprint", "-t", tag_names, self.cue]
        cueprint = subprocess.Popen(cmd, stdout=subprocess.PIPE)
        cueprint.wait()
        tracks = {}
        n = 1

        for i in cueprint.communicate()[0].split("\n\n")[:-1]:
            tracks[n] = i
            name = "%s/%02d.flac" % (self.path, n)
            new_name = tracks[n].split("\n")[6].split("=")[1]
            new_name = new_name.replace("/", "aka")
            new_name = "%s/%d-%s.flac" % (self.path, n, new_name)
            metaflac = subprocess.Popen(["metaflac", "--import-tags-from=-",
                name],
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE)
            actual_tags = ''
            for line in tracks[n].split("\n"):
                if line[-1] != "=":
                    actual_tags += line + "\n"
            metaflac.communicate(actual_tags)
            metaflac.wait()
            os.rename(name, new_name)
            self.tracks.append(new_name)
            n += 1

        self.album = year + "-" + self.album

    def moveFiles(self, album=''):
        print "moving files"
        if album == '': album = self.album
        dst = self.path + "/../" + album + "/"
        if os.path.exists(dst):
            dst = "%s%s/" % (dst, self.img.split("/")[-1][:-7])

        os.mkdir(dst)

        for dir in self.dirs:
            shutil.copytree(dir, "%s%s" 
                    % (dst, dir.split("/")[-1]))

        for track in self.tracks:
            print "shutil.move(%s,%s)" % (track, dst)
            shutil.move(track, dst)

        for item in self.other:
            shutil.copy(item,"%s%s"
                    % (dst, item.split("/")[-1]))

        os.remove(self.cue)

def getContent(dst_dir, cur_dir, files):
    while files != []:
        dst_dir.other.append(cur_dir + "/" + files.pop())

    for cur_file in dst_dir.other:
        if os.path.isdir(cur_file):
            dst_dir.other.remove(cur_file)
            dst_dir.dirs.append(cur_file)

    for cur_file in dst_dir.other:
        if dst_dir.cue != '': break
        if cur_file[-4:] == ".cue":
            dst_dir.cue = cur_file

    for cur_file in dst_dir.other:
        if dst_dir.src != '': break
        if cur_file[-3:] == ".wv":
             dst_dir.other.remove(cur_file)
             dst_dir.src = cur_file

######################################MAIN######################################
if not os.path.isdir(sys.argv[1]): raise AssertionError, "Not directory!"

work_dir = os.path.normpath(sys.argv[1])
work_list = []

for cur_dir in os.walk(work_dir):
    for cur_file in cur_dir[2]:
        if cur_file[-7:] == ".iso.wv":
            work_list.append(cur_dir[0] + "/" + cur_file)

if work_list == []: sys.exit()

for img in work_list: 
    tmp_dir = os.path.dirname(img) + "/tmp"
    mnt_dir = tmp_dir + "/mnt"
    os.mkdir(tmp_dir)
    os.mkdir(mnt_dir)

    if subprocess.call(["sudo", "mount", "-o", 
        "loop", "-o", "ro", img, mnt_dir]) == 0:
    else:
        raise RuntimeError, "Cant mount image!"

    try:
        WDir = DstDir(tmp_dir, img)
        os.path.walk(mnt_dir, getContent, WDir)
        WDir.makeFlac()
        WDir.tagFlack()
        WDir.moveFiles()
    finally: #pass
        if subprocess.call(["sudo", "umount", mnt_dir]) !=0:
            raise RuntimeError, "Cant umount image!"
        os.rmdir(mnt_dir)
        os.rmdir(tmp_dir)

    os.remove(img)

> subprocess.Popen > subprocess.call

не знам что твой скрипт делает, но подозореваю что на шелле это можно было бы написать строк в 5.

dilmah ★★★★★
()

>Ткните носом в косяки
>#!/usr/bin/env python

Dimanc ★★
()
Ответ на: комментарий от dimon555

Добил комментариев

#!/usr/bin/env python
#_*_coding: utf-8_*_
"""Разбивает .iso.wv образы в папке на отдельные треки в формате .flack
c сохранением структуры, записывает теги."""
import sys, os, subprocess, shutil

class DstDir:
    """Объект обрабатываемого образа. Хранит список файлов. Методы разбивают
    исходный файл на треки, проставляют тэги, раскладывают это всё по папкам."""
    def __init__ (self, path, img, cue='', src='', dirs=None, other=None):
        """инициализируемся"""
        self.path = path
        self.img = img
        self.cue = cue
        self.src = src
        if dirs == None:
            self.dirs = []
        else:
            self.dirs = dirs
        if other == None:
            self.other = []
        else:
            self.other = other
        self.tracks = []
        self.album = ''

    def makeFlac (self):
        """рубим wavepak на флаки, процесс стандартен"""
        # cuebreakpoints не разбирает некоторые .cue, надо будет дописать
        # обработчик для таких случаев
        cuebreakpoints = subprocess.Popen(["cuebreakpoints", self.cue],
                stdout=subprocess.PIPE)
        # ключики для shnsplit полностью скатаны
        cmd = ["shnsplit", "-O", "always", "-i", "wv", "-o",
                "flac flac -V -8 -e -p -o %f -",
                "-t", "-%n", self.src]
        shnsplit = subprocess.Popen(cmd,
                stdin=cuebreakpoints.stdout,
                stdout=subprocess.PIPE,
                cwd=self.path)
        shnsplit.wait()

    def tagFlack (self):
        """пытаемся собрать информацию для заполнения тэгов. много костылей"""
        # перекодируем .cue в православный юникод
        subprocess.Popen(["recode", "cp1251..utf8"],
                stdin=open(self.cue),
                stdout=open(self.path + "/tmp.cue", "w")).wait()
        # сохраняем в объекте адрес юникодного файла, ещё понадобится
        self.cue = self.path + "/tmp.cue"
        # выдёргиваем и сохраняем имя альбома
        cmd = ["cueprint", "-n", "1", "-t", "%T", self.cue]
        self.album = subprocess.Popen(cmd,
                stdout=subprocess.PIPE).communicate()[0]
        print "album name extracted", self.album

        # пытаемся выдернуть из .cue год выпуска, в cueprint почему-то нет для
        # этого опции, к тому же некоторые редиски его не записывают вообще
        try:
            year = subprocess.Popen(["grep", "REM DATE", self.cue],
                    stdout=subprocess.PIPE).communicate()[0].split()[2]
        except IndexError:
            year = "0000"
        print "album year extracted", year

        # набор интересующих тэгов
        tag_names = ("ARRANGER=%A\nCOMPOSER=%C\nGENRE=%G\nMESSAGE=%M\n" +
                "TRACKNUMBER=%n\nARTIST=%p\nTITLE=%t\nALBUM=%T\nDATE=" + 
                str(year) + "\n\n")
        # выдёргиваем всё что есть в .cue одной строкой
        cmd = ["cueprint", "-t", tag_names, self.cue]
        cueprint = subprocess.Popen(cmd, stdout=subprocess.PIPE)
        cueprint.wait()
        print "tracks metadata extracted"

        # составляем из этой строки словарь вида номер_трека->его_тэги
        tracks = {}
        n = 1
        for i in cueprint.communicate()[0].split("\n\n")[:-1]:
            tracks[n] = i
            name = "%s/%02d.flac" % (self.path, n)
            # magic numbers в полный рост, цепляем из тегов название песни
            new_name = tracks[n].split("\n")[6].split("=")[1]
            # делаем из названия песни название файла
            new_name = new_name.replace("/", "aka")
            new_name = "%s/%d-%s.flac" % (self.path, n, new_name)
            # пишем теги в файл
            metaflac = subprocess.Popen(["metaflac", "--import-tags-from=-",
                name],
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE)
            # выбираем только непустые
            actual_tags = ''
            for line in tracks[n].split("\n"):
                if line[-1] != "=":
                    actual_tags += line + "\n"
            metaflac.communicate(actual_tags)
            metaflac.wait()
            # переименовываем обработанный файл (# - название.flac 
            # вместо #.flac)
            os.rename(name, new_name)
            self.tracks.append(new_name)
            n += 1
        # сохраняем название альбома в виде "год-название", потом понадобится
        self.album = year + "-" + self.album
        print self.album
        print "taging completed"

    def moveFiles(self, album=''):
        """создаём папку с альбомом и закидываем туда всё"""
        print "moving files"
        if album == '': album = self.album
        dst = self.path + "/../" + album + "/"
        # если уже есть папка с таким названием, создаём в ней подпапку
        # по имени исходного образа (я пока не понял, чем отличаются 2
        # издания Кунсткамеры 98 года, но ещё попытаюсь)
        if os.path.exists(dst):
            dst = "%s%s/" % (dst, self.img.split("/")[-1][:-7])

        os.mkdir(dst)
        print "destination dir ready"
        
        # копируем обложки, или что там ещё может в папках лежать
        # т.к. образ смонтирован ro
        for dir in self.dirs:
            shutil.copytree(dir, "%s%s" 
                    % (dst, dir.split("/")[-1]))
        print "covers and scans moved"
        
        # перекидываем песни из временной папки в папку с альбомом
        for track in self.tracks:
            shutil.move(track, dst)
        print "tracks moved"

        # перекидываем всё остальное (логи etc.)
        for item in self.other:
            shutil.copy(item,"%s%s"
                    % (dst, item.split("/")[-1]))
        print "all files moved"
        
        os.remove(self.cue)
        print "tmp.cue removed"

def getContent(dst_dir, cur_dir, files):
    """Работает callback'ом в os.path.walk.
    Забиваем в объект содержимое образа для дальнейшей обработки"""

    while files != []:
        dst_dir.other.append(cur_dir + "/" + files.pop())

    for cur_file in dst_dir.other:
        if os.path.isdir(cur_file):
            dst_dir.other.remove(cur_file)
            dst_dir.dirs.append(cur_file)

    # хватаем первый попавшийся в образе .cue
    for cur_file in dst_dir.other:
        if dst_dir.cue != '': break
        if cur_file[-4:] == ".cue":
            dst_dir.cue = cur_file
    # хватаем звук для нарезки, вряд ли их больше одного
    for cur_file in dst_dir.other:
        if dst_dir.src != '': break
        if cur_file[-3:] == ".wv":
             dst_dir.other.remove(cur_file)
             dst_dir.src = cur_file
Lonli-Lokli ★★
() автор топика
Ответ на: комментарий от Lonli-Lokli
######################################MAIN######################################
if not os.path.isdir(sys.argv[1]): raise AssertionError, "Not directory!"

work_dir = os.path.normpath(sys.argv[1])
work_list = []

# составляем список образов для обработки
for cur_dir in os.walk(work_dir):
    for cur_file in cur_dir[2]:
        if cur_file[-7:] == ".iso.wv":
            work_list.append(cur_dir[0] + "/" + cur_file)

if work_list == []: sys.exit()

# хватаем, потрошим, выкидываем исходник
for img in work_list: 
    print img
    tmp_dir = os.path.dirname(img) + "/tmp"
    mnt_dir = tmp_dir + "/mnt"
    os.mkdir(tmp_dir)
    os.mkdir(mnt_dir)

    if subprocess.call(["sudo", "mount", "-o", 
        "loop", "-o", "ro", img, mnt_dir]) == 0:
        print "Ok!"
    else:
        raise OSError, "Cant mount image!"

    try:
        WDir = DstDir(tmp_dir, img)
        os.path.walk(mnt_dir, getContent, WDir)
        print "DOING STAFF"
        print "Source: ", WDir.src, os.path.exists(WDir.src)
        print ".cue file: ", WDir.cue
        WDir.makeFlac()
        WDir.tagFlack()
        WDir.moveFiles()
    finally: #pass
        if subprocess.call(["sudo", "umount", mnt_dir]) !=0:
            raise OSError, "Cant umount image!"
        os.rmdir(mnt_dir)
        os.rmdir(tmp_dir)

    os.remove(img)

вдохновлялся скриптом в этом топике www.linux.org.ru/view-message.jsp?msgid=1966695

Lonli-Lokli ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.