summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Haug2010-06-16 22:06:44 (GMT)
committerNathan Haug2010-06-16 22:06:44 (GMT)
commit30b9b95ded356d4593f91bc10be32427cba17767 (patch)
treed246855ad6111815cd862d872ea04bfb619cd9b1
parent6a18954727a90c32ab69a597b74393fd7ce9c760 (diff)
#480754: filefield_meta: store audio metadata from getid3.
-rw-r--r--filefield_meta/fielfield_meta.token.inc60
-rw-r--r--filefield_meta/filefield_meta.install39
-rw-r--r--filefield_meta/filefield_meta.module79
-rw-r--r--filefield_meta/includes/filefield_meta.views.inc13
-rw-r--r--filefield_meta/includes/filefield_meta_handler_field_tags.inc44
5 files changed, 229 insertions, 6 deletions
diff --git a/filefield_meta/fielfield_meta.token.inc b/filefield_meta/fielfield_meta.token.inc
new file mode 100644
index 0000000..22cdd58
--- /dev/null
+++ b/filefield_meta/fielfield_meta.token.inc
@@ -0,0 +1,60 @@
+<?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;
+}
diff --git a/filefield_meta/filefield_meta.install b/filefield_meta/filefield_meta.install
index 9af7760..fea9489 100644
--- a/filefield_meta/filefield_meta.install
+++ b/filefield_meta/filefield_meta.install
@@ -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;
+}
diff --git a/filefield_meta/filefield_meta.module b/filefield_meta/filefield_meta.module
index 2b86793..49c9ac9 100644
--- a/filefield_meta/filefield_meta.module
+++ b/filefield_meta/filefield_meta.module
@@ -7,6 +7,16 @@
*/
/**
+ * 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().
*/
function filefield_meta_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.
diff --git a/filefield_meta/includes/filefield_meta.views.inc b/filefield_meta/includes/filefield_meta.views.inc
index 9c32bf7..5eade13 100644
--- a/filefield_meta/includes/filefield_meta.views.inc
+++ b/filefield_meta/includes/filefield_meta.views.inc
@@ -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',
+ ),
),
);
}
diff --git a/filefield_meta/includes/filefield_meta_handler_field_tags.inc b/filefield_meta/includes/filefield_meta_handler_field_tags.inc
new file mode 100644
index 0000000..5d0c342
--- /dev/null
+++ b/filefield_meta/includes/filefield_meta_handler_field_tags.inc
@@ -0,0 +1,44 @@
+<?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]);
+ }
+ }
+}