Changeset d511f9f
- Timestamp:
- 12/07/11 15:32:19 (18 months ago)
- Branches:
- master, crem, crem2, dev, dev2, diadems, forma, generic, instru_search, lam, nlivemulti, production, release/1.4.4, security, social, storage, test, video
- Children:
- 06ce8dd
- Parents:
- 40aa64b
- git-author:
- yomguy <yomguy@…> (12/07/11 15:32:19)
- git-committer:
- yomguy <yomguy@…> (12/07/11 15:32:19)
- Location:
- telemeta
- Files:
-
- 3 edited
-
__init__.py (modified) (4 diffs)
-
models/media.py (modified) (39 diffs)
-
web/base.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
telemeta/__init__.py
r887f937 rd511f9f 13 13 14 14 __docformat__ = 'epytext en' 15 __version__ = '1. 3'15 __version__ = '1.4' 16 16 __url__ = 'http://telemeta.org' 17 17 __copyright__ = '(C) 2007-2011 Parisson' … … 24 24 <riccardo.zaccarelli@gmail.com> 25 25 26 This software is a computer program whose purpose is to backup, analyse, 26 This software is a computer program whose purpose is to backup, analyse, 27 27 transcode and stream any audio content with its metadata. 28 28 29 29 This software is governed by the CeCILL v2 license under French law and 30 abiding by the rules of distribution of free software. You can use, 30 abiding by the rules of distribution of free software. You can use, 31 31 modify and/ or redistribute the software under the terms of the CeCILL 32 32 license as circulated by CEA, CNRS and INRIA at the following URL 33 "http://www.cecill.info". 33 "http://www.cecill.info". 34 34 35 35 As a counterpart to the access to the source code and rights to copy, … … 37 37 with a limited warranty and the software's author, the holder of the 38 38 economic rights, and the successive licensors have only limited 39 liability. 39 liability. 40 40 41 41 In this respect, the user's attention is drawn to the risks associated … … 46 46 professionals having in-depth computer knowledge. Users are therefore 47 47 encouraged to load and test the software's suitability as regards their 48 requirements in conditions enabling the security of their systems and/or 49 data to be ensured and, more generally, to use and operate it in the 50 same conditions as regards security. 48 requirements in conditions enabling the security of their systems and/or 49 data to be ensured and, more generally, to use and operate it in the 50 same conditions as regards security. 51 51 52 52 The fact that you are presently reading this means that you have had -
telemeta/models/media.py
r33d177a rd511f9f 51 51 from django.db.models.fields import URLField 52 52 53 53 54 54 collection_published_code_regex = '[A-Za-z0-9._-]*' 55 55 collection_unpublished_code_regex = '[A-Za-z0-9._-]*' 56 collection_code_regex = '(?:%s|%s)' % (collection_published_code_regex, 56 collection_code_regex = '(?:%s|%s)' % (collection_published_code_regex, 57 57 collection_unpublished_code_regex) 58 58 … … 77 77 def set_revision(self, user): 78 78 "Save a media object and add a revision" 79 Revision.touch(self, user) 79 Revision.touch(self, user) 80 80 81 81 def get_revision(self): … … 87 87 class MediaRelated(MediaResource): 88 88 "Related media" 89 89 90 90 element_type = 'media' 91 91 92 92 title = CharField(_('title')) 93 93 date = DateTimeField(_('date'), auto_now=True) … … 97 97 credits = CharField(_('credits')) 98 98 file = FileField(_('file'), upload_to='items/%Y/%m/%d', db_column="filename") 99 99 100 100 def is_image(self): 101 101 is_url_image = False … … 106 106 is_url_image = True 107 107 return 'image' in self.mime_type or is_url_image 108 108 109 109 def save(self, force_insert=False, force_update=False): 110 110 super(MediaRelated, self).save(force_insert, force_update) 111 111 112 112 def set_mime_type(self): 113 113 if self.file: 114 114 self.mime_type = mimetypes.guess_type(self.file.path)[0] 115 115 116 116 def __unicode__(self): 117 117 if self.title and not re.match('^ *N *$', self.title): … … 120 120 title = unicode(self.item) 121 121 return title 122 122 123 123 class Meta: 124 124 abstract = True … … 127 127 class MediaCorpus(MediaResource): 128 128 "Describe a corpus of collections" 129 129 130 130 element_type = 'corpus' 131 131 … … 135 135 description = CharField(_('description')) 136 136 code = CharField(_('code'), unique=True, required=True) 137 public_access = CharField(_('public access'), choices=PUBLIC_ACCESS_CHOICES, 137 public_access = CharField(_('public access'), choices=PUBLIC_ACCESS_CHOICES, 138 138 max_length=16, default="metadata") 139 139 140 140 def __unicode__(self): 141 141 return self.code … … 147 147 def save(self, force_insert=False, force_update=False, user=None, code=None): 148 148 super(MediaCorpus, self).save(force_insert, force_update) 149 149 150 150 class Meta(MetaCore): 151 151 db_table = 'media_corpus' … … 155 155 class MediaCorpusCollectionRelation(ModelCore): 156 156 "Relations between Corpus and Collections" 157 158 collection = ForeignKey('MediaCollection', related_name="parent_relation", 157 158 collection = ForeignKey('MediaCollection', related_name="parent_relation", 159 159 verbose_name=_('collection')) 160 corpus = ForeignKey('MediaCorpus', related_name="child_relation", 160 corpus = ForeignKey('MediaCorpus', related_name="child_relation", 161 161 verbose_name=_('corpus')) 162 162 … … 164 164 db_table = 'media_corpus_collection_relations' 165 165 unique_together = (('collection', 'corpus'),) 166 166 167 167 def __unicode__(self): 168 168 sep = ' > ' 169 169 return self.corpus.code + sep + self.collection.code 170 170 171 171 172 172 class MediaCollection(MediaResource): 173 173 "Describe a collection of items" 174 174 175 175 element_type = 'collection' 176 176 … … 180 180 if not re.match(regex, value): 181 181 raise ValidationError(u'%s is not a valid collection code' % value) 182 182 183 183 # General informations 184 184 reference = CharField(_('reference'), unique=True, null=True) … … 186 186 alt_title = CharField(_('original title / translation')) 187 187 creator = CharField(_('depositor / contributor')) 188 recording_context = WeakForeignKey('RecordingContext', related_name="collections", 188 recording_context = WeakForeignKey('RecordingContext', related_name="collections", 189 189 verbose_name=_('recording context')) 190 190 recorded_from_year = IntegerField(_('recording year (from)')) 191 191 recorded_to_year = IntegerField(_('recording year (until)')) 192 192 year_published = IntegerField(_('year published')) 193 193 194 194 # Geographic and cultural informations 195 195 ## See "countries" and "ethnic_groups" methods below … … 197 197 # Legal notices 198 198 collector = CharField(_('recordist')) 199 publisher = WeakForeignKey('Publisher', related_name="collections", 200 verbose_name=_('publisher / status')) 201 publisher_collection = WeakForeignKey('PublisherCollection', related_name="collections", 199 publisher = WeakForeignKey('Publisher', related_name="collections", 200 verbose_name=_('publisher / status')) 201 publisher_collection = WeakForeignKey('PublisherCollection', related_name="collections", 202 202 verbose_name=_('publisher collection')) 203 203 publisher_serial = CharField(_('publisher serial number')) … … 205 205 external_references = TextField(_('bibliographic references')) 206 206 doctype_code = IntegerField(_('document type')) 207 public_access = CharField(_('public access'), choices=PUBLIC_ACCESS_CHOICES, 207 public_access = CharField(_('public access'), choices=PUBLIC_ACCESS_CHOICES, 208 208 max_length=16, default="metadata") 209 legal_rights = WeakForeignKey('LegalRight', related_name="collections", 209 legal_rights = WeakForeignKey('LegalRight', related_name="collections", 210 210 verbose_name=_('legal rights')) 211 211 212 212 # Archiving data 213 acquisition_mode = WeakForeignKey('AcquisitionMode', related_name="collections", 213 acquisition_mode = WeakForeignKey('AcquisitionMode', related_name="collections", 214 214 verbose_name=_('mode of acquisition')) 215 215 cnrs_contributor = CharField(_('CNRS depositor')) 216 metadata_author = WeakForeignKey('MetadataAuthor', related_name="collections", 216 metadata_author = WeakForeignKey('MetadataAuthor', related_name="collections", 217 217 verbose_name=_('record author')) 218 218 booklet_description = TextField(_('related documentation')) 219 publishing_status = WeakForeignKey('PublishingStatus', related_name="collections", 219 publishing_status = WeakForeignKey('PublishingStatus', related_name="collections", 220 220 verbose_name=_('secondary edition')) 221 221 alt_ids = CharField(_('copies')) 222 222 comment = TextField(_('comment')) 223 metadata_writer = WeakForeignKey('MetadataWriter', related_name="collections", 223 metadata_writer = WeakForeignKey('MetadataWriter', related_name="collections", 224 224 verbose_name=_('record writer')) 225 225 travail = CharField(_('archiver notes')) … … 228 228 is_published = BooleanField(_('published')) 229 229 conservation_site = CharField(_('conservation site')) 230 230 231 231 # Technical data 232 232 code = CharField(_('code'), unique=True, required=True, validators=[is_valid_collection_code]) … … 234 234 approx_duration = DurationField(_('approximative duration')) 235 235 physical_items_num = IntegerField(_('number of components (medium / piece)')) 236 physical_format = WeakForeignKey('PhysicalFormat', related_name="collections", 236 physical_format = WeakForeignKey('PhysicalFormat', related_name="collections", 237 237 verbose_name=_('archive format')) 238 ad_conversion = WeakForeignKey('AdConversion', related_name='collections', 238 ad_conversion = WeakForeignKey('AdConversion', related_name='collections', 239 239 verbose_name=_('digitization')) 240 240 state = TextField(_('status')) 241 241 a_informer_07_03 = CharField(_('a_informer_07_03')) 242 242 243 243 # All 244 244 objects = MediaCollectionManager() 245 245 246 246 def __unicode__(self): 247 247 return self.code … … 250 250 def public_id(self): 251 251 return self.code 252 252 253 253 @property 254 254 def has_mediafile(self): … … 259 259 return True 260 260 return False 261 261 262 262 def __name_cmp(self, obj1, obj2): 263 263 return unaccent_icmp(obj1.name, obj2.name) … … 270 270 if not country in countries: 271 271 countries.append(country) 272 273 countries.sort(self.__name_cmp) 272 273 countries.sort(self.__name_cmp) 274 274 275 275 return countries … … 285 285 286 286 cmp = lambda a, b: unaccent_icmp(a.value, b.value) 287 groups.sort(cmp) 287 groups.sort(cmp) 288 288 289 289 return groups … … 295 295 duration += item.computed_duration() 296 296 return duration 297 298 computed_duration.verbose_name = _('computed duration') 299 297 298 computed_duration.verbose_name = _('computed duration') 299 300 300 def save(self, force_insert=False, force_update=False, user=None, code=None): 301 301 super(MediaCollection, self).save(force_insert, force_update) 302 302 303 303 class Meta(MetaCore): 304 304 db_table = 'media_collections' … … 308 308 class MediaCollectionRelated(MediaRelated): 309 309 "Collection related media" 310 310 311 311 collection = ForeignKey('MediaCollection', related_name="related", verbose_name=_('collection')) 312 312 313 313 class Meta(MetaCore): 314 314 db_table = 'media_collection_related' 315 315 316 316 317 317 class MediaItem(MediaResource): 318 318 "Describe an item" 319 319 320 320 element_type = 'item' 321 321 322 322 # Main Informations 323 323 title = CharField(_('title')) 324 324 alt_title = CharField(_('original title / translation')) 325 325 collector = CharField(_('recordist')) 326 collection = ForeignKey('MediaCollection', related_name="items", 327 verbose_name=_('collection')) 326 collection = ForeignKey('MediaCollection', related_name="items", 327 verbose_name=_('collection')) 328 328 recorded_from_date = DateField(_('recording date (from)')) 329 329 recorded_to_date = DateField(_('recording date (until)')) 330 330 331 331 # Geographic and cultural informations 332 332 location = WeakForeignKey('Location', verbose_name=_('location')) 333 333 location_comment = CharField(_('location details')) 334 334 cultural_area = CharField(_('cultural area')) 335 ethnic_group = WeakForeignKey('EthnicGroup', related_name="items", 335 ethnic_group = WeakForeignKey('EthnicGroup', related_name="items", 336 336 verbose_name=_('population / social group')) 337 337 language = CharField(_('language')) 338 338 context_comment = TextField(_('comments / ethnographic context')) 339 339 moda_execut = CharField(_('moda_execut')) 340 340 341 341 # Musical informations 342 vernacular_style = WeakForeignKey('VernacularStyle', related_name="items", 342 vernacular_style = WeakForeignKey('VernacularStyle', related_name="items", 343 343 verbose_name=_('vernacular style')) 344 generic_style = WeakForeignKey('GenericStyle', related_name="items", 344 generic_style = WeakForeignKey('GenericStyle', related_name="items", 345 345 verbose_name=_('generic style')) 346 346 author = CharField(_('author / compositor')) 347 347 348 348 # General informations 349 349 comment = TextField(_('remarks')) 350 350 collector_selection = CharField(_('recordist selection')) 351 351 collector_from_collection = BooleanField(_('recordist as in collection')) 352 352 353 353 # Archiving data 354 354 code = CharField(_('code'), unique=True, blank=True) … … 360 360 public_access = CharField(_('public access'), choices=PUBLIC_ACCESS_CHOICES, max_length=16, default="metadata") 361 361 file = FileField(_('file'), upload_to='items/%Y/%m/%d', db_column="filename") 362 362 363 363 # Technical data 364 364 approx_duration = DurationField(_('approximative duration')) 365 365 366 366 # All 367 367 objects = MediaItemManager() … … 379 379 class Meta(MetaCore): 380 380 db_table = 'media_items' 381 permissions = (("can_play_all_items", "Can play all media items"), 381 permissions = (("can_play_all_items", "Can play all media items"), 382 382 ("can_download_all_items", "Can download all media items"), ) 383 383 … … 396 396 def clean(self): 397 397 if self.code and not self.is_valid_code(self.code): 398 raise ValidationError("%s is not a valid item code for collection %s" 398 raise ValidationError("%s is not a valid item code for collection %s" 399 399 % (self.code, self.collection.code)) 400 400 401 401 def save(self, force_insert=False, force_update=False): 402 402 super(MediaItem, self).save(force_insert, force_update) … … 406 406 return self.approx_duration 407 407 408 computed_duration.verbose_name = _('computed duration') 408 computed_duration.verbose_name = _('computed duration') 409 409 410 410 def __unicode__(self): … … 420 420 class MediaItemRelated(MediaRelated): 421 421 "Item related media" 422 422 423 423 item = ForeignKey('MediaItem', related_name="related", verbose_name=_('item')) 424 424 425 425 class Meta(MetaCore): 426 426 db_table = 'media_item_related' … … 439 439 class MediaItemPerformance(ModelCore): 440 440 "Item performance" 441 media_item = ForeignKey('MediaItem', related_name="performances", 441 media_item = ForeignKey('MediaItem', related_name="performances", 442 442 verbose_name=_('item')) 443 instrument = WeakForeignKey('Instrument', related_name="performances", 443 instrument = WeakForeignKey('Instrument', related_name="performances", 444 444 verbose_name=_('composition')) 445 alias = WeakForeignKey('InstrumentAlias', related_name="performances", 445 alias = WeakForeignKey('InstrumentAlias', related_name="performances", 446 446 verbose_name=_('vernacular name')) 447 447 instruments_num = CharField(_('number')) … … 455 455 "Item analysis result computed by TimeSide" 456 456 457 element_type = 'analysis' 457 element_type = 'analysis' 458 458 item = ForeignKey('MediaItem', related_name="analysis", verbose_name=_('item')) 459 459 analyzer_id = CharField(_('id'), required=True) … … 461 461 value = CharField(_('value')) 462 462 unit = CharField(_('unit')) 463 463 464 464 class Meta(MetaCore): 465 465 db_table = 'media_analysis' 466 466 ordering = ['name'] 467 467 468 468 def to_dict(self): 469 469 if self.analyzer_id == 'duration': … … 472 472 self.value = '.'.join([value[0], value[1][:2]]) 473 473 return {'id': self.analyzer_id, 'name': self.name, 'value': self.value, 'unit': self.unit} 474 475 474 475 476 476 class MediaPart(MediaResource): 477 477 "Describe an item part" … … 481 481 start = FloatField(_('start'), required=True) 482 482 end = FloatField(_('end'), required=True) 483 483 484 484 class Meta(MetaCore): 485 485 db_table = 'media_parts' … … 501 501 def __unicode__(self): 502 502 return self.title 503 503 504 504 505 505 class PlaylistResource(ModelCore): … … 514 514 class Meta(MetaCore): 515 515 db_table = 'playlist_resources' 516 517 516 517 518 518 class MediaItemMarker(MediaResource): 519 519 "2D marker object : text value vs. time" 520 520 521 521 element_type = 'marker' 522 522 523 523 item = ForeignKey('MediaItem', related_name="markers", verbose_name=_('item')) 524 524 public_id = CharField(_('public_id'), required=True) … … 528 528 description = TextField(_('description')) 529 529 author = ForeignKey(User, related_name="markers", verbose_name=_('author')) 530 530 531 531 class Meta(MetaCore): 532 532 db_table = 'media_markers' … … 541 541 class MediaItemTranscodingFlag(ModelCore): 542 542 "Item flag to know if the MediaItem has been transcoded to a given format" 543 543 544 544 item = ForeignKey('MediaItem', related_name="transcoding", verbose_name=_('item')) 545 545 mime_type = CharField(_('mime_type'), required=True) 546 546 date = DateTimeField(_('date'), auto_now=True) 547 547 value = BooleanField(_('transcoded')) 548 548 549 549 class Meta(MetaCore): 550 550 db_table = 'media_transcoding' 551 552 551 552 553 553 class Search(ModelCore): 554 554 "Keywork search" 555 555 556 556 element_type = 'search' 557 557 558 558 username = ForeignKey(User, related_name="searches", db_column="username") 559 559 keywords = CharField(_('keywords'), required=True) … … 568 568 569 569 class DublinCoreToFormatMetadata(object): 570 """ a mapping class to get item DublinCore metadata dictionaries 570 """ a mapping class to get item DublinCore metadata dictionaries 571 571 in various audio metadata format (MP3, OGG, etc...)""" 572 572 573 573 #FIXME: should be given by timeside 574 unavailable_extensions = ['wav', 'aiff', 'aif' ]575 576 metadata_mapping = { 574 unavailable_extensions = ['wav', 'aiff', 'aif', 'flac'] 575 576 metadata_mapping = { 577 577 'mp3' : { 578 578 'title': 'TIT2', #title2 … … 585 585 'date': 'TDRC', #year 586 586 # 'coverage': 'COMM', #comment 587 }, 587 }, 588 588 'ogg': { 589 589 'creator': 'artist', 590 'relation': 'album', 591 'all': 'all', 592 }, 590 'relation': 'album', 591 'all': 'all', 592 }, 593 593 'flac': { 594 594 'creator': 'artist', 595 'relation': 'album', 596 'all': 'all', 597 }, 595 'relation': 'album', 596 'all': 'all', 597 }, 598 598 'wav': { 599 599 'creator': 'artist', 600 'relation': 'album', 601 'all': 'all', 602 }, 600 'relation': 'album', 601 'all': 'all', 602 }, 603 603 } 604 604 605 605 def __init__(self, format): 606 606 self.format = format 607 607 608 608 def get_metadata(self, dc_metadata): 609 609 mapp = self.metadata_mapping[self.format] -
telemeta/web/base.py
r40aa64b rd511f9f 83 83 mimetype=mimetype) 84 84 85 def stream_from_processor(__decoder, __processor, __flag ):85 def stream_from_processor(__decoder, __processor, __flag, metadata=None): 86 86 while True: 87 __frames, eodproc = __processor.process(*__decoder.process()) 88 if eodproc: 87 __frames, __eodproc = __processor.process(*__decoder.process()) 88 if __eodproc or not len(__frames): 89 if metadata: 90 __processor.set_metadata(metadata) 91 __processor.write_metadata() 89 92 __flag.value = True 90 93 __flag.save() … … 876 879 # source > stream 877 880 if not extension in mapping.unavailable_extensions: 878 try: 879 proc = encoder(audio) 880 proc.set_metadata(metadata) 881 proc.write_metadata() 882 except: 883 pass 881 proc = encoder(audio) 882 proc.set_metadata(metadata) 883 proc.write_metadata() 884 884 response = HttpResponse(stream_from_file(audio), mimetype = mime_type) 885 885 else: 886 886 media = self.cache_export.dir + os.sep + file 887 if not self.cache_export.exists(file) or flag.value == False:887 if not self.cache_export.exists(file) or not flag.value: 888 888 # source > encoder > stream 889 889 decoder = timeside.decoder.FileDecoder(audio) … … 891 891 proc = encoder(media, streaming=True) 892 892 proc.setup(channels=decoder.channels(), samplerate=decoder.samplerate()) 893 proc.set_metadata(metadata) 894 response = HttpResponse(stream_from_processor(decoder, proc, flag), mimetype = mime_type) 893 if extension in mapping.unavailable_extensions: 894 metadata=None 895 response = HttpResponse(stream_from_processor(decoder, proc, flag, metadata=metadata), mimetype = mime_type) 895 896 else: 896 897 # cache > stream 897 if not extension in mapping.unavailable_extensions:898 try:899 proc = encoder(media)900 proc.set_metadata(metadata)901 proc.write_metadata()902 except:903 pass904 898 response = HttpResponse(self.cache_export.read_stream_bin(file), mimetype = mime_type) 905 899
Note: See TracChangeset
for help on using the changeset viewer.
