Commit 30b9b95d authored by quicksketch's avatar quicksketch

#480754: filefield_meta: store audio metadata from getid3.

parent 6a189547
<?php
// $Id$
/**
* @file
* Token integration for FileField Meta.
*/
/**
* Implementation of hook_token_list().
*
* Provide a user readable list of FileField Meta tokens.
*/
function filefield_token_list($type = 'all') {
if ($type == 'field' || $type == 'all') {
$tokens['file']['filefield-width'] = t('File Video width');
$tokens['file']['filefield-height'] = t('File Video height');
$tokens['file']['filefield-duration'] = t('File Duration');
$tokens['file']['filefield-audio-format'] = t('File Audio Format path');
$tokens['file']['filefield-audio-sample-rate'] = t('File Audio sample rate');
$tokens['file']['filefield-audio-channel-mode'] = t('File Audio channel mode (stereo, mono)');
$tokens['file']['filefield-audio-bitrate'] = t('File Audio bitrate');
$tokens['file']['filefield-audio-bitrate-mode'] = t('File Audio bitrate mode (cbr, vbr, abr...)');
// ID3 tags.
foreach (filefield_meta_tags() as $tag => $label) {
$tokens['file']['filefield-tag-' . $tag] = t('File ID3 @tag tag', array('@tag' => $label));
}
return $tokens;
}
}
/**
* Implementation of hook_token_values().
*
* Provide the token values for a given file item.
*/
function filefield_token_values($type, $object = NULL) {
$tokens = array();
if ($type == 'field' && isset($object[0]['fid'])) {
$item = $object[0];
$tokens['filefield-width'] = $item['data']['width'] ;
$tokens['filefield-height'] = $item['data']['height'] ;
$tokens['filefield-duration'] = $item['data']['duration'] ;
$tokens['filefield-audio-format'] = isset($item['data']['audio_format']) ? check_plain($item['data']['audio_format']) : '';
$tokens['filefield-audio-sample-rate'] = isset($item['data']['sample_rate']) ? check_plain($item['data']['sample_rate']) : '';
$tokens['filefield-audio-channel-mode'] = isset($item['data']['audio_channel_mode']) ? check_plain($item['data']['audio_channel_mode']) : '';
$tokens['filefield-audio-bitrate'] = isset($item['data']['audio_bitrate']) ? check_plain($item['data']['audio_bitrate']) : '';
$tokens['filefield-audio-bitrate-mode'] = isset($item['data']['audio_bitrate_mode']) ? check_plain($item['data']['audio_bitrate_mode']) : '';
// ID3 tags.
foreach (filefield_meta_tags() as $tag => $label) {
$tokens['filefield-tag-title'] = isset($item['data']['tags'][$tag]) ? check_plain($item['data']['tags'][$tag]) : '';
}
}
return $tokens;
}
......@@ -84,6 +84,11 @@ function filefield_meta_schema() {
'not null' => TRUE,
'default' => '',
),
'tags' => array(
'description' => 'ID3 tags such as artist, album, and genre.',
'type' => 'text',
'serialize' => TRUE,
),
),
'primary key' => array('fid'),
);
......@@ -129,4 +134,36 @@ function filefield_meta_update_1() {
'default' => '',
));
return $ret;
}
\ No newline at end of file
}
/**
* Add the tags column.
*/
function filefield_meta_update_6100(&$context) {
$ret = array();
// Set up our update and add the tags column.
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['total'] = db_result(db_query("SELECT COUNT(*) FROM {files} f INNER JOIN {filefield_meta} fm ON f.fid = fm.fid WHERE fm.audio_format <> ''"));
$context['sandbox']['current_fid'] = 0;
db_add_field($ret, 'filefield_meta', 'tags', array('type' => 'text'));
}
// Select and process 200 files at a time.
$limit = 200;
$result = db_query_range("SELECT f.* FROM {files} f INNER JOIN {filefield_meta} fm ON f.fid = fm.fid WHERE f.fid > %d AND fm.audio_format <> '' ORDER BY f.fid ASC", $context['sandbox']['current_fid'], 0, $limit);
// Loop through each file and read in its ID3 tags if applicable.
while ($file = db_fetch_object($result)) {
filefield_meta_file_update($file);
$context['sandbox']['current_fid'] = $file->fid;
$context['sandbox']['progress']++;
}
// Update our progress indicator.
$ret['#finished'] = $context['sandbox']['progress'] / $context['sandbox']['total'];
return $ret;
}
......@@ -6,6 +6,16 @@
* FileField Meta: Add Video Support to File Field.
*/
/**
* Implementation of hook_init().
*/
function filefield_meta_init() {
// Conditional module support.
if (module_exists('token')) {
module_load_include('inc', 'filefield_meta', 'filefield_meta.token');
}
}
/**
* Implementation of hook_theme().
*/
......@@ -44,7 +54,24 @@ function filefield_meta_views_api() {
}
/**
* Implementation of filefield's hook_file_insert().
* Implementation of FileField's hook_file_load().
*/
function filefield_meta_file_load(&$file) {
$result = db_query("SELECT * FROM {filefield_meta} WHERE fid = %d", $file->fid);
$data = db_fetch_array($result);
// Essentially this is a lazy-loader. If no record exists, read in the file.
if ($data) {
$data['tags'] = isset($data['tags']) ? unserialize($data['tags']) : array();
$file->data = isset($file->data) ? array_merge($file->data, $data) : $data;
}
else {
filefield_meta_file_insert($file);
}
}
/**
* Implementation of FileField's hook_file_insert().
*/
function filefield_meta_file_insert(&$file) {
if (!empty($file->fid)) {
......@@ -55,7 +82,7 @@ function filefield_meta_file_insert(&$file) {
}
/**
* Implementation of filefield's hook_file_update().
* Implementation of FileField's hook_file_update().
*/
function filefield_meta_file_update(&$file) {
if (!empty($file->fid)) {
......@@ -65,7 +92,7 @@ function filefield_meta_file_update(&$file) {
}
/**
* Implementation of filefield's hook_file_delete().
* Implementation of FileField's hook_file_delete().
*/
function filefield_meta_file_delete($file) {
db_query('DELETE FROM {filefield_meta} WHERE fid = %d', $file->fid);
......@@ -77,6 +104,7 @@ function filefield_meta_file_delete($file) {
function filefield_meta(&$file) {
$info = getid3_analyze($file->filepath);
$file->data = isset($file->data) ? $file->data : array();
$file->data['width'] = $file->data['height'] = $file->data['duration'] = 0;
if (isset($info['video']['resolution_x'])) {
$file->data['width'] = $info['video']['resolution_x'];
......@@ -93,7 +121,7 @@ function filefield_meta(&$file) {
$file->data['duration'] = $info['playtime_seconds'];
}
// initialize fields.
// Initialize fields.
$file->data['audio_format'] = $file->data['audio_channel_mode'] = $file->data['audio_bitrate_mode'] = '';
$file->data['audio_sample_rate'] = $file->data['audio_bitrate'] = 0;
......@@ -104,7 +132,48 @@ function filefield_meta(&$file) {
$file->data['audio_bitrate'] = isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : NULL; //e.g. 64000
$file->data['audio_bitrate_mode'] = isset($info['audio']['bitrate_mode']) ? $info['audio']['bitrate_mode'] : NULL; //e.g. cbr
}
};
// Add in arbitrary ID3 tags.
if (isset($info['tags_html'])) {
// We use tags_html instead of tags because it is the most reliable data
// source for pulling in non-UTF-8 characters according to getID3 docs.
foreach ($info['tags_html'] as $type => $values) {
// Typically $type may be IDv2 (for MP3s) or quicktime (for AAC).
foreach ($values as $key => $value) {
$value = isset($value[0]) ? (string) $value[0] : (string) $value;
if (!empty($value) && $key != 'coverart') {
$file->data['tags'][$key] = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
}
}
}
}
}
/**
* Utility function that simply returns the current list of all known ID3 tags.
*
* If new or different ID3 tags are desired, these may be overridden by adding
* the following to your site's settings.php file.
*
* @code
* $conf['filefield_meta_tags'] = array(
* 'title' => t('Title'),
* 'artist' => t('Artist'),
* 'composer' => t('Composer'),
* // etc...
* );
* @endcode
*/
function filefield_meta_tags() {
$defaults = array(
'title' => t('Title'),
'artist' => t('Artist'),
'album' => t('Album'),
'year' => t('Year'),
'genre' => t('Genre'),
);
return variable_get('filefield_meta_tags', $defaults);
}
/**
* Convert the float duration into a pretty string.
......
......@@ -162,6 +162,16 @@ function filefield_meta_views_data() {
),
);
// Tags.
$data['filefield_meta']['tags'] = array(
'title' => t('ID3 tags'),
'help' => t('ID3 tags include embedded information such as artist, album, year, genre and other informaiton.'),
'field' => array(
'handler' => 'filefield_meta_handler_field_tags',
'click sortable' => FALSE,
),
);
return $data;
}
......@@ -184,6 +194,9 @@ function filefield_meta_views_handlers() {
'filefield_meta_handler_field_samplerate' => array(
'parent' => 'views_handler_field_numeric',
),
'filefield_meta_handler_field_tags' => array(
'parent' => 'views_handler_field_prerender_list',
),
),
);
}
......
<?php
// $Id$
/**
* @file
* A special handler that renders ID3 tags attached to a file.
*/
/**
* Render a field as a readable value in hours, minutes, and seconds.
*
* @ingroup views_field_handlers
*/
class filefield_meta_handler_field_tags extends views_handler_field {
function option_definition() {
$options = parent::option_definition();
$default = reset(array_keys(filefield_meta_tags()));
$options['tag'] = array('tag' => $default, 'required' => TRUE, 'translatable' => TRUE);
return $options;
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['relationship']['#weight'] = -2;
$form['tag'] = array(
'#type' => 'select',
'#title' => t('ID3 tag'),
'#required' => TRUE,
'#default_value' => $this->options['tag'],
'#options' => filefield_meta_tags(),
'#description' => t('Select the tag to be rendered. If needing multiple tags, add another ID3 tags field.'),
'#weight' => -1,
);
}
function render($values) {
$value = unserialize($values->{$this->field_alias});
$tag = $this->options['tag'];
if (isset($value[$tag])) {
return check_plain($value[$tag]);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment