Writing streams into VirtualFileSystems?

I was wondering if its possible to create a VirtualFile that I can continuously write into using a StringStream or perhaps some other representation? I’m trying to HTTP stream a movie from a server and into a texture using loadTexture. An initial test with just writing the file straight into the disc with open() and write() shows some promise but I don’t want the file to be downloaded into the disk so I’m attempting to do it via MountFiles and VirtualFileSystem.

This is my somewhat naive implementation of HTTP streaming onto the disk. For some reason it grabs FLV’s more reliably than Firefox 3 does…

from pandac.PandaModules import HTTPClient
from pandac.PandaModules import Ramfile
from pandac.PandaModules import DocumentSpec

class HTTPStreamFile:

    def __init__(self,url,cachefile=None,cache_extension=None,start_callback=None):
        self.http = HTTPClient()
        self.chan = self.http.makeChannel(True)
        self.chan.beginGetDocument(DocumentSpec(url))
        self.ramFile = Ramfile()
        self.chan.downloadToRam(self.ramFile)
        
        if cachefile == None:
            cacheName = "tmp_%s.%s"%(abs(hash(url)),cache_extension)
            #self.cacheName = "temp.flv"
        else:
            cacheName = "%s.%s"%(cachefile,cache_extension)
        self.cacheFile = open(cacheName,"a",0)
        self.bytesDelta = 0 # A variable for knowing how many bytes to read on the next run()
        
        taskMgr.add(self.downloadTask,"StreamFile")
        
        if start_callback:
            start_callback()
        
    def downloadTask(self,task):
        if self.chan.run():
            print "Downloading ",self.cacheFile.name
            # Compare how many bytes have been downloaded between the two run() calls
            readBytes = self.chan.getBytesDownloaded() - self.bytesDelta
            self.bytesDelta = self.chan.getBytesDownloaded()
            print "Byte Delta:",self.bytesDelta
            print "%s bytes should be read"%readBytes
            
            if readBytes > 0:
                # Read that many bytes and write it to the cacheFile
                appendData = self.ramFile.read(readBytes)
                print "Append data"
                print "Gonk?"
                self.cacheFile.write(appendData)
            
            if readBytes > 0 and self.chan.getFileSize() == self.chan.getBytesDownloaded():
                print "Finished!"
                self.cacheFile.close()
                return task.done
            
            return task.cont

        if not self.chan.isDownloadComplete():
            self.cacheFile.close()
            print "------ ERROR ------"
            return task.done

        print "Finished normally"
        self.cacheFile.close()
        return task.done
    
    def __del__(self):
        if self.cacheFile.closed is False:
            self.cachFile.close()

if __name__ == "__main__":
    import direct.directbase.DirectStart
    file = HTTPStreamFile('http://youtube.com/get_video?video_id=ccWrbGEFgI8&t=OEgsToPDskIIn-88u3x3gIeLjB-OyVkA',cache_extension="flv")
    run()

I’m trying to replicate that model of spooling the Ramimage data into a file but I’m not quite sure how to do it with a VirtualFile. What I have so far while trying it out in the interactive console:

        # Setup the Multifile and StringStream
        self.multifile = Multifile()
        self.streamIn = StringStream() # The iostream that will accept data from the RamFile
        self.multifile.openReadWrite(self.streamIn)
        self.filehash = "%s.%s"%(abs(hash(url)),cache_extension)
        self.multifile.addSubfile(self.filehash,self.streamIn,0)
        vfs = VirtualFileSystem.getGlobalPtr()
        vfs.mount(self.multifile,'.',VirtualFileSystem.MFReadOnly)

So that mounts the multifile into a VirtualFile (I think) but I have no idea how I can modify the contents of that virtualFile dynamically. Is there a VirtualFile equivalent to python’s file.write()?

Wow streaming movies that would be cool!

Panda-tube!

I could have a demo up now with the disk strreamer if MovieTexture support for any of the streaming formats weren’t broken. As of now all 3 formats seem to break when I try them out of the Media Player sample. Mov’s aren’t able to load sound, FLV’s segfault when you try to seek and WMV has a big delay in the video.

Hmm, sounds exciting, though I’ll admit the VirtualFile system isn’t really designed with files that update on-the-fly in mind. I’m not sure if it can be done through that system.

David