Beispiel #1
0
 def getfileurl(self, node):
     # This method has all sorts of magic to write a
     # RealPix file "just in time".  If the node has
     # changed there is a tmpfile attribute.  Since the
     # node has changed internally, we must write a copy
     # and we'll use the tmpfile attribute for a file name.
     # If the node has no URL, there is no existing file
     # that we can use, so we invent a name and write the
     # file.
     url = Channel.ChannelWindowAsync.getfileurl(self, node)
     if not url or url[:5] == 'data:':
         if hasattr(node, 'rptmpfile') and node.rptmpfile[1] == url:
             url = node.rptmpfile[0]
         else:
             import tempfile, realsupport, MMurl
             f = MMurl.urlopen(url)
             head = f.read(4)
             if head != '<imf':
                 f.close()
                 # delete rptmpfile attr if it exists
                 node.rptmpfile = None
                 del node.rptmpfile
                 return url
             rp = realsupport.RPParser(url)
             rp.feed(head)
             rp.feed(f.read())
             f.close()
             rp.close()
             f = tempfile.mktemp('.rp')
             nurl = MMurl.pathname2url(f)
             node.rptmpfile = nurl, url
             realsupport.writeRP(f, rp, node, baseurl=url)
             if not self.__callback_added:
                 import windowinterface
                 windowinterface.addclosecallback(_deltmpfiles, ())
                 VideoChannel.__callback_added = 1
             self.tmpfiles.append(f)
     return url
Beispiel #2
0
    def update(self, changed = 0):
        node = self.node
        oldrp = self.rp
        if node.GetType() != 'ext' or \
           node.GetChannelType() != 'RealPix':
            # not a RealPix node anymore
##             if hasattr(node, 'expanded'):
##                 import HierarchyView
##                 HierarchyView.collapsenode(node)
            del node.slideshow
            self.destroy()
            # XXX what to do with node.tmpfile?
            if hasattr(node, 'tmpfile'):
                try:
                    os.unlink(node.tmpfile)
                except:
                    pass
                del node.tmpfile
            return
        if oldrp is None:
            return
        ctx = node.GetContext()
        url = MMAttrdefs.getattr(node, 'file')
        ourl = url
        if url:
            url = ctx.findurl(url)
            utype, host, path, params, query, tag = urlparse.urlparse(url)
            url = urlparse.urlunparse((utype, host, path, params, query, ''))
        if url != self.url:
            # different URL specified
            try:
                if not url:
                    raise IOError
                fp = MMurl.urlopen(url)
            except IOError:
                # new file does not exist, keep content
                rp = self.rp
            else:
                # new file exists, use it
                import realsupport
                self.filename = url
                rp = realsupport.RPParser(url, baseurl = ourl, printfunc = self.printfunc)
                try:
                    rp.feed(fp.read())
                    rp.close()
                except:
                    import sys
                    tp, vl, tb = sys.exc_info()
                    msg = 'Error reading RealPix file %s:\n%s' % (url, vl)
                    windowinterface.showmessage(msg, mtype = 'warning')
                    self.node.set_infoicon('error', msg)
                    rp = DummyRP()
                fp.close()
            if rp is not self.rp and hasattr(node, 'tmpfile'):
                # new content, delete temp file
##                 windowinterface.showmessage('You have edited the content of the slideshow file in node %s on channel %s' % (MMAttrdefs.getattr(node, 'name') or '<unnamed>', node.GetChannelName()), mtype = 'warning')
                choice = self.asksavechanges()
                if choice == 2:
                    # cancel
                    node.SetAttr('file', self.url)
                    self.update()
                    return
                if choice == 0:
                    # yes, save file
                    node.SetAttr('file', self.url)
                    writenode(node)
                    node.SetAttr('file', url)
                else:
                    # no, discard changes
                    try:
                        os.unlink(node.tmpfile)
                    except:
                        pass
                    del node.tmpfile
            self.url = url
            self.rp = rp
        rp = self.rp
        attrdict = node.GetAttrDict()
        bitrate = MMAttrdefs.getattr(node, 'bitrate')
        if bitrate != rp.bitrate:
            if rp is oldrp:
                rp.bitrate = bitrate
                changed = 1
            else:
                attrdict['bitrate'] = rp.bitrate
        size = MMAttrdefs.getattr(node, 'size')
        if size != (rp.width, rp.height):
            if rp is oldrp:
                rp.width, rp.height = size
                changed = 1
            else:
                if rp.width == 0 and rp.height == 0:
                    rp.width, rp.height = node.GetChannel().get('base_winoff',(0,0,256,256))[2:4]
                attrdict['size'] = rp.width, rp.height
        duration = MMAttrdefs.getattr(node, 'duration')
        if abs(float(duration - rp.duration)) / max(duration, rp.duration, 1) > 0.00001:
