diff --git a/.gitignore b/.gitignore index dcc69457f575f7edc667042fe7fe50490462584b..6e4732fa6546bc596175c5adfadd518b2b833c51 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ debian/dcpman.links debian/dcpman.postinst.debhelper debian/dcpman.prerm.debhelper debian/dcpman.substvars -dcpman/__pycache__ -dcpman/ui.py +source/__pycache__ +source/ui.py diff --git a/debian/changelog b/debian/changelog index 53e33ee23c04512001aa91ee48469a1d0a94e148..7061fff666ad0aa175bdd59c472441c9795f9d4e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,12 @@ +dcpman (0.1.1) UNRELEASED; urgency=medium + + * Adding better detection of encrypted DCPs by using avprobe to try and read the mxf files (still not 100% correct). + + -- Nimrod Adar <nimrod@nimrod.private> Mon, 14 Jul 2014 13:11:42 +0300 + dcpman (0.1) UNRELEASED; urgency=medium * Initial release. -- Nimrod Adar <nimrod@shore.co.il> Sun, 29 Jun 2014 16:19:53 +0300 + diff --git a/debian/control b/debian/control index 0a9f0b95ce5112867da125fbd3c596b1e1090dfa..2146d4de4f802c7c76d5fbcf8a1798aed47ffa87 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ X-Python3-Version: >= 3.2 Standards-Version: 3.9.5.0 Package: dcpman -Depends: python3 (>= 3.2), python3-pyqt4 | python3-pyqt5, oxygen-icon-theme +Depends: python3 (>= 3.2), python3-pyqt4 | python3-pyqt5, oxygen-icon-theme, python3-vlc Architecture: all Description: Management tool for Digital Cinema Packages. A tool to manage DCPs (Digital Cinema Packages), although currently it only diff --git a/debian/files b/debian/files index 27911539b7f8e8a7271b66b53962ac94ad5e4e25..bd1ff25a7a11c8c0dcddaceaf962179eaf49b52c 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -dcpman_0.1_all.deb video optional +dcpman_0.1.1_all.deb video optional diff --git a/debian/install b/debian/install index 27ee999344ed45c8cbf4f8863504d0fea91f2b35..348d1a77ed400502f5336d1d8e668af0758c16de 100644 --- a/debian/install +++ b/debian/install @@ -1,2 +1,2 @@ -dcpman/* usr/lib/python3/dist-packages/dcpman -dcpman.desktop usr/share/applications +source/*.py usr/lib/python3/dist-packages/dcpman +source/dcpman.desktop usr/share/applications diff --git a/debian/rules b/debian/rules index d63755bbe7c6bc29a0b329894cfcb402ffdef8e5..2a92017a084f479056d75e00f6745ba26b51dcad 100755 --- a/debian/rules +++ b/debian/rules @@ -1,4 +1,4 @@ #!/usr/bin/make -f %: - pyuic4 dcpman.ui > dcpman/ui.py + pyuic4 source/dcpman.ui > source/ui.py dh $@ --with python3 diff --git a/fabfile.py b/fabfile.py new file mode 100644 index 0000000000000000000000000000000000000000..ae2de68e785fa1576ee1f63d8b381691aeac6865 --- /dev/null +++ b/fabfile.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +from fabric.api import task, local + +@task +def publish (): + build () + for dist in ['wheezy', 'jessie', 'sid']: + local ('''reprepro includedeb ''' + dist + ''' ../dcpman_*.deb''') + +@task +def build (): + local ('''dpkg-buildpackage''') + +@task +def clean () + local ('''rm ../dcpman_*''') diff --git a/dcpman/__init__.py b/source/__init__.py similarity index 100% rename from dcpman/__init__.py rename to source/__init__.py diff --git a/dcpman/dcp.py b/source/dcp.py similarity index 72% rename from dcpman/dcp.py rename to source/dcp.py index d2fd8674e718847f97f32c70f9d7b6d99f0c40bc..cf5a846c6cccf3242f037a005b1443d20fb10f9a 100755 --- a/dcpman/dcp.py +++ b/source/dcp.py @@ -4,6 +4,7 @@ from base64 import b64encode from os import stat, listdir from xml.dom.minidom import parse import sys +import vlc class Asset(object): '''A simple asset that's part of whole DCP package.''' @@ -31,8 +32,15 @@ class Asset(object): hash.update(buffer) buffer = fh.read(buffersize) return(self.hash == b64encode (hash.digest()).decode()) + + def add_duration (self): + if hasattr (self, 'type') and self.type.find ('mxf') > -1: + instance = vlc.Instance () + media = instance.media_new ('file://' + self.fullpath) + media.parse () + self.duration = media.get_duration () - def __init__(self, rootpath, filename, id=None, hash=None, size=None, packinglist=False): + def __init__(self, rootpath, filename, id=None, hash=None, size=None, packinglist=False, type=None): '''Initialize an asset, has to have a filename and path.''' self.rootpath = rootpath if filename[0:8] == 'file:///': @@ -45,6 +53,8 @@ class Asset(object): self.hash = hash if size != None: self.size = size + if type != None: + self.type = type self.packinglist = packinglist @@ -76,35 +86,44 @@ class DCP: asset.filename) from e return True - def __init__(self, directory): - '''Parses the DCP in the directory specified.''' - self.root = directory - if 'ASSETMAP.xml' in listdir(directory): + def _parse_assetmap (self): + '''Adds the asset map file to the list of assets and parses it.''' + if 'ASSETMAP.xml' in listdir(self.directory): filename = 'ASSETMAP.xml' - elif 'ASSETMAP' in listdir(directory): + elif 'ASSETMAP' in listdir(self.directory): filename = 'ASSETMAP' else: raise RuntimeError ('Couldn\'t find assetmap file') - self.assets = [Asset(directory, filename)] + self.assets = [Asset(self.directory, filename, type='text/xml')] assetmap = self.assets[0].fullpath - if 'VOLINDEX.xml' in listdir(directory): - filename = 'VOLINDEX.xml' - elif 'VOLINDEX' in listdir(directory): - filename = 'VOLINDEX' - #else: - #raise RuntimeError ('Couldn\'t find volindex file') - self.assets.append(Asset(directory, filename)) try: assetmap = parse(assetmap).getElementsByTagName('Asset') - self.assets.append(Asset(directory, filename)) + self.assets.append(Asset(self.directory, filename)) for element in assetmap: id = element.getElementsByTagName('Id')[0].firstChild.data id = id.split(':')[-1] filename = element.getElementsByTagName('Path')[0].firstChild.data packinglist = len(element.getElementsByTagName('PackingList')) > 0 - self.assets.append(Asset(directory, filename, id=id, packinglist=packinglist)) + if packinglist: + self.assets.append(Asset(self.directory, filename, id=id, packinglist=packinglist, type='text/xml')) + else: + self.assets.append(Asset(self.directory, filename, id=id, packinglist=packinglist)) except BaseException as e: raise RuntimeError ('Failed to parse assetmap file') from e + + def _add_volindex (self): + '''Adds the volume index file to the list of assets.''' + if 'VOLINDEX.xml' in listdir(self.directory): + filename = 'VOLINDEX.xml' + elif 'VOLINDEX' in listdir(self.directory): + filename = 'VOLINDEX' + else: + #raise RuntimeError ('Couldn\'t find volindex file') + return + self.assets.append(Asset(self.directory, filename, type='text/xml')) + + def _parse_packinglist (self): + '''Parses the packing list.''' try: pkls = (parse(x.fullpath) for x in self.assets if x.packinglist) for pkl in pkls: @@ -119,13 +138,27 @@ class DCP: id = element.getElementsByTagName('Id')[0].firstChild.data id = id.split(':')[-1] hash = element.getElementsByTagName('Hash')[0].firstChild.data + type = element.getElementsByTagName('Type')[0].firstChild.data size = int(element.getElementsByTagName('Size')[0].firstChild.data) asset = [x for x in self.assets if hasattr(x, 'id') and x.id == id][0] asset.hash = hash asset.size = size + asset.type = type + asset.add_duration () except BaseException as e: raise RuntimeError ('Failed to parse packinglist file') from e + def __init__(self, directory): + '''Parses the DCP in the directory specified.''' + self.directory = directory + self._parse_assetmap () + self._add_volindex () + self._parse_packinglist () + try: + self.duration = max ([x.duration for x in self.assets if hasattr (x, 'duration')]) + except: + pass + if __name__ == '__main__': if (len(sys.argv) == 2): @@ -140,6 +173,7 @@ if __name__ == '__main__': print ('DCP is signed') else: print ('DCP is unsigned') + print ('Duration:', dcp.duration) if (dcp.verify()): print ('Verification succeeded.') else: diff --git a/dcpman.desktop b/source/dcpman.desktop similarity index 100% rename from dcpman.desktop rename to source/dcpman.desktop diff --git a/dcpman.ui b/source/dcpman.ui similarity index 91% rename from dcpman.ui rename to source/dcpman.ui index 312d646070275785f35eadb8bd4f0dbce42bebd2..af070f233195789045170bd1ff741ee89c622656 100644 --- a/dcpman.ui +++ b/source/dcpman.ui @@ -19,7 +19,7 @@ <rect> <x>11</x> <y>11</y> - <width>491</width> + <width>501</width> <height>131</height> </rect> </property> @@ -30,7 +30,7 @@ <widget class="QLabel" name="nameLabel"> <property name="minimumSize"> <size> - <width>45</width> + <width>65</width> <height>0</height> </size> </property> @@ -54,20 +54,20 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <widget class="QLabel" name="signedLabel"> + <widget class="QLabel" name="encryptedLabel"> <property name="minimumSize"> <size> - <width>45</width> + <width>65</width> <height>0</height> </size> </property> <property name="text"> - <string>Signed</string> + <string>Encrypted</string> </property> </widget> </item> <item> - <widget class="QLineEdit" name="signedLine"> + <widget class="QLineEdit" name="encryptedLine"> <property name="frame"> <bool>true</bool> </property> @@ -84,7 +84,7 @@ <widget class="QLabel" name="verifyLabel"> <property name="minimumSize"> <size> - <width>45</width> + <width>65</width> <height>0</height> </size> </property> diff --git a/dcpman/manager.py b/source/manager.py similarity index 84% rename from dcpman/manager.py rename to source/manager.py index 9839879d5eb15cf3c2e5c0cbffc27177cdd5b2e7..0aedaa821d9054ceed67796b285fc6dd4e8aaeb8 100755 --- a/dcpman/manager.py +++ b/source/manager.py @@ -1,8 +1,10 @@ #!/usr/bin/env python3 from PyQt4 import QtGui from PyQt4 import QtCore -from dcpman.dcp import DCP -from dcpman import ui #autogenerated file from Qt Designer to setup the window +#from dcpman.dcp import DCP +#from dcpman import ui #autogenerated file from Qt Designer to setup the window +from dcp import DCP +import ui import sys class verifyThread(QtCore.QThread): @@ -51,10 +53,12 @@ if __name__ == '__main__': window.nameLine.setText(dcp.name) except AttributeError: window.nameLine.setText(directory.split('/')[-1]) - if dcp.signed: - window.signedLine.setText('Signed') + if dcp.signed and dcp.duration == 0: + window.encryptedLine.setText('Most likely') + elif dcp.signed or dcp.duration == 0: + window.encryptedLine.setText ('Probably') else: - window.signedLine.setText('Not signed') + window.encryptedLine.setText('Probably not') window.verifyLine.setText('Click button to start verification') window.verifyButton.clicked.connect(verify_in_thread) except BaseException as exception: