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()?