[xiph-commits] r3936 - in arkaiv/trunk: arkaiv/controllers arkaiv/templates arkaiv/tests/functional data/templates

dcrowdy at svn.annodex.net dcrowdy at svn.annodex.net
Wed May 27 22:48:34 PDT 2009


Author: dcrowdy
Date: 2009-05-27 22:48:33 -0700 (Wed, 27 May 2009)
New Revision: 3936

Added:
   arkaiv/trunk/arkaiv/controllers/item.py
   arkaiv/trunk/arkaiv/controllers/list.py
   arkaiv/trunk/arkaiv/tests/functional/test_item.py
   arkaiv/trunk/arkaiv/tests/functional/test_list.py
Modified:
   arkaiv/trunk/arkaiv/controllers/addmedia.py
   arkaiv/trunk/arkaiv/controllers/page.py
   arkaiv/trunk/arkaiv/controllers/page.pyc
   arkaiv/trunk/arkaiv/controllers/playlist.py
   arkaiv/trunk/arkaiv/templates/autohandler
   arkaiv/trunk/arkaiv/templates/displayitem.mak
   arkaiv/trunk/arkaiv/templates/mainpage.mak
   arkaiv/trunk/arkaiv/templates/searchresults.mak
   arkaiv/trunk/data/templates/autohandler.py
   arkaiv/trunk/data/templates/autohandler.pyc
   arkaiv/trunk/data/templates/displayitem.mak.py
   arkaiv/trunk/data/templates/displayitem.mak.pyc
   arkaiv/trunk/data/templates/mainpage.mak.py
   arkaiv/trunk/data/templates/mainpage.mak.pyc
Log:
Completed splitting of controllers


Modified: arkaiv/trunk/arkaiv/controllers/addmedia.py
===================================================================
--- arkaiv/trunk/arkaiv/controllers/addmedia.py	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/arkaiv/controllers/addmedia.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -42,7 +42,7 @@
         if (self.__addmediatoarchive(cmmlsource, oggsource) == "file exists"):
             return render ('/fileexistsmessage.mak')
         else:
-            redirect_to(controller='page', action='mainpage')
+            redirect_to(controller='list', action='index')
 
     def __addmediatoarchive(self, cmmlsource, oggsource):
         # Deal with the cmml file
@@ -167,3 +167,145 @@
  
         return
 
+    def __localdirimport(self, cmmlfilename, oggfilename): 
+        print os.path.split(cmmlfilename)
+#        if os.path.split(cmmlfilename)[1] == "":
+        if (not os.path.isfile(cmmlfilename)):
+            # create new cmmlfile
+            baseoggname = os.path.split(oggfilename)[1]
+            basecmmlname = os.path.splitext(baseoggname)[0].replace(' ',"") + ".cmml"
+            print "basecmmlname: " + basecmmlname
+            print "archive_loc: " + archive_loc
+            newcmmlname = os.path.join(archive_loc, basecmmlname)
+            print "newcmmlname: " + newcmmlname
+            parser = cmmlParser()
+            fulloggpath = os.path.join(archive_loc, baseoggname)
+            if os.path.isfile(newcmmlname):
+                print "File exists - bail time"
+                return "file exists" 
+            parser.createnewfile(newcmmlname, fulloggpath)
+
+        else:
+            newcmmlname = os.path.join(archive_loc, os.path.split(cmmlfilename)[1])
+            permanent_file = open(newcmmlname, 'w')
+            sourcefile = open(cmmlfilename, 'r')
+            shutil.copyfileobj(sourcefile, permanent_file)
+            sourcefile.close()
+            permanent_file.close()
+       
+        # Now the ogg file...
+        baseoggname = os.path.split(oggfilename)[1]
+        baseoggname = baseoggname.replace(' ',"")
+        newoggname = os.path.join(archive_loc, baseoggname)
+#        newoggname = os.path.join(archive_loc, os.path.split(oggfilename)[1])
+        permanent_file = open(newoggname, 'w')
+        sourcefile = open(oggfilename, 'r')
+        shutil.copyfileobj(sourcefile, permanent_file)
+        sourcefile.close()
+        permanent_file.close()
+
+        # shouldn't the image directory stuff happen here?
+        basename = os.path.splitext(newoggname)[0]
+        imagedirname = basename + "_clipimages"
+        # Create a directory for clip images
+#        print imagedirname
+        if not os.path.isdir(imagedirname):
+            os.makedirs(imagedirname, mode=0755)
+ 
+        # Get the title for the item (head title)
+        parser = cmmlParser()
+        parser.setcmmlfilename(newcmmlname)
+        title = parser.gettitle() 
+        # adding an item here, even though we don't actually have the source
+        # anx file in place yet...
+        basename = os.path.splitext(newoggname)[0]
+        newanxname = basename + ".anx"
+ 
+        newitemid = model.addsource(title, newoggname, newcmmlname)
+       # Need to update the source tag in the cmml file 
+        parser.updatesourcetag(newoggname)
+        parser.addmetaid(newitemid) 
+ 
+        headinfo = {}
+        headinfo['itemid']= newitemid 
+        headinfo['id'] = ""
+        headinfo['title'] = title
+        headid = model.addhead(headinfo)
+        # Now extract any clip information and add it to the database
+        # get a list of dictionary objects
+        cliplist = parser.getclipsfromcmml()  
+        for clipdict in cliplist:
+            clipdict['itemid'] = newitemid
+            model.addclip(clipdict)
+
+        # Check whether the ogg file has any existing vorbis comments/tags
+        # and import them as meta tags
+
+        parser = cmmlParser()
+        parser.setcmmlfilename(newcmmlname)
+        metalist = parser.getheadinfofromcmml()
+
+        cmd = "vorbiscomment -l " + newoggname
+        print "cmd: " + cmd
+        runit = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE , stderr=subprocess.PIPE)
+        out, err = runit.communicate()
+
+        for line in out.splitlines():
+            metadict={}
+            print line
+            tag = line.split("=")
+            metadict['name'] = tag[0]
+            metadict['content'] = tag[1]
+            metadict['id'] = tag[0]
+            metadict['scheme'] = ""
+            metalist.append(metadict)
+  
+        # Extract meta info from the head and add to database
+        for metadict in metalist:
+            metadict['headindex'] = headid
+            metadict['itemid'] = newitemid
+            model.addmeta(metadict)
+
+        # Now we read the meta tags back from the database, and write them into
+        # the cmml file, syncing the id tags - useful (essential) for editing
+        # these later.
+        metalist = model.getmetasforhead(headid)
+        # sync cmml id attribute of head metas with the database primary key
+        for meta in metalist:
+            model.syncmetaid(meta.ixm)
+
+        # and sync with the cmml file
+        # Probably best to do it in one go at this stage
+        parser.setcmmlfilename(newcmmlname)
+        parser.syncheadmetas(metalist) 
+
+        collection = request.params['collection'] 
+        model.additemtocollection(headinfo['itemid'], collection)
+        return		
+
+    def addannodexindirform(self):
+        # Currently unused - useful if importing a load of material locally
+        collectionlist = model.getcollections()
+        c.collectioninfo = ""
+        for collection in collectionlist:
+            #print collection.name
+            c.collectioninfo = c.collectioninfo + "<option>" + collection['name'] + "</option>"
+
+        return render('/addannodexindirform.mak')
+
+    def addannodexindirmedia(self):
+        directory = request.params['mediadir']
+        files = os.listdir(directory)
+        for file in files:
+            try:
+                if os.path.splitext(file)[1] == ".ogg":
+                    cmmlfilename = directory + os.path.splitext(file)[0] + ".cmml"
+                    oggfilename = directory + file
+                    print "importing: " + cmmlfilename + " " + oggfilename
+                    self.__localdirimport(cmmlfilename, oggfilename)
+                else:
+                    print "moving right past: " + file
+            except:
+                print " problem with " + file
+        return
+ 

Added: arkaiv/trunk/arkaiv/controllers/item.py
===================================================================
--- arkaiv/trunk/arkaiv/controllers/item.py	                        (rev 0)
+++ arkaiv/trunk/arkaiv/controllers/item.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -0,0 +1,264 @@
+import os
+import os.path
+from string import split
+import logging
+from pylons import config
+
+from pylons import request, response, session, tmpl_context as c
+from pylons.controllers.util import abort, redirect_to
+
+from arkaiv.lib.base import BaseController, render, model
+from arkaiv.model.oggzinfo import OggzInfo
+from arkaiv.model.cmmlparser import cmmlParser
+from arkaiv.model.framer import Frame
+
+log = logging.getLogger(__name__)
+
+path_base = config['media_path_base']
+media_url_base = config['media_url_base']
+
+class ItemController(BaseController):
+
+    def index(self):
+        # Return a rendered template
+        #return render('/item.mako')
+        # or, return a response
+        return 'Hello World'
+
+    def displayitem(self):
+
+        itemid = request.params['id']
+        toedit = request.params['edit']
+        try:
+            c.playclip = request.params['playclip']
+            #print c.playclip
+        except:
+            c.playclip = ""
+
+
+        c.itemid = itemid
+        c.itemname = model.getitemname(itemid)
+        cmmlfile = model.getitemcmmlfile(itemid)
+        # get clip information
+        c.cliplist = model.getclipinfoforitem(itemid) 
+        # get the head information now
+        c.headdict = model.getheadinfoforitem(itemid) 
+        # And now meta info - a list of dicts
+
+        # FIXME - this should be just a list of the meta objects - why return a
+        # dict?
+
+        c.metalist = model.getmetainfoforhead(c.headdict['index'])
+        c.source = model.getsourcesforitem(itemid)
+        sourcedict = {}
+        oggsource = model.getsourcepath(c.source)
+
+        # convert path to a useful url for the web server
+        urlpath = split(cmmlfile, path_base)
+        # Now split off the extension
+        urlpath = os.path.splitext(urlpath[1])[0]
+        clipimageurl = media_url_base + os.path.dirname(urlpath) + "/"
+        #url = media_url_base + urlpath + ".anx"
+        url = media_url_base + urlpath + ".ogg"
+        if c.playclip=="":
+            sourcedict['clipdetail'] = ""
+        else:
+            sourcedict['clipdetail'] = "?id=" + c.playclip
+
+        sourcedict['urlpath'] = url   # + "?id=" + c.playclip
+        sourcedict['clipimageurl'] = clipimageurl
+        # now get some source info:
+        o = OggzInfo(oggsource)
+       	sourcedict['duration'] = o.duration()
+       	sourcedict['bitrate'] = o.bitrate()
+       	sourcedict['resolution'] = o.resolution()
+       	sourcedict['framerate'] = o.framerate()
+       	sourcedict['audio'] = o.audio()
+        if (o.has_video()):
+            sourcedict['has_video'] = "Yes"
+        else:
+            sourcedict['has_video'] = "No"
+            
+        if (o.has_audio()):
+            sourcedict['has_audio'] = "Yes"
+        else:
+            sourcedict['has_audio'] = "No" 
+        c.sourcedict = sourcedict
+        
+        return render('/displayitem.mak')
+
+    def addmetainfo(self):
+        metadict = {}
+        metadict['headindex'] = request.params['headindex']
+        metadict['itemid'] = request.params['itemid']
+        metadict['id'] = request.params['metaid']
+        metadict['name'] = request.params['metaname']
+        metadict['content'] = request.params['metacontent']
+        metadict['scheme'] = request.params['metascheme']
+        # pass a dict in to the model
+        metaid = model.addmeta(metadict)
+
+        model.syncmetaid(metaid)
+        cmmlfile = model.getitemcmmlfile(metadict['itemid'])
+        parser = cmmlParser()
+        parser.setcmmlfilename(cmmlfile)
+        parser.addmetaitem(metadict)
+        # add this to the cmml file
+        redirect_to(action='displayitem', id=metadict['itemid'], edit="yes")
+
+
+    def deletemeta(self):
+        """ Deletes a meta tag for an item
+        """
+        metaid = request.params['metaid']
+        itemid = request.params['itemid']
+        headid = request.params['headid']
+        print "itemid is" + str(itemid)
+        model.deletemeta(metaid)
+        # easier to read meta info and add all in one go?
+        metalist = model.getmetasforhead(headid)
+        print metalist
+        # now write these back to the cmml file
+#        parser = ...
+        cmmlfile = model.getitemcmmlfile(itemid)
+        parser = cmmlParser()
+        parser.setcmmlfilename(cmmlfile)
+        parser.syncheadmetas(metalist)
+
+        redirect_to(action='displayitem', id=itemid, edit="yes")
+
+    def addclip(self):
+        clip = {}
+        if request.params['starttime'] == "":
+            clip['starttime'] = 0
+        else: 
+            clip['starttime'] = float(request.params['starttime'])
+        if (not request.params['endtime']):
+            print "no value for endtime"
+            clip['endtime'] = ""
+        else:
+            clip['endtime'] = float(request.params['endtime'])
+        clip['itemid'] = request.params['itemid']
+        clip['a_text'] = request.params['a_text']
+        clip['id'] = clip['starttime'] # A kludge so users don't have to worry about providing ids
+        clip['a_href'] = request.params['a_href']
+        clip['desc'] = request.params['desc']
+        has_video = request.params['hasvideo']
+
+        # first get the source file info
+        cmmlfile = model.getitemcmmlfile(clip['itemid'])
+
+        # create an image to display for the clip
+        if has_video == "Yes":
+            clip['img_src'] = self.__createimageforclip(cmmlfile, clip)
+
+        else:
+            clip['img_src'] = ""
+
+        model.addclip(clip)
+        # Now the same information added to the cmml file
+        # Clips need to be in temporal order so redo the whole lot
+        # Get a list of clip dictionary objects
+        cliplist = model.getclipinfoforitem(clip['itemid'])
+        parser = cmmlParser()
+        parser.setcmmlfilename(cmmlfile)
+        parser.addclipstocmmlfile(cliplist)
+        redirect_to(action='displayitem', id=clip['itemid'], 
+                    playclip=clip['id'], edit="yes")
+
+    def deleteclip(self):
+        clipid = request.params['clipid']
+        itemid = request.params['itemid']
+        model.deleteclip(clipid)
+        # Now update the cmml file
+        cmmlfile = model.getitemcmmlfile(itemid)
+        cliplist = model.getclipinfoforitem(itemid)
+        parser = cmmlParser()
+        parser.setcmmlfilename(cmmlfile)
+        parser.addclipstocmmlfile(cliplist)
+
+        redirect_to(action='displayitem', id=itemid, edit="yes")
+
+    def deleteitem(self):
+        itemid = request.params['itemid']
+        model.deleteitem(itemid)
+
+        # FIXME - the source files aren't actually removed from the
+        # application's media directory by doing this - at this stage I regard
+        # this as a feature...
+
+        redirect_to(controller='list', action='index')
+
+    def edititemname(self):
+        """ Called from the Ajax in place editor
+
+            returns the item name
+        """
+        text = request.params['myparam']
+        itemid = request.params['itemid']
+
+        # change this element in the database
+        model.edititemname(itemid, text)
+
+        #  Item title is not in the cmml file - although I guess it could be
+        #  linked?  On import, the item title is the same as the head title
+        
+        return text
+
+    def editheadinfo(self):
+        headinfo = {}
+        headinfo['itemid'] = request.params['itemid']
+        headinfo['id'] = request.params['headid']
+        headinfo['title'] = request.params['headtitle']
+        model.edithead(headinfo)
+
+        parser = cmmlParser()
+        cmmlfilename = model.getitemcmmlfile(headinfo['itemid'])
+        parser.setcmmlfilename(cmmlfilename)
+        parser.edithead(headinfo['id'], headinfo['title'])
+        # Assume that if we get here we have the OK to edit...
+        redirect_to(action='displayitem', id=headinfo['itemid'], edit="yes")
+
+
+
+    def __createimageforclip(self, cmmlfile, clipinfo):
+#        print "cmmlfile: " + cmmlfile
+#        print clipinfo
+        basename = os.path.splitext(cmmlfile)[0]
+#        print basename
+        imagedirname = basename + "_clipimages"
+        clipimagename = str(clipinfo['starttime']) + ".png"
+#        print "clip name: " + clipimagename
+        oggsource = model.getsourcepath(clipinfo['itemid'])
+#        print oggsource
+        cwd = os.getcwd()
+#        print cwd
+        os.chdir(imagedirname)  # ugly...
+        frameimage = Frame(oggsource, float(clipinfo['starttime']), clipimagename)    
+        print "after frameimage"
+        os.chdir(cwd)   # very ugly... #
+
+        # add that info to the dictionary - only needs to be a relative
+        # location
+        relpath = os.path.split(imagedirname)[1]
+        imagefile = relpath + "/" + clipimagename
+#        print imagefile
+        return imagefile
+
+    def editheadmetaname(self):
+        text = request.params['myparam']
+        id = request.params['id']
+        itemid = request.params['itemid']
+        field = request.params['field']
+
+        # change this element in the database
+        model.editmeta(id, field, text)
+        # change this element in the cmml file
+        parser = cmmlParser()
+        cmmlfilename = model.getitemcmmlfile(itemid)
+        parser.setcmmlfilename(cmmlfilename)
+        parser.editmeta(id, field, text)
+        
+        return text
+
+

