Browse Source

add dvd support through my pydvdread wrapper around libdvdread...

it seems to work, though direct from disk seems to be too slow...

[git-p4: depot-paths = "//depot/": change = 830]
v0.3
John-Mark Gurney 19 years ago
parent
commit
9d5bc2b388
2 changed files with 214 additions and 0 deletions
  1. +213
    -0
      dvd.py
  2. +1
    -0
      pymediaserv

+ 213
- 0
dvd.py View File

@@ -0,0 +1,213 @@
#!/usr/bin/env python

'''DVD Handling'''

import os
import sets

from pydvdread import *

from DIDLLite import StorageFolder, Movie, VideoItem, Resource
from FSStorage import FSObject, registerklassfun

from twisted.python import log, threadable
from twisted.spread import pb
from twisted.web import resource, server

def gennameindexes(pref, item):
ret = []
d = {}
for i, title in enumerate(item):
t = '%s %d (%s)' % (pref, i + 1, title.time)
ret.append(t)
d[t] = i

return ret, d

class DVDChapterTransfer(pb.Viewable):
def __init__(self, iterable, request):
self.iter = iter(iterable)
self.request = request
request.registerProducer(self, 0)

def resumeProducing(self):
if not self.request:
return
# get data and write to request.
try:
data = self.iter.next()
if data:
# this .write will spin the reactor, calling
# .doWrite and then .resumeProducing again, so
# be prepared for a re-entrant call
self.request.write(data)
except StopIteration:
if self.request:
self.request.unregisterProducer()
self.request.finish()
self.request = None

def pauseProducing(self):
pass

def stopProducing(self):
# close zipfile
self.request = None

# Remotely relay producer interface.

def view_resumeProducing(self, issuer):
self.resumeProducing()

def view_pauseProducing(self, issuer):
self.pauseProducing()

def view_stopProducing(self, issuer):
self.stopProducing()

synchronized = ['resumeProducing', 'stopProducing']

threadable.synchronize(DVDChapterTransfer)

class DVDChapterResource(resource.Resource):
isLeaf = True

def __init__(self, chapter):
resource.Resource.__init__(self)

self.chapter = chapter

def getFileSize(self):
return self.chapter.size

def render(self, request):
request.setHeader('content-type', 'video/mpeg')

request.setHeader('content-length', str(self.getFileSize()))
if request.method == 'HEAD':
return ''

# return data
DVDChapterTransfer(self.chapter, request)
# and make sure the connection doesn't get closed
return server.NOT_DONE_YET

class DVDChapter(VideoItem):
def __init__(self, *args, **kwargs):
self.dvdtitle = kwargs['dvdtitle']
self.chapter = kwargs['chapter']
del kwargs['dvdtitle'], kwargs['chapter']

kwargs['content'] = DVDChapterResource(self.chapter)
VideoItem.__init__(self, *args, **kwargs)

self.url = '%s/%s' % (self.cd.urlbase, self.id)
self.res = Resource(self.url, 'http-get:*:video/mpeg:*')
self.res.size = self.chapter.size

def doUpdate(self):
pass

class DVDTitle(StorageFolder):
def __init__(self, *args, **kwargs):
self.dvdtitle = kwargs['dvdtitle']
self.dvddisc = kwargs['dvddisc']
del kwargs['dvdtitle'], kwargs['dvddisc']

StorageFolder.__init__(self, *args, **kwargs)

# mapping from path to objectID
self.pathObjmap = {}

def checkUpdate(self):
self.doUpdate()
#return self.dvddisc.checkUpdate()
return self

def doUpdate(self):
doupdate = False
children, toindex = gennameindexes('Chapter', self.dvdtitle)
children = sets.Set(children)
for i in self.pathObjmap.keys():
if i not in children:
doupdate = True
# delete
self.cd.delItem(self.pathObjmap[i])
del self.pathObjmap[i]

for i in children:
if i in self.pathObjmap:
continue

# new object
self.pathObjmap[i] = self.cd.addItem(self.id,
DVDChapter, i, dvdtitle = self.dvdtitle,
chapter = self.dvdtitle[toindex[i]])
doupdate = True

# sort our children
self.sort(lambda x, y: cmp(x.title, y.title))

if doupdate:
StorageFolder.doUpdate(self)


class DVDDisc(FSObject, StorageFolder):
def __init__(self, *args, **kwargs):
path = kwargs['path']
del kwargs['path']

StorageFolder.__init__(self, *args, **kwargs)
FSObject.__init__(self, path)

# mapping from path to objectID
self.pathObjmap = {}

def doUpdate(self):
# open the DVD as necessary.
self.dvd = DVD(self.FSpath)

doupdate = False
children, toindex = gennameindexes('Title', self.dvd)
children = sets.Set(children)
for i in self.pathObjmap.keys():
if i not in children:
doupdate = True
# delete
self.cd.delItem(self.pathObjmap[i])
del self.pathObjmap[i]

for i in children:
if i in self.pathObjmap:
continue

# new object
self.pathObjmap[i] = self.cd.addItem(self.id, DVDTitle,
i, dvdtitle = self.dvd[toindex[i]], dvddisc = self)
doupdate = True

# sort our children
self.sort(lambda x, y: cmp(x.title, y.title))

if doupdate:
StorageFolder.doUpdate(self)

def detectdvd(path, fobj):
if os.path.isdir(path):
log.msg('dvd isdir')
# Make sure we there is only a VIDEO_TS in there, even
# if there is a VIDEO_TS w/ other files, we will open
# the VIDEO_TS as a DVD (if it is one)
ld = os.listdir(path)
if ld == ['VIDEO_TS' ]:
pass
elif not filter(lambda x: x[:4] != 'VTS_' and
x[:9] != 'VIDEO_TS.', ld):
pass
else:
return None, None

d = DVD(path)
return DVDDisc, { 'path': path }

registerklassfun(detectdvd)

+ 1
- 0
pymediaserv View File

@@ -9,6 +9,7 @@
#

# Modules to import, maybe config file or something?
import dvd
import shoutcast
import ZipStorage # w/ tarfile support, it will gobble up empty files!



Loading…
Cancel
Save