CC-1799 : Live Studio Playout from media library (pytagsfs)

metadata almost working from airtime form -> python daemon. Just need to look into permissions for some stor folders.
This commit is contained in:
naomiaro 2011-05-05 10:55:14 -04:00 committed by martin
parent 5be039d349
commit a3d7c5e70b
5 changed files with 144 additions and 11 deletions

View File

@ -168,6 +168,10 @@ class LibraryController extends Zend_Controller_Action
$formdata = $form->getValues();
$file->replaceDbMetadata($formdata);
$data = $formdata;
$data['filepath'] = $file->getRealFilePath();
RabbitMq::SendFileMetaData($data);
$this->_helper->redirector('index');
}
}

View File

@ -2,6 +2,24 @@
class Application_Form_EditAudioMD extends Zend_Form
{
/*
"title": "track_title",\
"artist": "artist_name",\
"album": "album_title",\
"genre": "genre",\
"mood": "mood",\
"tracknumber": "track_number",\
"bpm": "bpm",\
"organization": "label",\
"composer": "composer",\
"encodedby": "encoded_by",\
"conductor": "conductor",\
"date": "year",\
"website": "info_url",\
"isrc": "isrc_number",\
"copyright": "copyright",\
*/
public function init()
{
@ -37,6 +55,13 @@ class Application_Form_EditAudioMD extends Zend_Form
'filters' => array('StringTrim')
));
// Add mood field
$this->addElement('text', 'track_number', array(
'label' => 'Track:',
'class' => 'input_text',
'filters' => array('StringTrim')
));
// Add genre field
$this->addElement('text', 'genre', array(
'label' => 'Genre:',
@ -77,9 +102,30 @@ class Application_Form_EditAudioMD extends Zend_Form
'filters' => array('StringTrim')
));
// Add language field
$this->addElement('text', 'language', array(
'label' => 'Language:',
// Add mood field
$this->addElement('text', 'bpm', array(
'label' => 'BPM:',
'class' => 'input_text',
'filters' => array('StringTrim')
));
// Add mood field
$this->addElement('text', 'copyright', array(
'label' => 'Copyright:',
'class' => 'input_text',
'filters' => array('StringTrim')
));
// Add mood field
$this->addElement('text', 'isrc_number', array(
'label' => 'ISRC Number:',
'class' => 'input_text',
'filters' => array('StringTrim')
));
// Add mood field
$this->addElement('text', 'info_url', array(
'label' => 'Website:',
'class' => 'input_text',
'filters' => array('StringTrim')
));

View File

@ -40,5 +40,27 @@ class RabbitMq
}
}
public static function SendFileMetaData($md)
{
global $CC_CONFIG;
$conn = new AMQPConnection($CC_CONFIG["rabbitmq"]["host"],
$CC_CONFIG["rabbitmq"]["port"],
$CC_CONFIG["rabbitmq"]["user"],
$CC_CONFIG["rabbitmq"]["password"]);
$channel = $conn->channel();
$channel->access_request($CC_CONFIG["rabbitmq"]["vhost"], false, false, true, true);
$EXCHANGE = 'airtime-media-monitor';
$channel->exchange_declare($EXCHANGE, 'direct', false, true);
$data = json_encode($md);
$msg = new AMQPMessage($data, array('content_type' => 'text/plain'));
$channel->basic_publish($msg, $EXCHANGE);
$channel->close();
$conn->close();
}
}

View File

@ -21,3 +21,10 @@ version_url = 'version/api_key/%%api_key%%'
# URL to tell Airtime to update file's meta data
update_media_url = 'reload-metadata/format/json/api_key/%%api_key%%'
############################################
# RabbitMQ settings #
############################################
rabbitmq_host = 'localhost'
rabbitmq_user = 'guest'
rabbitmq_password = 'guest'

View File

