polyphonic/library/models.py
2021-03-11 09:32:44 +11:00

138 lines
4.1 KiB
Python

from django.conf import settings
from django.db import models
from django.utils.text import slugify
from django.core.files.storage import get_storage_class
import re
import logging
logger = logging.getLogger(__name__)
try:
library_storage = get_storage_class(settings.LIBRARY_STORAGE)()
except (ImportError, AttributeError):
library_storage = get_storage_class()()
logger.info("Library storage: %s", library_storage.__class__.__name__)
INSTRUMENTS = [
('Score', 'Score'),
('S', 'Soprano'),
('A', 'Alto'),
('T', 'Tenor'),
('B', 'Bass'),
('V', 'Vocals'),
('Vln', 'Violin'),
('Vla', 'Viola'),
('Vc', 'Violoncello'),
('Cb', 'Contrabass'),
('Fl', 'Flute'),
('Picc', 'Piccolo'),
('Cl', 'Clarinet'),
('Ob', 'Oboe'),
('Hn', 'Horn'),
('Tpt', 'Trumpet'),
('Tbn', 'Trombone'),
('Tuba', 'Tuba'),
('Timp', 'Timpani'),
('Drum', 'Drupset'),
('Perc', 'Percussion'),
('Pno', 'Piano'),
('Hp', 'Harp'),
]
ORCHESTRATIONS = {
'SATB': ('S', 'A', 'T', 'B'),
'String Quartet': ('Vln1', 'Vln2', 'Vla', 'Vc'),
'Chamber Orchestra': ('Vln1', 'Vln2', 'Vla', 'Vc', 'Cb',
'Fl1', 'Fl2', 'Cl1', 'Cl2', 'Hn1', 'Hn2',
'Tpt1', 'Tpt2', 'Tbn1', 'Tbn2', 'Tuba',
'Timp', 'Drum', 'Perc'),
'RWE': ('Fl1', 'Fl2', 'Cl', 'Tbn', 'Vln1', 'Vln2', 'Vla', 'Vc'),
'Custom': ()
}
def tag_to_instrument(tag):
m = re.match(r'([A-Za-z]+)(\d*)', tag)
if not m:
return tag
l = m.groups()
return "{0} {1}".format(dict(INSTRUMENTS).get(l[0],l[0]), l[1]).strip()
class Work(models.Model):
ensemble = models.ForeignKey('interface.Ensemble', on_delete=models.CASCADE, related_name="works")
slug = models.SlugField(max_length=100, editable=False)
name = models.CharField(max_length=255)
orchestration = models.CharField(max_length=100, choices=[ (k, k) for k, v in ORCHESTRATIONS.items() ])
running_time = models.IntegerField(null=True, blank=True)
notes = models.TextField(blank=True)
projects = models.ManyToManyField('interface.Project', through='Playlist', related_name="works")
class Meta:
unique_together = ['ensemble', 'slug']
@property
def parts(self):
return Part.objects.filter(doc__work=self.pk)
@property
def instruments(self):
tags = ORCHESTRATIONS.get(self.orchestration, 'Custom')
return [ (tag, tag_to_instrument(tag)) for tag in tags ]
def save(self):
if not self.slug:
self.slug = slugify(self.name)
super(Work, self).save()
def __str__(self):
return self.name
class Playlist(models.Model):
project = models.ForeignKey('interface.Project', on_delete=models.CASCADE)
work = models.ForeignKey('Work', on_delete=models.CASCADE)
order = models.SmallIntegerField(default=0)
class Meta:
ordering = ['order', 'work']
def __str__(self):
return f"<{self.project.slug}:{self.work.slug}>"
def upload_filename(instance, filename):
return f'{instance.work.ensemble.slug}/works/{instance.work.slug}/{filename}'
class Document(models.Model):
work = models.ForeignKey('Work', on_delete=models.CASCADE, related_name="docs")
upload = models.FileField(upload_to=upload_filename, storage=library_storage)
def __str__(self):
return self.upload.name
class Part(models.Model):
doc = models.ForeignKey(Document, on_delete=models.CASCADE, related_name="parts")
tag = models.SlugField(max_length=20)
start = models.SmallIntegerField(null=True, blank=True)
end = models.SmallIntegerField(null=True, blank=True)
notes = models.TextField(blank=True)
class Meta:
ordering = ['doc', 'start', 'pk']
@property
def instrument(self):
return tag_to_instrument(self.tag)
@property
def filename(self):
return slugify(f'{self.doc.work.name}_{self.instrument}') + '.pdf'
@property
def pagerange(self):
if self.start:
if self.end:
return f"{self.start}-{self.end}"
return str(self.start)
return "all"
def __str__(self):
return f'{self.doc.upload} [{self.pagerange}]'