Added: arkaiv/trunk/arkaiv/controllers/list.py
===================================================================
--- arkaiv/trunk/arkaiv/controllers/list.py	                        (rev 0)
+++ arkaiv/trunk/arkaiv/controllers/list.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -0,0 +1,15 @@
+import logging
+
+from pylons import request, response, session, tmpl_context as c
+from pylons.controllers.util import abort, redirect_to
+
+from arkaiv.lib.base import BaseController, render, model
+
+log = logging.getLogger(__name__)
+
+class ListController(BaseController):
+
+    def index(self):
+        c.items = model.getallitems()
+        return render('/mainpage.mak')
+

Modified: arkaiv/trunk/arkaiv/controllers/page.py
===================================================================
--- arkaiv/trunk/arkaiv/controllers/page.py	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/arkaiv/controllers/page.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -37,17 +37,6 @@
 
 class PageController(BaseController):
 
-    def serverinfo(self):
-        import cgi
-        import pprint
-        c.pretty_environ = cgi.escape(pprint.pformat(request.environ))
-        c.name = 'Check it out...'
-        return render('/serverinfo.mak')
-
-    def mainpage(self):
-        c.items = model.getallitems()
-        return render('/mainpage.mak')
-
     def displayadd(self):
         # Get the list of collections
         collectionlist = model.getcollections()
@@ -59,217 +48,7 @@
         return render('/addform.mak')
 
 
-    def additemstoplaylist(self):
-        nmetas = int(request.params['nummetas'])
-        playlist = request.params['playlist']
-        for i in range(nmetas):
-            try:
-                itemid = request.params[str(i)]
-                model.additemtoplaylist(playlist, itemid)
-            except:
-                pass
 
-        redirect_to(controller='playlist', action='playlistpage')
-
-
-    def addclipstoplaylist(self):
-        nclips = int(request.params['numclips'])
-        playlist = request.params['playlist']
-        for i in range(nclips):
-            try:
-                clipid = request.params[str(i)]
-                model.addcliptoplaylist(playlist, clipid)
-            except:
-                pass
-
-        redirect_to(controller='playlist', action='playlistpage')
-
-
-    def addannodexindirform(self):
-        # Currently unused - useful if importing a load of material locally
-        collectionlist = model.getcollections()
-        c.collectioninfo = ""
-        for collection in collectionlist:
-            #print collection.name
-            c.collectioninfo = c.collectioninfo + "<option>" + collection['name'] + "</option>"
-
-        return render('/addannodexindirform.mak')
-
-  
-    def displayitem(self):
-
-        itemid = request.params['id']
-        toedit = request.params['edit']
-        try:
-            c.playclip = request.params['playclip']
-            #print c.playclip
-        except:
-            c.playclip = ""
-
-
-        c.itemid = itemid
-        c.itemname = model.getitemname(itemid)
-        cmmlfile = model.getitemcmmlfile(itemid)
-        # get clip information
-        c.cliplist = model.getclipinfoforitem(itemid) 
-        # get the head information now
-        c.headdict = model.getheadinfoforitem(itemid) 
-        # And now meta info - a list of dicts
-
-        # FIXME - this should be just a list of the meta objects - why return a
-        # dict?
-
-        c.metalist = model.getmetainfoforhead(c.headdict['index'])
-        c.source = model.getsourcesforitem(itemid)
-        sourcedict = {}
-        oggsource = model.getsourcepath(c.source)
-
-        # convert path to a useful url for the web server
-        urlpath = split(cmmlfile, path_base)
-        # Now split off the extension
-        urlpath = os.path.splitext(urlpath[1])[0]
-        clipimageurl = media_url_base + os.path.dirname(urlpath) + "/"
-        #url = media_url_base + urlpath + ".anx"
-        url = media_url_base + urlpath + ".ogg"
-        if c.playclip=="":
-            sourcedict['clipdetail'] = ""
-        else:
-            sourcedict['clipdetail'] = "?id=" + c.playclip
-
-        sourcedict['urlpath'] = url   # + "?id=" + c.playclip
-        sourcedict['clipimageurl'] = clipimageurl
-        # now get some source info:
-        o = OggzInfo(oggsource)
-       	sourcedict['duration'] = o.duration()
-       	sourcedict['bitrate'] = o.bitrate()
-       	sourcedict['resolution'] = o.resolution()
-       	sourcedict['framerate'] = o.framerate()
-       	sourcedict['audio'] = o.audio()
-        if (o.has_video()):
-            sourcedict['has_video'] = "Yes"
-        else:
-            sourcedict['has_video'] = "No"
-            
-        if (o.has_audio()):
-            sourcedict['has_audio'] = "Yes"
-        else:
-            sourcedict['has_audio'] = "No" 
-        c.sourcedict = sourcedict
-        
-        return render('/displayitem.mak')
-
-    def edititemname(self):
-        """ Called from the Ajax in place editor
-
-            returns the item name
-        """
-        text = request.params['myparam']
-        itemid = request.params['itemid']
-
-        # change this element in the database
-        model.edititemname(itemid, text)
-
-        #  Item title is not in the cmml file - although I guess it could be
-        #  linked?  On import, the item title is the same as the head title
-        
-        return text
-
-    def editheadinfo(self):
-        headinfo = {}
-        headinfo['itemid'] = request.params['itemid']
-        headinfo['id'] = request.params['headid']
-        headinfo['title'] = request.params['headtitle']
-        model.edithead(headinfo)
-
-        parser = cmmlParser()
-        cmmlfilename = model.getitemcmmlfile(headinfo['itemid'])
-        parser.setcmmlfilename(cmmlfilename)
-        parser.edithead(headinfo['id'], headinfo['title'])
-        # Assume that if we get here we have the OK to edit...
-        redirect_to(action='displayitem', id=headinfo['itemid'], edit="yes")
-
-    def addmetainfo(self):
-        metadict = {}
-        metadict['headindex'] = request.params['headindex']
-        metadict['itemid'] = request.params['itemid']
-        metadict['id'] = request.params['metaid']
-        metadict['name'] = request.params['metaname']
-        metadict['content'] = request.params['metacontent']
-        metadict['scheme'] = request.params['metascheme']
-        # pass a dict in to the model
-        metaid = model.addmeta(metadict)
-
-        model.syncmetaid(metaid)
-        cmmlfile = model.getitemcmmlfile(metadict['itemid'])
-        parser = cmmlParser()
-        parser.setcmmlfilename(cmmlfile)
-        parser.addmetaitem(metadict)
-        # add this to the cmml file
-        redirect_to(action='displayitem', id=metadict['itemid'], edit="yes")
-
-    def addclip(self):
-        clip = {}
-        if request.params['starttime'] == "":
-            clip['starttime'] = 0
-        else: 
-            clip['starttime'] = float(request.params['starttime'])
-        if (not request.params['endtime']):
-            print "no value for endtime"
-            clip['endtime'] = ""
-        else:
-            clip['endtime'] = float(request.params['endtime'])
-        clip['itemid'] = request.params['itemid']
-        clip['a_text'] = request.params['a_text']
-        clip['id'] = clip['starttime'] # A kludge so users don't have to worry about providing ids
-        clip['a_href'] = request.params['a_href']
-        clip['desc'] = request.params['desc']
-        has_video = request.params['hasvideo']
-
-        # first get the source file info
-        cmmlfile = model.getitemcmmlfile(clip['itemid'])
-
-        # create an image to display for the clip
-        if has_video == "Yes":
-            clip['img_src'] = self.__createimageforclip(cmmlfile, clip)
-
-        else:
-            clip['img_src'] = ""
-
-        model.addclip(clip)
-        # Now the same information added to the cmml file
-        # Clips need to be in temporal order so redo the whole lot
-        # Get a list of clip dictionary objects
-        cliplist = model.getclipinfoforitem(clip['itemid'])
-        parser = cmmlParser()
-        parser.setcmmlfilename(cmmlfile)
-        parser.addclipstocmmlfile(cliplist)
-        redirect_to(action='displayitem', id=clip['itemid'], 
-                    playclip=clip['id'], edit="yes")
-
-    def deleteclip(self):
-        clipid = request.params['clipid']
-        itemid = request.params['itemid']
-        model.deleteclip(clipid)
-        # Now update the cmml file
-        cmmlfile = model.getitemcmmlfile(itemid)
-        cliplist = model.getclipinfoforitem(itemid)
-        parser = cmmlParser()
-        parser.setcmmlfilename(cmmlfile)
-        parser.addclipstocmmlfile(cliplist)
-
-        redirect_to(action='displayitem', id=itemid, edit="yes")
-
-    def deleteitem(self):
-        itemid = request.params['itemid']
-        model.deleteitem(itemid)
-
-        # FIXME - the source files aren't actually removed from the
-        # application's media directory by doing this - at this stage I regard
-        # this as a feature...
-
-        redirect_to(action='mainpage')
-
-
     def search(self):
         searchterms = request.params['searchterms']
 
@@ -291,227 +70,5 @@
  
         return render('/searchresults.mak')
 
-
-    def editheadmetaname(self):
-        text = request.params['myparam']
-        id = request.params['id']
-        itemid = request.params['itemid']
-        field = request.params['field']
-
-        # change this element in the database
-        model.editmeta(id, field, text)
-        # change this element in the cmml file
-        parser = cmmlParser()
-        cmmlfilename = model.getitemcmmlfile(itemid)
-        parser.setcmmlfilename(cmmlfilename)
-        parser.editmeta(id, field, text)
-        
-        return text
-
-    def addannodexindirmedia(self):
-        directory = request.params['mediadir']
-        files = os.listdir(directory)
-        for file in files:
-            try:
-                if os.path.splitext(file)[1] == ".ogg":
-                    cmmlfilename = directory + os.path.splitext(file)[0] + ".cmml"
-                    oggfilename = directory + file
-                    print "importing: " + cmmlfilename + " " + oggfilename
-                    self.__localdirimport(cmmlfilename, oggfilename)
-                else:
-                    print "moving right past: " + file
-            except:
-                print " problem with " + file
-        return
-#    def addannodexindirmedia(self):
-#        directory = request.params['mediadir']
-#        files = os.listdir(directory)
-#        for file in files:
-#            try:
-#                if os.path.splitext(file)[1] == ".cmml":
-#                    oggfilename = directory + os.path.splitext(file)[0] + ".ogg"
-#                    cmmlfilename = directory + file
-#                    print "importing: " + cmmlfilename + " " + oggfilename
-#                    self.__localdirimport(cmmlfilename, oggfilename)
-#                else:
-#                    print "moving right past: " + file
-#            except:
-#                print " problem with " + file
-#        return
-  
-    def __localdirimport(self, cmmlfilename, oggfilename): 
-        print os.path.split(cmmlfilename)
-#        if os.path.split(cmmlfilename)[1] == "":
-        if (not os.path.isfile(cmmlfilename)):
-            # create new cmmlfile
-            baseoggname = os.path.split(oggfilename)[1]
-            basecmmlname = os.path.splitext(baseoggname)[0].replace(' ',"") + ".cmml"
-            print "basecmmlname: " + basecmmlname
-            print "archive_loc: " + archive_loc
-            newcmmlname = os.path.join(archive_loc, basecmmlname)
-            print "newcmmlname: " + newcmmlname
-            parser = cmmlParser()
-            fulloggpath = os.path.join(archive_loc, baseoggname)
-            if os.path.isfile(newcmmlname):
-                print "File exists - bail time"
-                return "file exists" 
-            parser.createnewfile(newcmmlname, fulloggpath)
-
-        else:
-            newcmmlname = os.path.join(archive_loc, os.path.split(cmmlfilename)[1])
-            permanent_file = open(newcmmlname, 'w')
-            sourcefile = open(cmmlfilename, 'r')
-            shutil.copyfileobj(sourcefile, permanent_file)
-            sourcefile.close()
-            permanent_file.close()
-       
-        # Now the ogg file...
-        baseoggname = os.path.split(oggfilename)[1]
-        baseoggname = baseoggname.replace(' ',"")
-        newoggname = os.path.join(archive_loc, baseoggname)
-#        newoggname = os.path.join(archive_loc, os.path.split(oggfilename)[1])
-        permanent_file = open(newoggname, 'w')
-        sourcefile = open(oggfilename, 'r')
-        shutil.copyfileobj(sourcefile, permanent_file)
-        sourcefile.close()
-        permanent_file.close()
-
-        # shouldn't the image directory stuff happen here?
-        basename = os.path.splitext(newoggname)[0]
-        imagedirname = basename + "_clipimages"
-        # Create a directory for clip images
-#        print imagedirname
-        if not os.path.isdir(imagedirname):
-            os.makedirs(imagedirname, mode=0755)
  
-        # Get the title for the item (head title)
-        parser = cmmlParser()
-        parser.setcmmlfilename(newcmmlname)
-        title = parser.gettitle() 
-        # adding an item here, even though we don't actually have the source
-        # anx file in place yet...
-        basename = os.path.splitext(newoggname)[0]
-        newanxname = basename + ".anx"
- 
-        newitemid = model.addsource(title, newoggname, newcmmlname)
-       # Need to update the source tag in the cmml file 
-        parser.updatesourcetag(newoggname)
-        parser.addmetaid(newitemid) 
- 
-        headinfo = {}
-        headinfo['itemid']= newitemid 
-        headinfo['id'] = ""
-        headinfo['title'] = title
-        headid = model.addhead(headinfo)
-        # Now extract any clip information and add it to the database
-        # get a list of dictionary objects
-        cliplist = parser.getclipsfromcmml()  
-        for clipdict in cliplist:
-            clipdict['itemid'] = newitemid
-            model.addclip(clipdict)
 
-        # Check whether the ogg file has any existing vorbis comments/tags
-        # and import them as meta tags
-
-        parser = cmmlParser()
-        parser.setcmmlfilename(newcmmlname)
-        metalist = parser.getheadinfofromcmml()
-
-        cmd = "vorbiscomment -l " + newoggname
-        print "cmd: " + cmd
-        runit = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE , stderr=subprocess.PIPE)
-        out, err = runit.communicate()
-
-        for line in out.splitlines():
-            metadict={}
-            print line
-            tag = line.split("=")
-            metadict['name'] = tag[0]
-            metadict['content'] = tag[1]
-            metadict['id'] = tag[0]
-            metadict['scheme'] = ""
-            metalist.append(metadict)
-  
-        # Extract meta info from the head and add to database
-        for metadict in metalist:
-            metadict['headindex'] = headid
-            metadict['itemid'] = newitemid
-            model.addmeta(metadict)
-
-        # Now we read the meta tags back from the database, and write them into
-        # the cmml file, syncing the id tags - useful (essential) for editing
-        # these later.
-        metalist = model.getmetasforhead(headid)
-        # sync cmml id attribute of head metas with the database primary key
-        for meta in metalist:
-            model.syncmetaid(meta.ixm)
-
-        # and sync with the cmml file
-        # Probably best to do it in one go at this stage
-        parser.setcmmlfilename(newcmmlname)
-        parser.syncheadmetas(metalist) 
-
-        collection = request.params['collection'] 
-        model.additemtocollection(headinfo['itemid'], collection)
-        return		
-
-    def deletemeta(self):
-        metaid = request.params['metaid']
-        itemid = request.params['itemid']
-        headid = request.params['headid']
-        print "itemid is" + str(itemid)
-        model.deletemeta(metaid)
-        # easier to read meta info and add all in one go?
-        metalist = model.getmetasforhead(headid)
-        print metalist
-        # now write these back to the cmml file
-#        parser = ...
-        cmmlfile = model.getitemcmmlfile(itemid)
-        parser = cmmlParser()
-        parser.setcmmlfilename(cmmlfile)
-        parser.syncheadmetas(metalist)
-
-        redirect_to(action='displayitem', id=itemid, edit="yes")
-
-
-    def __createimageforclip(self, cmmlfile, clipinfo):
-#        print "cmmlfile: " + cmmlfile
-#        print clipinfo
-        basename = os.path.splitext(cmmlfile)[0]
-#        print basename
-        imagedirname = basename + "_clipimages"
-        clipimagename = str(clipinfo['starttime']) + ".png"
-#        print "clip name: " + clipimagename
-        oggsource = model.getsourcepath(clipinfo['itemid'])
-#        print oggsource
-        cwd = os.getcwd()
-#        print cwd
-        os.chdir(imagedirname)  # ugly...
-        frameimage = Frame(oggsource, float(clipinfo['starttime']), clipimagename)    
-        print "after frameimage"
-        os.chdir(cwd)   # very ugly... #
-
-        # add that info to the dictionary - only needs to be a relative
-        # location
-        relpath = os.path.split(imagedirname)[1]
-        imagefile = relpath + "/" + clipimagename
-#        print imagefile
-        return imagefile
-
-    def __geturlforcmmlfile(self, cmmlfile, clipid):
-        """ Given a cmml filename and clipid (optional), returns
-            url information - a base path and the clip id detail
-        """
-        url={}
-        urlpath = split(cmmlfile, path_base)
-        urlpath = os.path.splitext(urlpath[1])[0]
-        #clipimageurl = media_url_base + os.path.dirname(urlpath) + "/"
-        url['base'] = media_url_base + urlpath + ".anx"
-        if clipid=="":
-            url['clipdetail'] = ""
-        else:
-            url['clipdetail'] = "?id=" + clipid
-
-        return url
-
-

Modified: arkaiv/trunk/arkaiv/controllers/page.pyc
===================================================================
(Binary files differ)

Modified: arkaiv/trunk/arkaiv/controllers/playlist.py
===================================================================
--- arkaiv/trunk/arkaiv/controllers/playlist.py	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/arkaiv/controllers/playlist.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -99,4 +99,29 @@
         else:
             return render('/playlistview.mak')
 
+    def additemstoplaylist(self):
+        nmetas = int(request.params['nummetas'])
+        playlist = request.params['playlist']
+        for i in range(nmetas):
+            try:
+                itemid = request.params[str(i)]
+                model.additemtoplaylist(playlist, itemid)
+            except:
+                pass
 
+        redirect_to(controller='playlist', action='playlistpage')
+
+
+    def addclipstoplaylist(self):
+        nclips = int(request.params['numclips'])
+        playlist = request.params['playlist']
+        for i in range(nclips):
+            try:
+                clipid = request.params[str(i)]
+                model.addcliptoplaylist(playlist, clipid)
+            except:
+                pass
+
+        redirect_to(controller='playlist', action='playlistpage')
+
+

Modified: arkaiv/trunk/arkaiv/templates/autohandler
===================================================================
--- arkaiv/trunk/arkaiv/templates/autohandler	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/arkaiv/templates/autohandler	2009-05-28 05:48:33 UTC (rev 3936)
@@ -10,7 +10,7 @@
 <h1>Arkaiv</h1>
 <div id="navcontainer">
 <ul id="navlist">
-  <li>${ h.link_to("All Items", h.url_for(controller='page', action="mainpage")) }</li>
+  <li>${ h.link_to("All Items", h.url_for(controller='list', action='index')) }</li>
   <li>${ h.link_to("Collections", h.url_for(controller='collection', action='list')) }</li>
   <li>${ h.link_to("Add media", h.url_for(controller='addmedia', action='index')) }</li>
   <li>${ h.link_to("Playlists", h.url_for(controller='playlist', action="playlistpage")) }</li>

Modified: arkaiv/trunk/arkaiv/templates/displayitem.mak
===================================================================
--- arkaiv/trunk/arkaiv/templates/displayitem.mak	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/arkaiv/templates/displayitem.mak	2009-05-28 05:48:33 UTC (rev 3936)
@@ -5,7 +5,7 @@
 ## Title of item and script to change name
 <p id="edititemname">${c.itemname}</p>
 <script type="text/javascript">
- new Ajax.InPlaceEditor('edititemname', '/page/edititemname', { callback: function(form, value) { return 'itemid=${c.itemid}&myparam=' + escape(value) }});
+ new Ajax.InPlaceEditor('edititemname', '/item/edititemname', { callback: function(form, value) { return 'itemid=${c.itemid}&myparam=' + escape(value) }});
 </script>
 
 ## Or delete it...
@@ -43,7 +43,7 @@
 ##Header info - should really only be editable by priveleged users
 <hr>
 Head:
-${ h.form(h.url_for(action='editheadinfo'), multipart=True) }
+${ h.form(h.url_for(controller='item', action='editheadinfo'), multipart=True) }
 id:
 ${ h.text_field('headid', value=c.headdict['id']) }
 Title:
@@ -66,13 +66,13 @@
 <td>
 <p id="editmetaname">${metainfo['name']}</p>
 <script type="text/javascript">
- new Ajax.InPlaceEditor('editmetaname', '/page/editheadmetaname', { callback: function(form, value) { return 'id=${metainfo['id']}&field=name&itemid=${c.itemid}&myparam=' + escape(value) }});
+ new Ajax.InPlaceEditor('editmetaname', '/item/editheadmetaname', { callback: function(form, value) { return 'id=${metainfo['id']}&field=name&itemid=${c.itemid}&myparam=' + escape(value) }});
 </script>
 </td>
 <td>
 <p id="editmetacontent">${metainfo['content']}</p>
 <script type="text/javascript">
- new Ajax.InPlaceEditor('editmetacontent', '/page/editheadmetaname', { callback: function(form, value) { return 'id=${metainfo['id']}&field=content&itemid=${c.itemid}&myparam=' + escape(value) }});
+ new Ajax.InPlaceEditor('editmetacontent', '/item/editheadmetaname', { callback: function(form, value) { return 'id=${metainfo['id']}&field=content&itemid=${c.itemid}&myparam=' + escape(value) }});
 </script>
 </td>
 <td>

Modified: arkaiv/trunk/arkaiv/templates/mainpage.mak
===================================================================
--- arkaiv/trunk/arkaiv/templates/mainpage.mak	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/arkaiv/templates/mainpage.mak	2009-05-28 05:48:33 UTC (rev 3936)
@@ -5,7 +5,7 @@
 
 % for item in c.items:
 <li>
-    ${ h.link_to(item['name'], h.url_for(action="displayitem", edit="no", id=item['index'])) }
+    ${ h.link_to(item['name'], h.url_for(controller='item', action='displayitem', edit="no", id=item['index'])) }
 </li>
 % endfor
 

Modified: arkaiv/trunk/arkaiv/templates/searchresults.mak
===================================================================
--- arkaiv/trunk/arkaiv/templates/searchresults.mak	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/arkaiv/templates/searchresults.mak	2009-05-28 05:48:33 UTC (rev 3936)
@@ -3,7 +3,7 @@
 
 <hr>
 <p>Items:</p>
-<form name='items' action='additemstoplaylist'>
+${ h.form(h.url_for(controller='playlist', action='additemstoplaylist'), name='items', multipart=True) }
 <table>
 <tr>
 <td>Item</td>
@@ -24,6 +24,7 @@
 i = i + 1
 %>
 % endfor
+${ h.end_form() } 
 </table>
 Playlist:
 ${ h.select("playlist", c.playlistinfo)}
@@ -34,7 +35,7 @@
 
 <hr>
 <p>Meta names:</p>
-<form name='metas' action='additemstoplaylist'>
+${ h.form(h.url_for(controller='playlist', action='additemstoplaylist'), name='metas', multipart=True) }
 <table>
 <tr>
 <td>Name</td>
@@ -61,12 +62,12 @@
 
 ${ h.hidden_field('nummetas', value=i) }
 ${ h.submit('Add') } 
-</form>
+${ h.end_form() } 
 
 <hr>
 Clips:
 <table>
-<form name='clips' action='addclipstoplaylist'>
+${ h.form(h.url_for(controller='playlist', action='addclipstoplaylist'), name='clips', multipart=True) }
 <tr>
 <td>id</td>
 <td>desc</td>
@@ -92,5 +93,5 @@
 
 ${ h.hidden_field('numclips', value=i) }
 ${ h.submit('Add') } 
-</form>
+${ h.end_form() } 
 

Added: arkaiv/trunk/arkaiv/tests/functional/test_item.py
===================================================================
--- arkaiv/trunk/arkaiv/tests/functional/test_item.py	                        (rev 0)
+++ arkaiv/trunk/arkaiv/tests/functional/test_item.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -0,0 +1,7 @@
+from arkaiv.tests import *
+
+class TestItemController(TestController):
+
+    def test_index(self):
+        response = self.app.get(url(controller='item', action='index'))
+        # Test response...

Added: arkaiv/trunk/arkaiv/tests/functional/test_list.py
===================================================================
--- arkaiv/trunk/arkaiv/tests/functional/test_list.py	                        (rev 0)
+++ arkaiv/trunk/arkaiv/tests/functional/test_list.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -0,0 +1,7 @@
+from arkaiv.tests import *
+
+class TestListController(TestController):
+
+    def test_index(self):
+        response = self.app.get(url(controller='list', action='index'))
+        # Test response...

Modified: arkaiv/trunk/data/templates/autohandler.py
===================================================================
--- arkaiv/trunk/data/templates/autohandler.py	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/data/templates/autohandler.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -3,7 +3,7 @@
 __M_dict_builtin = dict
 __M_locals_builtin = locals
 _magic_number = 5
-_modified_time = 1243480755.038595
+_modified_time = 1243485005.7403729
 _template_filename=u'/home/dcrowdy/src/arkaiv/working/trunk/arkaiv/templates/autohandler'
 _template_uri=u'/autohandler'
 _template_cache=cache.Cache(__name__, _modified_time)