##         if duration != rp.duration:
            if rp is oldrp:
                rp.duration = duration
                changed = 1
            else:
                attrdict['duration'] = rp.duration
        aspect = MMAttrdefs.getattr(node, 'aspect')
        if (rp.aspect == 'true') != aspect:
            if rp is oldrp:
                rp.aspect = ['false','true'][aspect]
                changed = 1
            else:
                attrdict['aspect'] = rp.aspect == 'true'
        author = MMAttrdefs.getattr(node, 'author')
        if author != rp.author:
            if rp is oldrp:
                rp.author = author
                changed = 1
            elif rp.author:
                attrdict['author'] = rp.author
            elif attrdict.has_key('author'):
                del attrdict['author']
        copyright = MMAttrdefs.getattr(node, 'copyright')
        if copyright != rp.copyright:
            if rp is oldrp:
                rp.copyright = attrdict.get('copyright')
                changed = 1
            elif rp.copyright:
                attrdict['copyright'] = rp.copyright
            elif attrdict.has_key('copyright'):
                del attrdict['copyright']
        title = MMAttrdefs.getattr(node, 'title')
        if title != rp.title:
            if rp is oldrp:
                rp.title = attrdict.get('title')
                changed = 1
            elif rp.title:
                attrdict['title'] = rp.title
            elif attrdict.has_key('title'):
                del attrdict['title']
        href = MMAttrdefs.getattr(node, 'href')
        if href != rp.url:
            if rp is oldrp:
                rp.url = attrdict.get('href')
                changed = 1
            elif rp.url:
                attrdict['href'] = rp.url
            elif attrdict.has_key('href'):
                del attrdict['href']
        maxfps = MMAttrdefs.getattr(node, 'maxfps')
        if maxfps != rp.maxfps:
            if rp is oldrp:
                rp.maxfps = maxfps
                changed = 1
            elif rp.maxfps is not None:
                attrdict['maxfps'] = rp.maxfps
            elif attrdict.has_key('maxfps'):
                del attrdict['maxfps']
        preroll = MMAttrdefs.getattr(node, 'preroll')
        if preroll != rp.preroll:
            if rp is oldrp:
                rp.preroll = preroll
                changed = 1
            elif rp.preroll is not None:
                attrdict['preroll'] = rp.preroll
            elif attrdict.has_key('preroll'):
                del attrdict['preroll']
        if hasattr(node, 'expanded'):
            if oldrp is rp:
                i = 0
                children = node.children
                nchildren = len(children)
                taglist = rp.tags
                ntags = len(taglist)
                rp.tags = []
                nnodes = max(ntags, nchildren)
                while i < nnodes:
                    if i < nchildren:
                        childattrs = children[i].attrdict
                        rp.tags.append(childattrs.copy())
                    else:
                        changed = 1
                        childattrs = None
                    if i < ntags:
                        attrs = taglist[i]
                    else:
                        changed = 1
                        attrs = None
                    if childattrs != attrs:
                        changed = 1
                    i = i + 1
##             else:
##                 # re-create children
##                 import HierarchyView
##                 HierarchyView.collapsenode(node)
##                 HierarchyView.expandnode(node)
        if changed:
            if not hasattr(node, 'tmpfile'):
                url = MMAttrdefs.getattr(node, 'file')
                url = node.context.findurl(url)
##                 if not url:
##                     windowinterface.showmessage('specify a location for this node')
##                     return
                utype, host, path, params, query, fragment = urlparse.urlparse(url)
                if (utype and utype != 'file') or \
                   (host and host != 'localhost'):
                    windowinterface.showmessage('Cannot edit remote RealPix files.')
                    return
                import tempfile
                pre = tempfile.gettempprefix()
                dir = os.path.dirname(MMurl.url2pathname(path))
                while 1:
                    tempfile.counter = tempfile.counter + 1
                    file = os.path.join(dir, pre+`tempfile.counter`+'.rp')
                    if not os.path.exists(file):
                        break
                node.tmpfile = file
                if not SlideShow.__callback_added:
                    windowinterface.addclosecallback(
                            deltmpfiles, ())
                    SlideShow.__callback_added = 1
                SlideShow.tmpfiles.append(file)