@ -7,16 +7,19 @@ import datetime
import os
import sys
import hashlib
import json
from subprocess import Popen, PIPE, STDOUT
from configobj import ConfigObj
import mutagen
import pyinotify
from pyinotify import WatchManager, Notifier, ProcessEvent
import mutagen
# For RabbitMQ
from kombu.connection import BrokerConnection
from kombu.messaging import Exchange, Queue, Consumer, Producer
from api_clients import api_client
# configure logging
@ -38,6 +41,59 @@ list of supported easy tags in mutagen version 1.20
['albumartistsort', 'musicbrainz_albumstatus', 'lyricist', 'releasecountry', 'date', 'performer', 'musicbrainz_albumartistid', 'composer', 'encodedby', 'tracknumber', 'musicbrainz_albumid', 'album', 'asin', 'musicbrainz_artistid', 'mood', 'copyright', 'author', 'media', 'length', 'version', 'artistsort', 'titlesort', 'discsubtitle', 'website', 'musicip_fingerprint', 'conductor', 'compilation', 'barcode', 'performer:*', 'composersort', 'musicbrainz_discid', 'musicbrainz_albumtype', 'genre', 'isrc', 'discnumber', 'musicbrainz_trmid', 'replaygain_*_gain', 'musicip_puid', 'artist', 'title', 'bpm', 'musicbrainz_trackid', 'arranger', 'albumsort', 'replaygain_*_peak', 'organization']
"""
def checkRabbitMQ(notifier):
try:
notifier.connection.drain_events(timeout=5)
except Exception, e:
logger = logging.getLogger('root')
logger.info("%s", e)
class AirtimeNotifier(Notifier):
def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None):
Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, threshold, timeout)
self.airtime2mutagen = {\
"track_title": "title",\
"artist_name": "artist",\
"album_title": "album",\
"genre": "genre",\
"mood": "mood",\
"track_number": "tracknumber",\
"bpm": "bpm",\
"label": "organization",\
"composer": "composer",\
"encoded_by": "encodedby",\
"conductor": "conductor",\
"year": "date",\
"info_url": "website",\
"isrc_number": "isrc",\
"copyright": "copyright",\
}
schedule_exchange = Exchange("airtime-media-monitor", "direct", durable=True, auto_delete=True)
schedule_queue = Queue("media-monitor", exchange=schedule_exchange, key="filesystem")
self.connection = BrokerConnection(config["rabbitmq_host"], config["rabbitmq_user"], config["rabbitmq_password"], "/")
channel = self.connection.channel()
consumer = Consumer(channel, schedule_queue)
consumer.register_callback(self.handle_message)
consumer.consume()
def handle_message(self, body, message):
# ACK the message to take it off the queue
message.ack()
logger = logging.getLogger('root')
logger.info("Received md from RabbitMQ: " + body)
m = json.loads(message.body)
airtime_file = mutagen.File(m['filepath'], easy=True)
del m['filepath']
for key in m.keys() :
airtime_file[self.airtime2mutagen[key]] = m[key]
airtime_file.save()
class MediaMonitor(ProcessEvent):
def my_init(self):
@ -69,7 +125,7 @@ class MediaMonitor(ProcessEvent):
def process_IN_CREATE(self, event):
if not event.dir :
#This is a newly imported file.
print "%s: %s%s" % (event.maskname, event.path, event.name)
print "%s: %s" % (event.maskname, event.pathname)
#event.path : /srv/airtime/stor/bd2
#event.name : bd2aa73b58d9c8abcced989621846e99.mp3
@ -98,12 +154,10 @@ class MediaMonitor(ProcessEvent):
print "%s: path: %s name: %s" % (event.maskname, event.path, event.name)
def process_default(self, event):
print "%s: %s%s" % (event.maskname, event.path, event.name)
print "%s: %s" % (event.maskname, event.pathname)
if __name__ == '__main__':
print 'Media Monitor'
try:
# watched events
mask = pyinotify.IN_CREATE | pyinotify.IN_MODIFY
@ -111,9 +165,9 @@ if __name__ == '__main__':
wm = WatchManager()
wdd = wm.add_watch('/srv/airtime/stor', mask, rec=True, auto_add=True)
notifier = Notifier(wm, MediaMonitor(), read_freq=10, timeout=1)
notifier = AirtimeNotifier(wm, MediaMonitor(), read_freq=10, timeout=1)
notifier.coalesce_events()
notifier.loop()
notifier.loop(callback=checkRabbitMQ)
except KeyboardInterrupt:
notifier.stop()