@@ -24,7 +24,7 @@
         __M_writer(unicode( h.javascript_include_tag('/javascripts/effects.js', builtins=True) ))
         __M_writer(u' \n\n    </head>\n    <body onkeypress=\'keyPressed(event)\'>\n<p class="header">\n<h1>Arkaiv</h1>\n<div id="navcontainer">\n<ul id="navlist">\n  <li>')
         # SOURCE LINE 13
-        __M_writer(unicode( h.link_to("All Items", h.url_for(controller='page', action="mainpage")) ))
+        __M_writer(unicode( h.link_to("All Items", h.url_for(controller='list', action='index')) ))
         __M_writer(u'</li>\n  <li>')
         # SOURCE LINE 14
         __M_writer(unicode( h.link_to("Collections", h.url_for(controller='collection', action='list')) ))

Modified: arkaiv/trunk/data/templates/autohandler.pyc
===================================================================
(Binary files differ)

Modified: arkaiv/trunk/data/templates/displayitem.mak.py
===================================================================
--- arkaiv/trunk/data/templates/displayitem.mak.py	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/data/templates/displayitem.mak.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -3,7 +3,7 @@
 __M_dict_builtin = dict
 __M_locals_builtin = locals
 _magic_number = 5
-_modified_time = 1242363498.105473
+_modified_time = 1243488511.693424
 _template_filename='/home/dcrowdy/src/arkaiv/working/trunk/arkaiv/templates/displayitem.mak'
 _template_uri='/displayitem.mak'
 _template_cache=cache.Cache(__name__, _modified_time)
@@ -34,7 +34,7 @@
         # SOURCE LINE 6
         __M_writer(u'<p id="edititemname">')
         __M_writer(unicode(c.itemname))
-        __M_writer(u'</p>\n<script type="text/javascript">\n new Ajax.InPlaceEditor(\'edititemname\', \'/page/edititemname\', { callback: function(form, value) { return \'itemid=')
+        __M_writer(u'</p>\n<script type="text/javascript">\n new Ajax.InPlaceEditor(\'edititemname\', \'/item/edititemname\', { callback: function(form, value) { return \'itemid=')
         # SOURCE LINE 8
         __M_writer(unicode(c.itemid))
         __M_writer(u"&myparam=' + escape(value) }});\n</script>\n\n")
@@ -76,7 +76,7 @@
         # SOURCE LINE 44
         __M_writer(u'<hr>\nHead:\n')
         # SOURCE LINE 46
-        __M_writer(unicode( h.form(h.url_for(action='editheadinfo'), multipart=True) ))
+        __M_writer(unicode( h.form(h.url_for(controller='item', action='editheadinfo'), multipart=True) ))
         __M_writer(u'\nid:\n')
         # SOURCE LINE 48
         __M_writer(unicode( h.text_field('headid', value=c.headdict['id']) ))
@@ -99,7 +99,7 @@
             __M_writer(u'<tr>\n<td>\n<p id="editmetaname">')
             # SOURCE LINE 67
             __M_writer(unicode(metainfo['name']))
-            __M_writer(u'</p>\n<script type="text/javascript">\n new Ajax.InPlaceEditor(\'editmetaname\', \'/page/editheadmetaname\', { callback: function(form, value) { return \'id=')
+            __M_writer(u'</p>\n<script type="text/javascript">\n new Ajax.InPlaceEditor(\'editmetaname\', \'/item/editheadmetaname\', { callback: function(form, value) { return \'id=')
             # SOURCE LINE 69
             __M_writer(unicode(metainfo['id']))
             __M_writer(u'&field=name&itemid=')
@@ -107,7 +107,7 @@
             __M_writer(u'&myparam=\' + escape(value) }});\n</script>\n</td>\n<td>\n<p id="editmetacontent">')
             # SOURCE LINE 73
             __M_writer(unicode(metainfo['content']))
-            __M_writer(u'</p>\n<script type="text/javascript">\n new Ajax.InPlaceEditor(\'editmetacontent\', \'/page/editheadmetaname\', { callback: function(form, value) { return \'id=')
+            __M_writer(u'</p>\n<script type="text/javascript">\n new Ajax.InPlaceEditor(\'editmetacontent\', \'/item/editheadmetaname\', { callback: function(form, value) { return \'id=')
             # SOURCE LINE 75
             __M_writer(unicode(metainfo['id']))
             __M_writer(u'&field=content&itemid=')

Modified: arkaiv/trunk/data/templates/displayitem.mak.pyc
===================================================================
(Binary files differ)

Modified: arkaiv/trunk/data/templates/mainpage.mak.py
===================================================================
--- arkaiv/trunk/data/templates/mainpage.mak.py	2009-05-28 03:37:52 UTC (rev 3935)
+++ arkaiv/trunk/data/templates/mainpage.mak.py	2009-05-28 05:48:33 UTC (rev 3936)
@@ -3,8 +3,8 @@
 __M_dict_builtin = dict
 __M_locals_builtin = locals
 _magic_number = 5
-_modified_time = 1239258391.0307009
-_template_filename='/home/dcrowdy/src/arkaiv/trunk/arkaiv/templates/mainpage.mak'
+_modified_time = 1243485005.717896
+_template_filename='/home/dcrowdy/src/arkaiv/working/trunk/arkaiv/templates/mainpage.mak'
 _template_uri='/mainpage.mak'
 _template_cache=cache.Cache(__name__, _modified_time)
 _source_encoding=None
@@ -36,7 +36,7 @@
             # SOURCE LINE 7
             __M_writer(u'<li>\n    ')
             # SOURCE LINE 8
-            __M_writer(unicode( h.link_to(item['name'], h.url_for(action="displayitem", edit="no", id=item['index'])) ))
+            __M_writer(unicode( h.link_to(item['name'], h.url_for(controller='item', action='displayitem', edit="no", id=item['index'])) ))
             __M_writer(u'\n</li>\n')
         # SOURCE LINE 11
         __M_writer(u'\n\n')

Modified: arkaiv/trunk/data/templates/mainpage.mak.pyc
===================================================================
(Binary files differ)



More information about the commits mailing list