<commit_before># -*- coding: utf-8 -*-

# Licensed under the MIT license
# http://opensource.org/licenses/mit-license.php

# Copyright 2007,2008, <NAME> <<EMAIL>>

"""

MediaStore

A MediaServer with a database backend,
exposes its content in All, Albums and Artists containers.
Serves cover art with the Album object, and keeps references to
the MusicBrainz DB - http://musicbrainz.org/

Should not scan for files, but gets feeded
with proper tagged ones via some import tool
or/and allow imports via the web-UI.

depends on:
            for the sqlite db handling:

                Axiom - http://divmod.org/trac/wiki/DivmodAxiom
                Epsilon - http://divmod.org/trac/wiki/DivmodEpsilon

            for id3 tag extraction:

                libmtag - http://code.google.com/p/libmtag/
                taglib - http://developer.kde.org/~wheeler/taglib.html

                or

                pyid3lib - http://pyid3lib.sourceforge.net/doc.html

                or

                tagpy - http://news.tiker.net/software/tagpy
                taglib - http://developer.kde.org/~wheeler/taglib.html

            CoversByAmazon - https://coherence.beebits.net/browser/trunk/coherence/extern/covers_by_amazon.py
"""

import os, shutil
import string
import urllib

from urlparse import urlsplit

from axiom import store, item, attributes
from epsilon.extime import Time

import louie

from twisted.internet import reactor, defer

from twisted.python.filepath import FilePath
from coherence.upnp.core import DIDLLite

from coherence.extern.covers_by_amazon import CoverGetter

from coherence.backend import BackendItem, BackendStore


def _dict_from_tags(tag):
    tags = {}
    tags['artist'] = tag.artist.strip()
    tags['album'] = tag.album.strip()
    tags['title'] = tag.title.strip()
    if type(tag.track) == int:
        tags['track'] = tag.track
    elif type(tag.track) in (str, unicode):
        tags['track'] = int(tag.track.strip())
    else:
        tags['track'] = tag.track[0]

    for key in ('artist', 'album', 'title'):
        value = tags.get(key, u'')
        if isinstance(value, unicode):
            tags[key] = value.encode('utf-8')

    return tags

try:
    import libmtag

    def get_tags(filename):
        audio_file = libmtag.File(filename)
        tags = {}
        tags['artist'] = audio_file.tag().get('artist').strip()
        tags['album'] = audio_file.tag().get('album').strip()
        tags['title'] = audio_file.tag().get('title').strip()
        tags['track'] = audio_file.tag().get('track').strip()
        return tags

except ImportError:
    try:
        import pyid3lib

        def get_tags(filename):
            audio_file = pyid3lib.tag(filename)
            return _dict_from_tags(audio_file)

    except ImportError:
        try:
            import tagpy

            def get_tags(filename):
                audio_file = tagpy.FileRef(filename)
                return _dict_from_tags(audio_file.tag())
        except ImportError:
            get_tags = None

if not get_tags:
    raise ImportError, "we need some installed id3 tag library for this backend: python-tagpy, pyid3lib or libmtag"



MEDIA_DB = 'tests/media.db'

ROOT_CONTAINER_ID = 0
AUDIO_CONTAINER = 100
AUDIO_ALL_CONTAINER_ID = 101
AUDIO_ARTIST_CONTAINER_ID = 102
AUDIO_ALBUM_CONTAINER_ID = 103

def sanitize(filename):
    badchars = ''.join(set(string.punctuation) - set('-_+.~'))
    f = unicode(filename.lower())
    for old, new in ((u'ä','ae'),(u'ö','oe'),(u'ü','ue'),(u'ß','ss')):
        f = f.replace(unicode(old),unicode(new))
    f = f.replace(badchars, '_')
    return f

class Container(BackendItem):

    def __init__(self, id, parent_id, name, children_callback=None):
        self.id = id
        self.parent_id = parent_id
        self.name = name
        self.mimetype = 'directory'
        self.item = DIDLLite.Container(id, parent_id,self.name)
        self.update_id = 0
        if children_callback != None:
            self.children = children_callback
        else:
            self.children = []
        self.item.childCount = self.get_child_count()

    def add_child(self, child):
        self.children.append(child)
        self.item.childCount += 1

    def get_children(self,start=0,request_count=0):
        if callable(self.children):
            children = self.children()
        else:
            children = self.children
        if request_count == 0:
            return children[start:]
        else:
            return children[start:request_count]

    def get_child_count(self):
        if callable(self.children):
            return len(self.children())
        else:
            return len(self.children)

    def get_item(self):
        return self.item

    def get_name(self):
        return self.name

    def get_id(self):
        return self.id

class Artist(item.Item,BackendItem):
    """ definition for an artist """

    schemaVersion = 1
    typeName = 'artist'
    mimetype = 'directory'

    name = attributes.text(allowNone=False, indexed=True)
    musicbrainz_id = attributes.text()

    def get_children(self,start=0,request_count=0):
        all_id = 'artist_all_tracks_%d' % (self.storeID+1000)
        self.store.containers[all_id] = \
                Container( all_id, self.storeID+1000, 'All tracks of %s' % self.name,
                          children_callback=lambda :[x[1] for x in list(self.store.query((Album,Track),
                            attributes.AND(Album.artist == self,
                                           Track.album == Album.storeID),
                            sort=(Track.title.ascending)
                            ))])

        children = [self.store.containers[all_id]] + list(self.store.query(Album, Album.artist == self,sort=Album.title.ascending))
        if request_count == 0:
            return children[start:]
        else:
            return children[start:request_count]

    def get_child_count(self):
        return len(list(self.store.query(Album, Album.artist == self))) + 1

    def get_item(self):
        item = DIDLLite.MusicArtist(self.storeID+1000, AUDIO_ARTIST_CONTAINER_ID, self.name)
        return item

    def get_id(self):
        return self.storeID + 1000

    def get_name(self):
        return self.name

    def __repr__(self):
        return '<Artist %d name="%s" musicbrainz="%s">' \
               % (self.storeID, self.name.encode('ascii', 'ignore'), self.musicbrainz_id)

class Album(item.Item,BackendItem):
    """ definition for an album """

    schemaVersion = 1
    typeName = 'album'
    mimetype = 'directory'

    title = attributes.text(allowNone=False, indexed=True)
    musicbrainz_id = attributes.text()
    artist = attributes.reference(allowNone=False, indexed=True)
    cd_count = attributes.integer(default=1)
    cover = attributes.text(default=u'')

    def get_children(self,start=0,request_count=0):
        children = list(self.store.query(Track, Track.album == self,sort=Track.track_nr.ascending))
        if request_count == 0:
            return children[start:]
        else:
            return children[start:request_count]

    def get_child_count(self):
        return len(list(self.store.query(Track, Track.album == self)))

    def get_item(self):
        item = DIDLLite.MusicAlbum(self.storeID+1000, AUDIO_ALBUM_CONTAINER_ID, self.title)
        if len(self.cover)>0:
            _,ext =  os.path.splitext(self.cover)
            item.albumArtURI = ''.join((self.store.urlbase,str(self.get_id()),'?cover',ext))
        return item

    def get_id(self):
        return self.storeID + 1000

    def get_name(self):
        return self.title

    def get_cover(self):
        return self.cover

    def __repr__(self):
        return '<Album %d title="%s" artist="%s" #cds %d cover="%s" musicbrainz="%s">' \
               % (self.storeID, self.title.encode('ascii', 'ignore'),
                  self.artist.name.encode('ascii', 'ignore'),
                  self.cd_count,
                  self.cover.encode('ascii', 'ignore'),
                  self.musicbrainz_id)

class Track(item.Item,BackendItem):
    """ definition for a track """<commit_msg>add some more details to the Album and the Artist object<commit_after># -*- coding: utf-8 -*-

# Licensed under the MIT license
# http://opensource.org/licenses/mit-license.php

# Copyright 2007,2008, <NAME> <<EMAIL>>

"""

MediaStore

A MediaServer with a database backend,
exposes its content in All, Albums and Artists containers.
Serves cover art with the Album object, and keeps references to
the MusicBrainz DB - http://musicbrainz.org/

Should not scan for files, but gets feeded
with proper tagged ones via some import tool
or/and allow imports via the web-UI.

depends on:
            for the sqlite db handling:

                Axiom - http://divmod.org/trac/wiki/DivmodAxiom
                Epsilon - http://divmod.org/trac/wiki/DivmodEpsilon

            for id3 tag extraction:

                libmtag - http://code.google.com/p/libmtag/
                taglib - http://developer.kde.org/~wheeler/taglib.html

                or

                pyid3lib - http://pyid3lib.sourceforge.net/doc.html

                or

                tagpy - http://news.tiker.net/software/tagpy
                taglib - http://developer.kde.org/~wheeler/taglib.html

            CoversByAmazon - https://coherence.beebits.net/browser/trunk/coherence/extern/covers_by_amazon.py
"""

import os, shutil
import string
import urllib

from urlparse import urlsplit

from axiom import store, item, attributes
from epsilon.extime import Time

import louie

from twisted.internet import reactor, defer

from twisted.python.filepath import FilePath
from coherence.upnp.core import DIDLLite

from coherence.extern.covers_by_amazon import CoverGetter

from coherence.backend import BackendItem, BackendStore


def _dict_from_tags(tag):
    tags = {}
    tags['artist'] = tag.artist.strip()
    tags['album'] = tag.album.strip()
    tags['title'] = tag.title.strip()
    if type(tag.track) == int:
        tags['track'] = tag.track
    elif type(tag.track) in (str, unicode):
        tags['track'] = int(tag.track.strip())
    else:
        tags['track'] = tag.track[0]

    for key in ('artist', 'album', 'title'):
        value = tags.get(key, u'')
        if isinstance(value, unicode):
            tags[key] = value.encode('utf-8')

    return tags

try:
    import libmtag

    def get_tags(filename):
        audio_file = libmtag.File(filename)
        tags = {}
        tags['artist'] = audio_file.tag().get('artist').strip()
        tags['album'] = audio_file.tag().get('album').strip()
        tags['title'] = audio_file.tag().get('title').strip()
        tags['track'] = audio_file.tag().get('track').strip()
        return tags

except ImportError:
    try:
        import pyid3lib

        def get_tags(filename):
            audio_file = pyid3lib.tag(filename)
            return _dict_from_tags(audio_file)

    except ImportError:
        try:
            import tagpy

            def get_tags(filename):
                audio_file = tagpy.FileRef(filename)
                return _dict_from_tags(audio_file.tag())
        except ImportError:
            get_tags = None

if not get_tags:
    raise ImportError, "we need some installed id3 tag library for this backend: python-tagpy, pyid3lib or libmtag"



MEDIA_DB = 'tests/media.db'

ROOT_CONTAINER_ID = 0
AUDIO_CONTAINER = 100
AUDIO_ALL_CONTAINER_ID = 101
AUDIO_ARTIST_CONTAINER_ID = 102
AUDIO_ALBUM_CONTAINER_ID = 103

def sanitize(filename):
    badchars = ''.join(set(string.punctuation) - set('-_+.~'))
    f = unicode(filename.lower())
    for old, new in ((u'ä','ae'),(u'ö','oe'),(u'ü','ue'),(u'ß','ss')):
        f = f.replace(unicode(old),unicode(new))
    f = f.replace(badchars, '_')
    return f

class Container(BackendItem):

    def __init__(self, id, parent_id, name, children_callback=None):
        self.id = id
        self.parent_id = parent_id
        self.name = name
        self.mimetype = 'directory'
        self.item = DIDLLite.Container(id, parent_id,self.name)
        self.update_id = 0
        if children_callback != None:
            self.children = children_callback
        else:
            self.children = []
        self.item.childCount = self.get_child_count()

    def add_child(self, child):
        self.children.append(child)
        self.item.childCount += 1

    def get_children(self,start=0,request_count=0):
        if callable(self.children):
            children = self.children()
        else:
            children = self.children
        if request_count == 0:
            return children[start:]
        else:
            return children[start:request_count]

    def get_child_count(self):
        if callable(self.children):
            return len(self.children())
        else:
            return len(self.children)

    def get_item(self):
        return self.item

    def get_name(self):
        return self.name

    def get_id(self):
        return self.id

class Artist(item.Item,BackendItem):
    """ definition for an artist """

    schemaVersion = 1
    typeName = 'artist'
    mimetype = 'directory'

    name = attributes.text(allowNone=False, indexed=True)
    musicbrainz_id = attributes.text()

    def get_children(self,start=0,request_count=0):
        all_id = 'artist_all_tracks_%d' % (self.storeID+1000)
        self.store.containers[all_id] = \
                Container( all_id, self.storeID+1000, 'All tracks of %s' % self.name,
                          children_callback=lambda :[x[1] for x in list(self.store.query((Album,Track),
                            attributes.AND(Album.artist == self,
                                           Track.album == Album.storeID),
                            sort=(Track.title.ascending)
                            ))])

        children = [self.store.containers[all_id]] + list(self.store.query(Album, Album.artist == self,sort=Album.title.ascending))
        if request_count == 0:
            return children[start:]
        else:
            return children[start:request_count]

    def get_child_count(self):
        return len(list(self.store.query(Album, Album.artist == self))) + 1

    def get_item(self):
        item = DIDLLite.MusicArtist(self.storeID+1000, AUDIO_ARTIST_CONTAINER_ID, self.name)
        item.childCount = self.get_child_count()
        return item

    def get_id(self):
        return self.storeID + 1000

    def get_name(self):
        return self.name

    def __repr__(self):
        return '<Artist %d name="%s" musicbrainz="%s">' \
               % (self.storeID, self.name.encode('ascii', 'ignore'), self.musicbrainz_id)

class Album(item.Item,BackendItem):
    """ definition for an album """

    schemaVersion = 1
    typeName = 'album'
    mimetype = 'directory'

    title = attributes.text(allowNone=False, indexed=True)
    musicbrainz_id = attributes.text()
    artist = attributes.reference(allowNone=False, indexed=True)
    cd_count = attributes.integer(default=1)
    cover = attributes.text(default=u'')

    def get_children(self,start=0,request_count=0):
        children = list(self.store.query(Track, Track.album == self,sort=Track.track_nr.ascending))
        if request_count == 0:
            return children[start:]
        else:
            return children[start:request_count]

    def get_child_count(self):
        return len(list(self.store.query(Track, Track.album == self)))

    def get_item(self):
        item = DIDLLite.MusicAlbum(self.storeID+1000, AUDIO_ALBUM_CONTAINER_ID, self.title)
        item.artist = self.artist.name
        item.childCount = self.get_child_count()
        if len(self.cover)>0:
            _,ext =  os.path.splitext(self.cover)
            item.albumArtURI = ''.join((self.store.urlbase,str(self.get_id()),'?cover',ext))
        return item

    def get_id(self):
        return self.storeID + 1000

    def get_name(self):
        return self.title

    def get_cover(self):
        return self.cover

    def __repr__(self):
        return '<Album %d title="%s" artist="%s" #cds %d cover="%s" musicbrainz="%s">' \
               % (self.storeID, self.title.encode('ascii', 'ignore'),
                  self.artist.name.encode('ascii', 'ignore'),
                  self.cd_count,
                  self.cover.encode('ascii', 'ignore'),
                  self.musicbrainz_id)

class Track(item.Item,BackendItem):
    """ definition for a track """
{'fraction_non_alphanumeric': 0.12050534499514091, 'fraction_numerical': 0.008746355685131196, 'mean_word_length': 2.4409613375130617, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '508731', 'n_tokens_mistral': 5336, 'n_tokens_neox': 5003, 'n_words': 1084}