gh-61 Add support for audio (m4a) files and accompanying tests

This commit is contained in:
Jaisen Mathai 2016-01-03 22:10:56 -08:00
parent 64695fea08
commit 58f0fadc07
6 changed files with 206 additions and 5 deletions

View File

@ -10,6 +10,7 @@ from docopt import docopt
from elodie import constants from elodie import constants
from elodie import geolocation from elodie import geolocation
from elodie.media.media import Media from elodie.media.media import Media
from elodie.media.audio import Audio
from elodie.media.photo import Photo from elodie.media.photo import Photo
from elodie.media.video import Video from elodie.media.video import Video
from elodie.filesystem import FileSystem from elodie.filesystem import FileSystem
@ -34,7 +35,7 @@ FILESYSTEM = FileSystem()
def import_file(_file, destination, album_from_folder): def import_file(_file, destination, album_from_folder):
"""Set file metadata and move it to destination. """Set file metadata and move it to destination.
""" """
media = Media.get_class_by_file(_file, (Photo, Video)) media = Media.get_class_by_file(_file, [Audio, Photo, Video])
if not media: if not media:
if constants.debug: if constants.debug:
print 'Not a supported file (%s)' % _file print 'Not a supported file (%s)' % _file
@ -119,7 +120,7 @@ def _update(params):
destination = os.path.expanduser(os.path.dirname(os.path.dirname( destination = os.path.expanduser(os.path.dirname(os.path.dirname(
os.path.dirname(file_path)))) os.path.dirname(file_path))))
media = Media.get_class_by_file(file_path, (Photo, Video)) media = Media.get_class_by_file(file_path, [Audio, Photo, Video])
if not media: if not media:
continue continue
@ -155,7 +156,7 @@ def _update(params):
updated = True updated = True
if updated: if updated:
updated_media = Media.get_class_by_file(file_path, (Photo, Video)) updated_media = Media.get_class_by_file(file_path, [Audio, Photo, Video])
# See comments above on why we have to do this when titles # See comments above on why we have to do this when titles
# get updated. # get updated.
if remove_old_title_from_name and len(original_title) > 0: if remove_old_title_from_name and len(original_title) > 0:

View File

@ -92,7 +92,8 @@ def decimal_to_dms(decimal, signed=True):
return ( return (
pyexiv2.Rational(degrees, 1), pyexiv2.Rational(degrees, 1),
pyexiv2.Rational(minutes, 1), pyexiv2.Rational(minutes, 1),
pyexiv2.Rational(subseconds_fraction.numerator, subseconds_fraction.denominator) # noqa pyexiv2.Rational(subseconds_fraction.numerator,
subseconds_fraction.denominator)
) )

21
elodie/media/audio.py Normal file
View File

@ -0,0 +1,21 @@
"""
Author: Jaisen Mathai <jaisen@jmathai.com>
Audio package that handles all audio operations
Inherits from Video package
"""
from elodie import constants
from elodie import plist_parser
from media import Media
from video import Video
class Audio(Video):
__name__ = 'Audio'
extensions = ('m4a')
"""
@param, source, string, The fully qualified path to the audio file
"""
def __init__(self, source=None):
super(Audio, self).__init__(source)

View File

@ -27,6 +27,7 @@ class Video(Media):
""" """
@param, source, string, The fully qualified path to the video file @param, source, string, The fully qualified path to the video file
@param, Audio, class or none, The Audio class if being extendted by the Audio class
""" """
def __init__(self, source=None): def __init__(self, source=None):
super(Video, self).__init__(source) super(Video, self).__init__(source)
@ -375,7 +376,7 @@ class Video(Media):
# Before we do anything destructive we confirm that the # Before we do anything destructive we confirm that the
# file is in tact. # file is in tact.
check_media = Video(temp_movie) check_media = Media.get_class_by_file(temp_movie, [self.__class__])
check_metadata = check_media.get_metadata() check_metadata = check_media.get_metadata()
if( if(
( (

Binary file not shown.

View File

@ -0,0 +1,177 @@
# -*- coding: utf-8
# Project imports
import os
import sys
import shutil
import tempfile
import time
import datetime
from nose.plugins.skip import SkipTest
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))))
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
import helper
from elodie.media.media import Media
from elodie.media.video import Video
from elodie.media.audio import Audio
os.environ['TZ'] = 'GMT'
def test_audio_extensions():
audio = Audio()
extensions = audio.extensions
assert 'm4a' in extensions
valid_extensions = Audio.get_valid_extensions()
assert extensions == valid_extensions, valid_extensions
def test_get_coordinate():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_coordinate()
assert coordinate == 29.75893888888889, coordinate
def test_get_coordinate_latitude():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_coordinate('latitude')
assert coordinate == 29.75893888888889, coordinate
def test_get_coordinate_longitude():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_coordinate('longitude')
assert coordinate == -95.3677, coordinate
def test_get_date_taken():
raise SkipTest('gh-32 this test fails on travisci')
audio = Audio(helper.get_file('audio.m4a'))
date_taken = audio.get_date_taken()
print '%r' % date_taken
assert date_taken == (2016, 1, 4, 5, 24, 15, 0, 19, 0), date_taken
def test_get_exif():
audio = Audio(helper.get_file('audio.m4a'))
exif = audio.get_exif()
assert exif is not None, exif
def test_is_valid():
audio = Audio(helper.get_file('audio.m4a'))
assert audio.is_valid()
def test_is_not_valid():
audio = Audio(helper.get_file('text.txt'))
assert not audio.is_valid()
def test_set_date_taken():
if not can_edit_exif():
raise SkipTest('avmetareadwrite executable not found')
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
status = audio.set_date_taken(datetime.datetime(2013, 9, 30, 7, 6, 5))
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata()
date_taken = metadata['date_taken']
shutil.rmtree(folder)
assert date_taken == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_taken']
def test_set_location():
if not can_edit_exif():
raise SkipTest('avmetareadwrite executable not found')
raise SkipTest('gh-31, precision is lost in conversion from decimal to dms')
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
origin_metadata = audio.get_metadata()
# Verify that original photo has no location information
#assert origin_metadata['latitude'] is None, origin_metadata['latitude']
#assert origin_metadata['longitude'] is None, origin_metadata['longitude']
status = audio.set_location(11.1111111111, 99.9999999999)
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata()
shutil.rmtree(folder)
# @TODO: understand why the decimal to degree conversion loses accuracy
assert metadata['latitude'] == 11.1111111111, metadata['latitude']
assert metadata['longitude'] == 99.9999999999, metadata['longitude']
def test_set_title():
if not can_edit_exif():
raise SkipTest('avmetareadwrite executable not found')
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
origin_metadata = audio.get_metadata()
status = audio.set_title('my audio title')
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata()
shutil.rmtree(folder)
assert metadata['title'] == 'my audio title', metadata['title']
def test_set_title_non_ascii():
if not can_edit_exif():
raise SkipTest('avmetareadwrite executable not found')
raise SkipTest('gh-27, non-ascii characters')
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
origin_metadata = audio.get_metadata()
status = audio.set_title('形声字 / 形聲字')
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata()
shutil.rmtree(folder)
assert metadata['title'] == '形声字 / 形聲字', metadata['title']
def can_edit_exif():
audio = Audio()
return audio.get_avmetareadwrite()