1 # -*- coding: utf-8 -*-
3 __revision__ = '$Id: $'
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Library General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 # You may use and distribute this software under the terms of the
22 # GNU General Public License, version 2 or later
24 from plugins.imp import ImportPlugin as IP
28 from xml.dom import minidom, Node
29 from lxml import etree
31 from shutil import rmtree
32 from tempfile import mkdtemp
35 log = logging.getLogger("Griffith")
38 Supports importing videodb.xml exported as single file from Kodi/XBMC.
40 http://kodi.wiki/view/Import-export_library
41 http://kodi.wiki/view/HOW-TO:Backup_the_video_library
43 See lib/plugins/imp/__init__.py for workflow how importer invokes methods from importer plugins
45 class ImportPlugin(IP):
46 description = 'Kodi/XBMC MovieDB importer'
47 author = 'Elan Ruusamäe'
48 email = 'glen@pld-linux.org'
50 file_filters = 'videodb.xml'
58 # used by get_movie_details method
59 # griffith field => kodi field
60 # griffith field is actual SQL column in 'movies' table
63 'o_title': 'originaltitle',
68 'director': 'director',
71 'classification': 'mpaa',
72 # while the trailer field exists, it is not useful for griffith
73 # as it's something like: "plugin://plugin.video.youtube/?action=play_video&videoid=..."
74 # however youtube urls can be probably fixed.
78 # rest of the stuff to insert into notes field
81 _('Play count'): 'playcount',
82 _('Date added'): 'dateadded',
83 _('Last played'): 'lastplayed',
84 _('Collection'): 'set',
85 _('Premiered'): 'premiered',
90 if not IP.initialize(self):
95 def set_source(self, name):
96 IP.set_source(self, name)
98 self.fileversion = self.read_fileversion()
99 if self.fileversion == None:
100 gutils.error(_('The format of the file is not supported.'))
105 """clear plugin state before next source file"""
109 self.fileversion = None
114 """close all resources"""
117 def read_fileversion(self):
120 self.xml = etree.parse(self.filename)
121 version = self.xml.xpath('/videodb/version')[0].text
124 log.info('Found file version %s' % version)
127 def count_movies(self):
128 """Returns number of movies in file which is about to be imported"""
130 log.error('No XML object')
136 count = int(self.xml.xpath('count(/videodb/movie)'))
140 log.info('%s movies for import' % count)
143 def get_movie_details(self):
144 """Returns dictionary with movie details"""
146 log.error('XML not opened')
150 self.items = self.xml.xpath('/videodb/movie')
153 # don't bother for empty db (shouldn't happen really)
154 if not self.items or len(self.items) < 1:
158 if self.itemindex >= len(self.items):
161 item = self.items[self.itemindex]
165 for k,v in self.field_map.items():
166 details[k] = item.findtext(v)
168 # if playcount set, means it's seen
169 details['seen'] = int(item.find('playcount').text) > 0
171 # genre can be multiple items, join by comma
172 details['genre'] = ', '.join(n.text for n in item.findall('genre'))
174 # build text for 'cast' field
176 for actor in item.findall('actor'):
177 cast.append('%s as %s' % (actor.findtext('name'), actor.findtext('role')))
180 details['cast'] = "\n".join(cast)
182 # put rest of information into notes field
184 for k,v in self.notes_map.items():
187 notes.append('%s: %s' % (k, v))
189 # credits can have multiple values, handle separately
190 credits = ', '.join(n.text for n in item.findall('credits'))
192 notes.append(_('Credits: %s') % credits)
195 details['notes'] = "\n".join(notes)
197 # increment for next iteration
198 self.itemindex = self.itemindex + 1