##             import realsupport
##             realsupport.writeRP(node.tmpfile, rp, node)
            MMAttrdefs.flushcache(node)
Beispiel #3
0
 def __init__(self, node, new_file = 0):
     if node is None:
         # special case, only used in copy method
         return
     if node.GetType() != 'ext' or \
        node.GetChannelType() != 'RealPix':
         raise RuntimeError("shouldn't happen")
     update = 0
     self.node = node
     import realsupport
     ctx = node.GetContext()
     url = MMAttrdefs.getattr(node, 'file')
     if not url:
         name = MMAttrdefs.getattr(node, 'name') or '<unnamed>'
         cname = node.GetChannelName()
         windowinterface.showmessage('No URL specified for slideshow node %s on channel %s' % (name, cname), mtype = 'warning')
         rp = DummyRP()
     else:
         ourl = url
         url = ctx.findurl(url)
         utype, host, path, params, query, tag = urlparse.urlparse(url)
         url = urlparse.urlunparse((utype, host, path, params, query, ''))
         self.url = url
         fp = None
         is_data = utype == 'data'
         if new_file and type(new_file) == type(''):
             url = MMurl.basejoin(new_file, ourl)
             if is_data:
                 file = None
                 baseurl = new_file
             else:
                 file = baseurl = url
             try:
                 self.filename = url
                 fp = MMurl.urlopen(url)
                 rp = realsupport.RPParser(file, baseurl = baseurl, printfunc = self.printfunc)
                 rp.feed(fp.read())
                 rp.close()
                 fp.close()
                 update = 1
                 # zap the URL so that the
                 # template doesn't get
                 # overwritten
                 node.DelAttr('file')
                 url = self.url = ''
             except:
                 pass
             url = self.url
         else:
             if is_data:
                 file = None
                 baseurl = ''
             else:
                 file = url
                 baseurl = ourl
             try:
                 self.filename = url
                 fp = MMurl.urlopen(url)
                 rp = realsupport.RPParser(file, baseurl = baseurl, printfunc = self.printfunc)
                 rp.feed(fp.read())
                 rp.close()
                 fp.close()
             except:
                 windowinterface.showmessage('Cannot read slideshow file with URL %s in node %s on channel %s' % (url, MMAttrdefs.getattr(node, 'name') or '<unnamed>', node.GetChannelName()), mtype = 'warning')
                 rp = DummyRP()
         if fp is not None:
             fp.close()
         if is_data:
             # zap the URL for "immediate" RP files
             node.DelAttr('file')
             self.url = url = ''
     self.url = url
     self.rp = rp
     attrdict = node.GetAttrDict()
     attrdict['bitrate'] = rp.bitrate
     if rp.width == 0 and rp.height == 0:
         # no size specified, initialize with channel size
         rp.width, rp.height = node.GetChannel().get('base_winoff',(0,0,256,256))[2:4]
     attrdict['size'] = rp.width, rp.height
     attrdict['duration'] = rp.duration
     if rp.aspect != 'true':
         attrdict['aspect'] = 0
     if rp.author is not None:
         attrdict['author'] = rp.author
     if rp.copyright is not None:
         attrdict['copyright'] = rp.copyright
     if rp.maxfps is not None:
         attrdict['maxfps'] = rp.maxfps
     if rp.preroll is not None:
         attrdict['preroll'] = rp.preroll
     if rp.title is not None:
         attrdict['title'] = rp.title
     if rp.url is not None:
         attrdict['href'] = rp.url
         if rp.url not in ctx.externalanchors:
             ctx.externalanchors.append(rp.url)
     for tag in rp.tags:
         if tag.has_key('href') and tag['href'] and \
            tag['href'] not in ctx.externalanchors:
             ctx.externalanchors.append(tag['href'])
     ctx.register(self) # *must* come first
     if update:
         self.update(changed = 1)
