#!/usr/bin/env python # -*- coding: utf-8 -*- import pygtk pygtk.require('2.0') import gtk import tempfile, zipfile import sys, os, errno, time from lxml import etree import gettext import webbrowser # setup translation support LOCALE_DOMAIN = 'simple-scorm-player' LOCALE_DIR = os.path.join(sys.prefix, 'share', 'locale') gettext.bindtextdomain(LOCALE_DOMAIN, LOCALE_DIR) gettext.textdomain(LOCALE_DOMAIN) gettext.install(LOCALE_DOMAIN) _ = gettext.gettext class SCORMPlayer(): def __init__(self): self.filename = '' self.orig_dir = os.getcwd() self.scorm_dir = os.path.expanduser('~/.scorm') #create ~/.scorm directory if it doesn't exist try: os.makedirs(self.scorm_dir) except OSError as exc: if exc.errno == errno.EEXIST: pass else: raise #prefix temporary dirs tempfile.tempdir = self.scorm_dir self.temp_dir = tempfile.mkdtemp() def select_dialog(self): dialog = gtk.FileChooserDialog(_("Select a SCORM package..."), None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) dialog.set_default_response(gtk.RESPONSE_OK) filter = gtk.FileFilter() filter.set_name(_("SCORM packages")) filter.add_pattern("*.zip") dialog.add_filter(filter) filter = gtk.FileFilter() filter.set_name(_("All files")) filter.add_pattern("*") dialog.add_filter(filter) response = dialog.run() if response == gtk.RESPONSE_OK: self.filename = dialog.get_filename() dialog.destroy() if response == gtk.RESPONSE_CANCEL: sys.exit(0) def is_SCORM(self): if zipfile.is_zipfile(self.filename): zf = zipfile.ZipFile(self.filename) else: return False return 'imsmanifest.xml' in zf.namelist() #all SCORM must have this file def cancel_dialog(self): dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_YES_NO) dialog.set_markup(_("Selected file is not a SCORM package")) dialog.format_secondary_markup(_("Do you want to try selecting another file?")) response = dialog.run() dialog.destroy() if response == gtk.RESPONSE_NO: sys.exit(0) def select(self): if len(sys.argv)>1: self.filename = sys.argv[1] while True: if self.filename == '': self.select_dialog() while gtk.events_pending(): gtk.main_iteration(block=False) if self.is_SCORM(): return else: self.cancel_dialog() self.filename = '' def extract(self): zf = zipfile.ZipFile(self.filename) zf.extractall(self.temp_dir) os.chdir(self.temp_dir) #eXe SCORM adds this JS library for online LMS but fails in local mode if os.path.exists('APIWrapper.js'): os.remove('APIWrapper.js') def generate_index(self): with open('imsmanifest.xml') as f: doc = etree.parse(f) namespace = doc.getroot().tag[1:].split("}")[0] #extract namespace from xml file #only a simple plain index by now (no hierarchy or sequences) title = doc.find(".//{%s}title" % namespace).text items = doc.findall(".//{%s}item" % namespace) resources = doc.findall(".//{%s}resource" % namespace) if len(resources) == 1: self.target = resources[0].get('href') return #if there's only one resource there's no need to generate an index else: self.target = 'scorm-idx.html' resdict = {} for r in resources: resdict[r.get('identifier')] = r.get('href') first_item = resdict[items[0].get('identifierref')] html_list = '