charles95

bsc-v2.py

Apr 29th, 2015
962
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2.  
  3. # this script can installed to the current user account by running the following commands:
  4.  
  5. # sudo apt-get install python-nautilus python-mutagen python-pyexiv2 python-kaa-metadata
  6. # mkdir ~/.local/share/nautilus-python/extensions/
  7. # cp bsc-v2.py ~/.local/share/nautilus-python/extensions/
  8. # chmod a+x ~/.local/share/nautilus-python/extensions/bsc-v2.py
  9.  
  10. # alternatively, you can be able to place the script in:
  11. # /usr/share/nautilus-python/extensions/
  12.  
  13. # change log:
  14. # geb666: original bsc.py, based on work by Giacomo Bordiga
  15. # jmdsdf: version 2 adds extra ID3 and EXIF tag support
  16. # jmdsdf: added better error handling for ID3 tags, added mp3 length support, distinguished
  17. #         between exif image size and true image size
  18. # SabreWolfy: set consistent hh:mm:ss format, fixed bug with no ID3 information
  19. #             throwing an unhandled exception
  20. # jmdsdf: fixed closing file handles with mpinfo (thanks gueba)
  21. # jmdsdf: fixed closing file handles when there's an exception (thanks Pitxyoki)
  22. # jmdsdf: added video parsing (work based on enbeto, thanks!)
  23. # jmdsdf: added FLAC audio parsing through kaa.metadata (thanks for the idea l-x-l)
  24. # jmdsdf: added trackno, added mkv file support (thanks ENigma885)
  25. # jmdsdf: added date/album for flac/video (thanks eldon.t)
  26. # jmdsdf: added wav file support thru pyexiv2
  27. # jmdsdf: added sample rate file support thru mutagen and kaa (thanks for the idea N'ko)
  28. # jmdsdf: fix with tracknumber for FLAC, thanks l-x-l
  29. # draxus: support for pdf files
  30. # arun (engineerarun@gmail.com): made changes to work with naulitus 3.x
  31. # Andrew@webupd8.org: get EXIF support to work with Nautilus 3
  32. # cehlgn added MP4 Audio support (mp4,m4a,Apple lossles)
  33. # added close file for exif
  34. # Charles Bos: change 'import Image' to 'from PIL import Image' to fix import error
  35.  
  36. import os
  37. import urllib
  38. #import nautilus
  39. from gi.repository import Nautilus, GObject, Gtk, GdkPixbuf
  40. # for id3 support
  41. from mutagen.easyid3 import EasyID3
  42. from mutagen.mp3 import MPEGInfo
  43. # for exif support
  44. import pyexiv2
  45. # for reading videos. for future improvement, this can also read mp3!
  46. import kaa.metadata
  47. # for reading image dimensions
  48. from PIL import Image
  49. # for reading pdf
  50. try:
  51.     from pyPdf import PdfFileReader
  52. except:
  53.     pass
  54. # for mp4 AUDIO handling (Including ALAC *.m4a Apple Lossless)
  55. try:
  56.     from mutagen.mp4 import MP4
  57.     import mutagen.easymp4
  58.     from mutagen.easymp4 import EasyMP4
  59. except:
  60.     pass
  61.  
  62.  
  63. class ColumnExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoProvider):
  64.     def __init__(self):
  65.         pass
  66.  
  67.     def get_columns(self):
  68.         return (
  69.             Nautilus.Column(name="NautilusPython::title_column",attribute="title",label="Title",description="Song title"),
  70.             Nautilus.Column(name="NautilusPython::album_column",attribute="album",label="Album",description="Album"),
  71.             Nautilus.Column(name="NautilusPython::artist_column",attribute="artist",label="Artist",description="Artist"),
  72.             Nautilus.Column(name="NautilusPython::tracknumber_column",attribute="tracknumber",label="Track",description="Track number"),
  73.             Nautilus.Column(name="NautilusPython::genre_column",attribute="genre",label="Genre",description="Genre"),
  74.             Nautilus.Column(name="NautilusPython::date_column",attribute="date",label="Date",description="Date"),
  75.             Nautilus.Column(name="NautilusPython::bitrate_column",attribute="bitrate",label="Bitrate",description="Audio Bitrate in kilo bits per second"),
  76.             Nautilus.Column(name="NautilusPython::samplerate_column",attribute="samplerate",label="Sample rate",description="Sample rate in Hz"),
  77.             Nautilus.Column(name="NautilusPython::length_column",attribute="length",label="Length",description="Length of audio"),
  78.             Nautilus.Column(name="NautilusPython::exif_datetime_original_column",attribute="exif_datetime_original",label="EXIF Dateshot ",description="Get the photo capture date from EXIF data"),
  79.             Nautilus.Column(name="NautilusPython::exif_software_column",attribute="exif_software",label="EXIF Software",description="EXIF - software used to save image"),
  80.             Nautilus.Column(name="NautilusPython::exif_flash_column",attribute="exif_flash",label="EXIF flash",description="EXIF - flash mode"),
  81.             Nautilus.Column(name="NautilusPython::exif_pixeldimensions_column",attribute="exif_pixeldimensions",label="EXIF Image Size",description="Image size - pixel dimensions as reported by EXIF data"),
  82.             Nautilus.Column(name="NautilusPython::pixeldimensions_column",attribute="pixeldimensions",label="Image Size",description="Image/video size - actual pixel dimensions"),
  83.             Nautilus.Column(name="NautilusPython::format_column",attribute="format",label="Format",description="Mpeg Audio Format"),
  84.             Nautilus.Column(name="NautilusPython::mp3version_column",attribute="version",label="Version",description="Version"),
  85.             Nautilus.Column(name="NautilusPython::composer_column",attribute="composer",label="Composer",description="Composer"),
  86.             Nautilus.Column(name="NautilusPython::liricist_column",attribute="liricist",label="Liricist",description="Liricist"),
  87. )
  88.  
  89.     def update_file_info(self, file):
  90.         # set defaults to blank
  91.         for x in EasyID3.valid_keys.keys():
  92.             file.add_string_attribute(x, '')
  93.         file.add_string_attribute('bitrate', '')
  94.         file.add_string_attribute('samplerate', '')
  95.         file.add_string_attribute('length', '')
  96.         file.add_string_attribute('exif_datetime_original', '')
  97.         file.add_string_attribute('exif_software', '')
  98.         file.add_string_attribute('exif_flash', '')
  99.         file.add_string_attribute('exif_pixeldimensions', '')
  100.         file.add_string_attribute('pixeldimensions', '')
  101.         file.add_string_attribute('format', '')
  102.  
  103.         if file.get_uri_scheme() != 'file':
  104.             return
  105.  
  106.         # strip file:// to get absolute path
  107.         filename = urllib.unquote(file.get_uri()[7:])
  108.        
  109.         # mp3 handling
  110.         if file.is_mime_type('audio/mpeg'):
  111.             # attempt to read ID3 tag
  112.             try:
  113.                 audio = EasyID3(filename)
  114.                 # sometimes the audio variable will not have one of these items defined, that's why
  115.                 # there is this long try / except attempt
  116.                 for x in EasyID3.valid_keys.keys():
  117.                     val = "[n/a]"
  118.                     if audio.has_key(x):
  119.                         val = audio[x][0]
  120.                         if x == "tracknumber": val = "%3s" % (val)
  121.                     file.add_string_attribute(x, val)
  122.             except:
  123.                 # [SabreWolfy] some files have no ID3 tag and will throw this exception:
  124.                 for x in EasyID3.valid_keys.keys():
  125.                     file.add_string_attribute(x, "[no ID3]")
  126.                
  127.             # try to read MP3 information (bitrate, length, samplerate)
  128.             try:
  129.                 mpfile = open (filename)
  130.                 mpinfo = MPEGInfo (mpfile)
  131.                 file.add_string_attribute('bitrate', str(mpinfo.bitrate/1000) + " Kbps")
  132.                 file.add_string_attribute('samplerate', str(mpinfo.sample_rate) + " Hz")
  133.                 # [SabreWolfy] added consistent formatting of times in format hh:mm:ss
  134.                 # [SabreWolfy[ to allow for correct column sorting by length
  135.                 mp3length = "%02i:%02i:%02i" % ((int(mpinfo.length/3600)), (int(mpinfo.length/60%60)), (int(mpinfo.length%60)))
  136.                
  137.                 try: mpgfmt = "MPEG%d Layer%d" % (mpinfo.version,mpinfo.layer)
  138.                 except:mpgfmt = "[n/a]"
  139.                
  140.                 mpfile.close()
  141.                 file.add_string_attribute('length', mp3length)
  142.                 file.add_string_attribute('format', mpgfmt)
  143.             except:
  144.                 file.add_string_attribute('bitrate', "[n/a]")
  145.                 file.add_string_attribute('length', "[n/a]")
  146.                 file.add_string_attribute('samplerate', "[n/a]")
  147.                 file.add_string_attribute('format', "[n/a]")
  148.                 try:
  149.                     mpfile.close()
  150.                 except: pass
  151.    
  152.         # image handling
  153.         if file.is_mime_type('image/jpeg') or file.is_mime_type('image/png') or file.is_mime_type('image/gif') or file.is_mime_type('image/bmp'):
  154.             # EXIF handling routines
  155.             try:
  156.                 metadata = pyexiv2.ImageMetadata(filename)
  157.                 metadata.read()
  158.                 exif_datetimeoriginal = metadata['Exif.Photo.DateTimeOriginal']
  159.                 exif_imagesoftware = metadata['Exif.Image.Software']
  160.                 exif_photoflash = metadata['Exif.Photo.Flash']
  161.                 exif_pixelydimension = metadata['Exif.Photo.PixelYDimension']
  162.                 exif_pixelxdimension = metadata['Exif.Photo.PixelXDimension']
  163.                 file.add_string_attribute('exif_datetime_original',str(exif_datetimeoriginal.raw_value))
  164.                 file.add_string_attribute('exif_software',str(exif_imagesoftware.raw_value))
  165.                 file.add_string_attribute('exif_flash',str(exif_photoflash.raw_value))
  166.                 file.add_string_attribute('exif_pixeldimensions',str(exif_pixelydimension.raw_value)+'x'+str(exif_pixelxdimension.raw_value))
  167.             except:
  168.                 # no exif data?
  169.                 file.add_string_attribute('exif_datetime_original',"")
  170.                 file.add_string_attribute('exif_software',"")
  171.                 file.add_string_attribute('exif_flash',"")
  172.                 file.add_string_attribute('exif_pixeldimensions',"")
  173.             # try read image info directly
  174.             try:
  175.                 im = Image.open(filename)
  176.                 file.add_string_attribute('pixeldimensions',str(im.size[0])+'x'+str(im.size[1]))
  177.                 try: im.close()
  178.                 except: pass
  179.             except:
  180.                 file.add_string_attribute('pixeldimensions',"[image read error]")
  181.  
  182.         # video/flac handling
  183.         if file.is_mime_type('video/x-msvideo') | file.is_mime_type('video/mpeg') | file.is_mime_type('video/x-ms-wmv') | file.is_mime_type('video/mp4') | file.is_mime_type('audio/x-flac') | file.is_mime_type('video/x-flv') | file.is_mime_type('video/x-matroska') | file.is_mime_type('audio/x-wav'):
  184.             try:
  185.                 info=kaa.metadata.parse(filename)
  186.                 try: file.add_string_attribute('length',"%02i:%02i:%02i" % ((int(info.length/3600)), (int(info.length/60%60)), (int(info.length%60))))
  187.                 except: file.add_string_attribute('length','[n/a]')
  188.                 try: file.add_string_attribute('pixeldimensions', str(info.video[0].width) + 'x'+ str(info.video[0].height))
  189.                 except: file.add_string_attribute('pixeldimensions','[n/a]')
  190.                 try: file.add_string_attribute('bitrate',str(round(info.audio[0].bitrate/1000)))
  191.                 except: file.add_string_attribute('bitrate','[n/a]')
  192.                 try: file.add_string_attribute('samplerate',str(int(info.audio[0].samplerate))+' Hz')
  193.                 except: file.add_string_attribute('samplerate','[n/a]')
  194.                 try: file.add_string_attribute('title', info.title)
  195.                 except: file.add_string_attribute('title', '[n/a]')
  196.                 try: file.add_string_attribute('artist', info.artist)
  197.                 except: file.add_string_attribute('artist', '[n/a]')
  198.                 try: file.add_string_attribute('genre', info.genre)
  199.                 except: file.add_string_attribute('genre', '[n/a]')
  200.                 try: file.add_string_attribute('tracknumber',info.trackno)
  201.                 except: file.add_string_attribute('tracknumber', '[n/a]')
  202.                 try: file.add_string_attribute('date',info.userdate)
  203.                 except: file.add_string_attribute('date', '[n/a]')                 
  204.                 try: file.add_string_attribute('album',info.album)
  205.                 except: file.add_string_attribute('album', '[n/a]')
  206.             except:
  207.                 file.add_string_attribute('length','error')
  208.                 file.add_string_attribute('pixeldimensions','error')
  209.                 file.add_string_attribute('bitrate','error')
  210.                 file.add_string_attribute('samplerate','error')
  211.                 file.add_string_attribute('title','error')
  212.                 file.add_string_attribute('artist','error')
  213.                 file.add_string_attribute('genre','error')
  214.                 file.add_string_attribute('track','error')
  215.                 file.add_string_attribute('date','error')
  216.                 file.add_string_attribute('album','error')
  217.        
  218.         # pdf handling
  219.         if file.is_mime_type('application/pdf'):
  220.             try:
  221.                 f = open(filename, "rb")
  222.                 pdf = PdfFileReader(f)
  223.                 try: file.add_string_attribute('title', pdf.getDocumentInfo().title)
  224.                 except: file.add_string_attribute('title', "[n/a]")
  225.                 try: file.add_string_attribute('artist', pdf.getDocumentInfo().author)
  226.                 except: file.add_string_attribute('artist', "[n/a]")
  227.                 f.close()
  228.             except:
  229.                 file.add_string_attribute('title', "[no info]")
  230.                 file.add_string_attribute('artist', "[no info]")
  231.  
  232.         # mp4 AUDIO handling (Including ALAC *.m4a Apple Lossless)
  233.         if file.is_mime_type('audio/mp4'):
  234.             # attempt to read MP4 tag
  235.             try:
  236.                 audio = EasyMP4(filename)
  237.                 # sometimes the audio variable will not have one of these items defined, that's why
  238.                 # there is this long try / except attempt
  239.                 try: file.add_string_attribute('title', "".join(audio["title"]))
  240.                 except: file.add_string_attribute('title', [n/a])
  241.                 try: file.add_string_attribute('album', "".join(audio["album"]))
  242.                 except: file.add_string_attribute('album', "[n/a]")
  243.                 try: file.add_string_attribute('artist', "".join(audio["artist"]))
  244.                 except: file.add_string_attribute('artist', "[n/a]")
  245.                 try: file.add_string_attribute('tracknumber', "".join(audio["tracknumber"]))
  246.                 except: file.add_string_attribute('tracknumber', "[n/a]")
  247.                 try: file.add_string_attribute('genre', "".join(audio["genre"]))
  248.                 except: file.add_string_attribute('genre', "[n/a]")
  249.                 try: file.add_string_attribute('date', "".join(audio["date"]))
  250.                 except: file.add_string_attribute('date', "[n/a]")
  251.             except:
  252.                 # some files have no MP4 tag and will throw this exception:
  253.                 file.add_string_attribute('title', "[no MP4 Tag]")
  254.                 file.add_string_attribute('album', "[no MP4 Tag]")
  255.                 file.add_string_attribute('artist', "[no MP4 Tag]")
  256.                 file.add_string_attribute('tracknumber', "[no MP4 Tag]")
  257.                 file.add_string_attribute('genre', "[no MP4 Tag]")
  258.                 file.add_string_attribute('date', "[no MP4 Tag]")
  259.  
  260.  
  261.         #try to read MP4 information (bitrate, length, samplerate)
  262.         try:
  263.             m4info=MP4(filename)
  264.             try: file.add_string_attribute('length', "%02i:%02i:%02i" % ((int(m4info.info.length/3600)), (int(m4info.info.length/60%60)), (int(m4info.info.length%60))))
  265.             except: file.add_string_attribute('length', "[n/a]")   
  266.             try: file.add_string_attribute('bitrate', str(m4info.info.bitrate))
  267.             except: file.add_string_attribute('bitrate', "[n/a]")
  268.             try: file.add_string_attribute('samplerate', str(m4info.info.sample_rate))
  269.             except: file.add_string_attribute('samplerate', "[n/a]")
  270.         except:
  271.             file.add_string_attribute('bitrate', "error")
  272.             file.add_string_attribute('length', "error")
  273.             file.add_string_attribute('samplerate', "error")
  274.                    
  275.         self.get_columns()
RAW Paste Data