Beispiel #4
0
def rpconvert(node, errorfunc = None):
    # convert a RealPix node into a par node with children,
    # together representing the RealPix node
    ctx = node.GetContext()
    # check that node is a RealPix node
    furl = node.GetAttr('file')
    if node.GetType() != 'ext' or not furl:
        if errorfunc is not None: errorfunc('not a RealPix node')
        return
    ch = node.GetChannel()
    if not ch:
        if errorfunc is not None: errorfunc('no region associated with node')
        return
    url = ctx.findurl(furl)
    if furl[:5] == 'data:':
        furl = ''
    try:
        f = MMurl.urlopen(url)
    except IOError:
        if errorfunc is not None: errorfunc('cannot open RealPix file')
        return
    head = f.read(4)
    if head != '<imf':
        if errorfunc is not None: errorfunc('not a RealPix file')
        f.close()
        return

    # parse the RealPix file, result in rp
    rp = realsupport.RPParser(url)
    rp.feed(head)
    rp.feed(f.read())
    f.close()
    rp.close()

    region = ch.GetLayoutChannel()
    regionname = region.name

    em = ctx.editmgr
    if not em.transaction():
        # not allowed to do it at this point
        return

    ctx.attributes['project_boston'] = 1 # It's definitely a SMIL 2.0 document now

    # convert the ext node to a par node
    em.setnodeattr(node, 'file', None)
    em.setnodetype(node, 'seq')
    em.setnodeattr(node, 'channel', None)
    em.setnodeattr(node, 'bgcolor', None)
    em.setnodeattr(node, 'transparent', None)
    if node.GetAttrDef('fill', 'default') == 'default' and node.GetInherAttrDef('fillDefault', 'inherit') == 'inherit':
        # make default fill behavior explicit
        em.setnodeattr(node, 'fill', node.GetFill())
    em.setnodeattr(node, 'fillDefault', 'hold')
    ndur = node.GetAttrDef('duration', None)
    if ndur is None:
        ndur = rp.duration
    else:
        ndur = min(ndur, rp.duration)
    em.setnodeattr(node, 'duration', ndur)
    em.setchannelattr(regionname, 'chsubtype', None)

    # First deal with fadein transitions that specify an
    # associated fadeout.  We just create an explicit fadeout for
    # these associated fadeouts, keeping the list of transitions
    # sorted (and the start attribute relative to the previous).
    # The result is a new list of transitions in tags.
    start = 0
    i = 0
    fadeouts = []
    tags = []
    for tagdict in rp.tags:
        prevstart = start
        start = start + tagdict['start']
        while fadeouts:
            fodict = fadeouts[0]
            if fodict['start'] < start:
                tags.append(fodict)
                fodict['start'], prevstart = fodict['start'] - prevstart, fodict['start']
                del fadeouts[0]
            else:
                break
        tagdict['start'] = start - prevstart
        tags.append(tagdict)
        if tagdict['tag'] == 'fadein' and tagdict.get('fadeout', 0):
            fodict = tagdict.copy()
            fodict['tag'] = 'fadeout'
            fodict['start'] = start + tagdict['fadeouttime']
            fodict['tduration'] = tagdict['fadeoutduration']
            fodict['color'] = tagdict['fadeoutcolor']
            del fodict['fadeouttime']
            del fodict['fadeoutduration']
            del fodict['fadeout']
            del fodict['fadeoutcolor']
            for j in range(len(fadeouts)):
                if fadeouts[j]['start'] > fodict['start']:
                    fadeouts.insert(j, fodict)
                    break
            else:
                fadeouts.append(fodict)
    prevstart = start
    for fodict in fadeouts:
        tags.append(fodict)
        fodict['start'], prevstart = fodict['start'] - prevstart, fodict['start']

    # width and height of the region
    # this had better be in pixels
    rw, rh = region.getPxGeom()[2:]
    i = 0                           # used to create unique channel name
    start = 0
    for tagdict in tags:
        transition = tagdict['tag']
        start = tagdict.get('start', 0) + start
        if transition in ('viewchange', 'animate'):
            if errorfunc is not None: errorfunc("ignoring transition we can't convert")
            continue
        if transition in ('fadeout', 'fill'):
            chtype = 'brush'
            newnode = ctx.newnode('brush')
            em.addnode(node, -1, newnode)
            em.setnodeattr(newnode, 'fgcolor', tagdict['color'])
        else:
            chtype = 'image'
            newnode = ctx.newnode('ext')
            em.addnode(node, -1, newnode)
            em.setnodeattr(newnode, 'file', MMurl.basejoin(furl, tagdict['file']))
            if tagdict.get('aspect', rp.aspect == 'true'):
                em.setnodeattr(newnode, 'fit', 'meet')
            else:
                em.setnodeattr(newnode, 'fit', 'fill')
            base = posixpath.splitext(posixpath.split(tagdict['file'])[1])[0]
            em.setnodeattr(newnode, 'name', base)
            # As this item comes from a RealPix file it should
            # be ready for Real playback
            em.setnodeattr(newnode, 'project_convert', 0)

        # calculate subregion positioning
        # first work in source (RealPix) coordinates
        if tagdict.get('displayfull', 0):
            x, y, w, h = 0, 0, rp.width, rp.height
        else:
            x, y = tagdict.get('subregionxy', (0, 0))
            w, h = tagdict.get('subregionwh', (0, 0))
            # they really default to the size of the window
            if w == 0:
                w = rp.width
            if h == 0:
                h = rp.height
        # if size too big, reduce to RealPix size
        if w > rp.width:
            w = rp.width
        if h > rp.height:
            h = rp.height
        # if the destination area doesn't fit, it is shifted up and left to make it fit
        if x + w > rp.width:
            x = rp.width - w
        if y + h > rp.height:
            y = rp.height - h
        # convert to destination (SMIL 2.0) coordinates
        x = int((float(x) / rp.width) * rw + 0.5)
        w = int((float(w) / rp.width) * rw + 0.5)
        y = int((float(y) / rp.height) * rh + 0.5)
        h = int((float(h) / rp.height) * rh + 0.5)

        em.setnodeattr(newnode, 'left', x)
        em.setnodeattr(newnode, 'top', y)
        em.setnodeattr(newnode, 'width', w)
        em.setnodeattr(newnode, 'height', h)
        em.setnodeattr(newnode, 'regPoint', 'center')
        em.setnodeattr(newnode, 'regAlign', 'center')
        # XXX to be compatible with RealPix, the background
        # should not be transparent and be transitioned in
        # together with the image.  However, that's not so
        # easy in SMIL 2.0.  We'd need a coordinated
        # transition of a brush to represent the background
        # and the image.  For now, just use a transparent
        # background so that it isn't too ugly.
        em.setnodeattr(newnode, 'transparent', 1)
        em.setnodeattr(newnode, 'channel', regionname)
        em.addsyncarc(newnode, 'beginlist', MMSyncArc(newnode, 'begin', srcnode='syncbase', delay=start))
        start = 0
        if transition in ('fadein', 'fadeout', 'crossfade', 'wipe'):
            # the real transtions
            trdict = {'dur': tagdict.get('tduration', 0),
# defaults
##                   'direction': 'forward',
##                   'startProgress': 0.0,
##                   'endProgress': 1.0,
##                   'horzRepeat': 1,
##                   'vertRepeat': 1,
##                   'borderWidth': 0,
# removed from SMIL 2.0
##                   'coordinated': 0,
##                   'clipBoundary': 'children',
                      }
            if transition == 'wipe':
                dir = tagdict['direction']
                if tagdict['wipetype'] == 'normal':
                    trdict['trtype'] = 'barWipe'
                    if dir == 'left':
                        trdict['subtype'] = 'leftToRight'
                        trdict['direction'] = 'reverse'
                    elif dir == 'right':
                        trdict['subtype'] = 'leftToRight'
                    elif dir == 'up':
                        trdict['subtype'] = 'topToBottom'
                        trdict['direction'] = 'reverse'
                    elif dir == 'down':
                        trdict['subtype'] = 'topToBottom'
                else:
                    trdict['trtype'] = 'pushWipe'
                    if dir == 'left':
                        trdict['subtype'] = 'fromRight'
                    elif dir == 'right':
                        trdict['subtype'] = 'fromLeft'
                    elif dir == 'up':
                        trdict['subtype'] = 'fromBottom'
                    elif dir == 'down':
                        trdict['subtype'] = 'fromTop'
            else:
                trdict['trtype'] = 'fade'
            # no point in doing zero-duration transitions
            if trdict['dur'] > 0:
                for trname, trval in ctx.transitions.items():
                    if trval == trdict:
                        # found an existing transition that'll do
                        break
                else:
                    j = 0
                    trname = '%s %d' % (transition, j)
                    while ctx.transitions.has_key(trname):
                        j = j + 1
                        trname = '%s %d' % (transition, j)
                    em.addtransition(trname, trdict)
                em.setnodeattr(newnode, 'transIn', [trname])

        if tagdict.get('href'):
            anchor = ctx.newnode('anchor')
            em.addnode(newnode, -1, anchor)
            em.setnodeattr(anchor, 'sourcePlaystate', 'play')
            em.setnodeattr(anchor, 'destinationPlaystate', 'play')
            em.setnodeattr(anchor, 'show', 'new')
            em.addlink((anchor, tagdict['href'], DIR_1TO2))
    em.commit()