Skip to content

Instantly share code, notes, and snippets.

@infirit
Created October 4, 2014 21:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save infirit/497d589c4dcf44ffe920 to your computer and use it in GitHub Desktop.
Save infirit/497d589c4dcf44ffe920 to your computer and use it in GitHub Desktop.
Caja colums for additinal metadate info on list-view
#!/usr/bin/python
# this script can installed to the current user account by running the following commands:
# sudo apt-get install python-caja python-mutagen GExiv2 python-kaa-metadata
# mkdir ~/.local/share/caja-python/extensions/
# cp bsc-v2.py ~/.local/share/caja-python/extensions/
# chmod a+x ~/.local/share/caja-python/extensions/bsc-v2.py
# alternatively, you can be able to place the script in:
# /usr/share/caja-python/extensions/
# change log:
# geb666: original bsc.py, based on work by Giacomo Bordiga
# jmdsdf: version 2 adds extra ID3 and EXIF tag support
# jmdsdf: added better error handling for ID3 tags, added mp3 length support, distinguished
# between exif image size and true image size
# SabreWolfy: set consistent hh:mm:ss format, fixed bug with no ID3 information
# throwing an unhandled exception
# jmdsdf: fixed closing file handles with mpinfo (thanks gueba)
# jmdsdf: fixed closing file handles when there's an exception (thanks Pitxyoki)
# jmdsdf: added video parsing (work based on enbeto, thanks!)
# jmdsdf: added FLAC audio parsing through kaa.metadata (thanks for the idea l-x-l)
# jmdsdf: added trackno, added mkv file support (thanks ENigma885)
# jmdsdf: added date/album for flac/video (thanks eldon.t)
# jmdsdf: added wav file support thru pyexiv2
# jmdsdf: added sample rate file support thru mutagen and kaa (thanks for the idea N'ko)
# jmdsdf: fix with tracknumber for FLAC, thanks l-x-l
# draxus: support for pdf files
# arun (engineerarun@gmail.com): made changes to work with naulitus 3.x
# Andrew@webupd8.org: get EXIF support to work with Caja 3
# Julien Blanc: fix bug caused by missing Exif.Image.Software key
import os
import urllib
#import caja
from gi.repository import Caja, GObject, Gtk, GdkPixbuf
# for id3 support
from mutagen.easyid3 import EasyID3
from mutagen.mp3 import MPEGInfo
# for exif support
from gi.repository import GExiv2 as Exif
# for reading videos. for future improvement, this can also read mp3!
import kaa.metadata
# for reading image dimensions
from PIL import Image
# for reading pdf
try:
from pyPdf import PdfFileReader
except:
pass
class ColumnExtension(GObject.GObject, Caja.ColumnProvider, Caja.InfoProvider):
def __init__(self):
pass
def get_columns(self):
return (
Caja.Column(name="CajaPython::title_column",attribute="title",label="Title",description="Song title"),
Caja.Column(name="CajaPython::album_column",attribute="album",label="Album",description="Album"),
Caja.Column(name="CajaPython::artist_column",attribute="artist",label="Artist",description="Artist"),
Caja.Column(name="CajaPython::tracknumber_column",attribute="tracknumber",label="Track",description="Track number"),
Caja.Column(name="CajaPython::genre_column",attribute="genre",label="Genre",description="Genre"),
Caja.Column(name="CajaPython::date_column",attribute="date",label="Date",description="Date"),
Caja.Column(name="CajaPython::bitrate_column",attribute="bitrate",label="Bitrate",description="Audio Bitrate in kilo bits per second"),
Caja.Column(name="CajaPython::samplerate_column",attribute="samplerate",label="Sample rate",description="Sample rate in Hz"),
Caja.Column(name="CajaPython::length_column",attribute="length",label="Length",description="Length of audio"),
Caja.Column(name="CajaPython::exif_datetime_original_column",attribute="exif_datetime_original",label="EXIF Dateshot ",description="Get the photo capture date from EXIF data"),
Caja.Column(name="CajaPython::exif_software_column",attribute="exif_software",label="EXIF Software",description="EXIF - software used to save image"),
Caja.Column(name="CajaPython::exif_flash_column",attribute="exif_flash",label="EXIF flash",description="EXIF - flash mode"),
Caja.Column(name="CajaPython::exif_pixeldimensions_column",attribute="exif_pixeldimensions",label="EXIF Image Size",description="Image size - pixel dimensions as reported by EXIF data"),
Caja.Column(name="CajaPython::pixeldimensions_column",attribute="pixeldimensions",label="Image Size",description="Image/video size - actual pixel dimensions"),
)
def update_file_info(self, file):
# set defaults to blank
file.add_string_attribute('title', '')
file.add_string_attribute('album', '')
file.add_string_attribute('artist', '')
file.add_string_attribute('tracknumber', '')
file.add_string_attribute('genre', '')
file.add_string_attribute('date', '')
file.add_string_attribute('bitrate', '')
file.add_string_attribute('samplerate', '')
file.add_string_attribute('length', '')
file.add_string_attribute('exif_datetime_original', '')
file.add_string_attribute('exif_software', '')
file.add_string_attribute('exif_flash', '')
file.add_string_attribute('exif_pixeldimensions', '')
file.add_string_attribute('pixeldimensions', '')
if file.get_uri_scheme() != 'file':
return
# strip file:// to get absolute path
filename = urllib.unquote(file.get_uri()[7:])
# mp3 handling
if file.is_mime_type('audio/mpeg'):
# attempt to read ID3 tag
try:
audio = EasyID3(filename)
# sometimes the audio variable will not have one of these items defined, that's why
# there is this long try / except attempt
try: file.add_string_attribute('title', audio["title"][0])
except: file.add_string_attribute('title', "[n/a]")
try: file.add_string_attribute('album', audio["album"][0])
except: file.add_string_attribute('album', "[n/a]")
try: file.add_string_attribute('artist', audio["artist"][0])
except: file.add_string_attribute('artist', "[n/a]")
try: file.add_string_attribute('tracknumber', audio["tracknumber"][0])
except: file.add_string_attribute('tracknumber', "[n/a]")
try: file.add_string_attribute('genre', audio["genre"][0])
except: file.add_string_attribute('genre', "[n/a]")
try: file.add_string_attribute('date', audio["date"][0])
except: file.add_string_attribute('date', "[n/a]")
except:
# [SabreWolfy] some files have no ID3 tag and will throw this exception:
file.add_string_attribute('title', "[no ID3]")
file.add_string_attribute('album', "[no ID3]")
file.add_string_attribute('artist', "[no ID3]")
file.add_string_attribute('tracknumber', "[no ID3]")
file.add_string_attribute('genre', "[no ID3]")
file.add_string_attribute('date', "[no ID3]")
# try to read MP3 information (bitrate, length, samplerate)
try:
mpfile = open (filename)
mpinfo = MPEGInfo (mpfile)
file.add_string_attribute('bitrate', str(mpinfo.bitrate/1000) + " Kbps")
file.add_string_attribute('samplerate', str(mpinfo.sample_rate) + " Hz")
# [SabreWolfy] added consistent formatting of times in format hh:mm:ss
# [SabreWolfy[ to allow for correct column sorting by length
mp3length = "%02i:%02i:%02i" % ((int(mpinfo.length/3600)), (int(mpinfo.length/60%60)), (int(mpinfo.length%60)))
mpfile.close()
file.add_string_attribute('length', mp3length)
except:
file.add_string_attribute('bitrate', "[n/a]")
file.add_string_attribute('length', "[n/a]")
file.add_string_attribute('samplerate', "[n/a]")
try:
mpfile.close()
except: pass
# image handling
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'):
# EXIF handling routines
try:
metadata = GExiv2.Metadata(filename)
try:
exif_datetimeoriginal = metadata['Exif.Photo.DateTimeOriginal']
file.add_string_attribute('exif_datetime_original',str(exif_datetimeoriginal.raw_value))
except:
file.add_string_attribute('exif_datetime_original',"")
try:
exif_imagesoftware = metadata['Exif.Image.Software']
file.add_string_attribute('exif_software',str(exif_imagesoftware.raw_value))
except:
file.add_string_attribute('exif_software',"")
try:
exif_photoflash = metadata['Exif.Photo.Flash']
file.add_string_attribute('exif_flash',str(exif_photoflash.raw_value))
except:
file.add_string_attribute('exif_flash',"")
try:
exif_pixelydimension = metadata['Exif.Photo.PixelYDimension']
exif_pixelxdimension = metadata['Exif.Photo.PixelXDimension']
file.add_string_attribute('exif_pixeldimensions',str(exif_pixelydimension.raw_value)+'x'+str(exif_pixelxdimension.raw_value))
except:
file.add_string_attribute('exif_pixeldimensions',"")
except:
# no exif data?
file.add_string_attribute('exif_datetime_original',"")
file.add_string_attribute('exif_software',"")
file.add_string_attribute('exif_flash',"")
file.add_string_attribute('exif_pixeldimensions',"")
# try read image info directly
try:
im = Image.open(filename)
file.add_string_attribute('pixeldimensions',str(im.size[0])+'x'+str(im.size[1]))
except:
file.add_string_attribute('pixeldimensions',"[image read error]")
# video/flac handling
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'):
try:
info=kaa.metadata.parse(filename)
try: file.add_string_attribute('length',"%02i:%02i:%02i" % ((int(info.length/3600)), (int(info.length/60%60)), (int(info.length%60))))
except: file.add_string_attribute('length','[n/a]')
try: file.add_string_attribute('pixeldimensions', str(info.video[0].width) + 'x'+ str(info.video[0].height))
except: file.add_string_attribute('pixeldimensions','[n/a]')
try: file.add_string_attribute('bitrate',str(round(info.audio[0].bitrate/1000)))
except: file.add_string_attribute('bitrate','[n/a]')
try: file.add_string_attribute('samplerate',str(int(info.audio[0].samplerate))+' Hz')
except: file.add_string_attribute('samplerate','[n/a]')
try: file.add_string_attribute('title', info.title)
except: file.add_string_attribute('title', '[n/a]')
try: file.add_string_attribute('artist', info.artist)
except: file.add_string_attribute('artist', '[n/a]')
try: file.add_string_attribute('genre', info.genre)
except: file.add_string_attribute('genre', '[n/a]')
try: file.add_string_attribute('tracknumber',info.trackno)
except: file.add_string_attribute('tracknumber', '[n/a]')
try: file.add_string_attribute('date',info.userdate)
except: file.add_string_attribute('date', '[n/a]')
try: file.add_string_attribute('album',info.album)
except: file.add_string_attribute('album', '[n/a]')
except:
file.add_string_attribute('length','error')
file.add_string_attribute('pixeldimensions','error')
file.add_string_attribute('bitrate','error')
file.add_string_attribute('samplerate','error')
file.add_string_attribute('title','error')
file.add_string_attribute('artist','error')
file.add_string_attribute('genre','error')
file.add_string_attribute('track','error')
file.add_string_attribute('date','error')
file.add_string_attribute('album','error')
# pdf handling
if file.is_mime_type('application/pdf'):
try:
f = open(filename, "rb")
pdf = PdfFileReader(f)
try: file.add_string_attribute('title', pdf.getDocumentInfo().title)
except: file.add_string_attribute('title', "[n/a]")
try: file.add_string_attribute('artist', pdf.getDocumentInfo().author)
except: file.add_string_attribute('artist', "[n/a]")
f.close()
except:
file.add_string_attribute('title', "[no info]")
file.add_string_attribute('artist', "[no info]")
self.get_columns()
@uvwild
Copy link

uvwild commented Apr 14, 2018

apt install gir1.2-gexiv2-0.10 ??

@jrbray1
Copy link

jrbray1 commented Nov 26, 2020

This is very different from the original bsc-v2.py. I have taken the nautilus-columns fork and ported it to caja, getting the Icon View to work, adding jpg titles and changing 'artist' to creator. It may be useful to others. https://github.com/jrbray1/bsc-v2/blob/main/caja-columns.py

@infirit
Copy link
Author

infirit commented Nov 26, 2020

No idea where I got the original but do notice this gist is 6 years old 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment