Bump version
[dcpomatic.git] / hacks / python-playback / film.py
1 import os
2 import subprocess
3 import shlex
4 import shutil
5 import player
6
7 class Film:
8     def __init__(self, data = None):
9         # File or directory containing content
10         self.content = None
11         # True if content is in DVD format
12         self.dvd = False
13         # DVD title number
14         self.dvd_title = 1
15         # Directory containing metadata
16         self.data = None
17         # Film name
18         self.name = None
19         # Number of pixels by which to crop the content from each edge
20         self.left_crop = 0
21         self.top_crop = 0
22         self.right_crop = 0
23         self.bottom_crop = 0
24         # Use deinterlacing filter
25         self.deinterlace = False
26         # Target ratio
27         self.ratio = 1.85
28         # Audio stream ID to play
29         self.aid = None
30
31         self.width = None
32         self.height = None
33         self.fps = None
34         self.length = None
35
36         if data is not None:
37             self.data = data
38             f = open(os.path.join(self.data, 'info'), 'r')
39             while 1:
40                 l = f.readline()
41                 if l == '':
42                     break
43
44                 d = l.strip()
45             
46                 s = d.find(' ')
47                 if s != -1:
48                     key = d[:s]
49                     value = d[s+1:]
50                 
51                     if key == 'name':
52                         self.name = value
53                     elif key == 'content':
54                         self.content = value
55                     elif key == 'dvd':
56                         self.dvd = int(value) == 1
57                     elif key == 'dvd_title':
58                         self.dvd_title = int(value)
59                     elif key == 'left_crop':
60                         self.left_crop = int(value)
61                     elif key == 'top_crop':
62                         self.top_crop = int(value)
63                     elif key == 'right_crop':
64                         self.right_crop = int(value)
65                     elif key == 'bottom_crop':
66                         self.bottom_crop = int(value)
67                     elif key == 'deinterlace':
68                         self.deinterlace = int(value) == 1
69                     elif key == 'ratio':
70                         self.ratio = float(value)
71                     elif key == 'aid':
72                         self.aid = int(value)
73                     elif key == 'width':
74                         self.width = int(value)
75                     elif key == 'height':
76                         self.height = int(value)
77                     elif key == 'fps':
78                         self.fps = float(value)
79                     elif key == 'length':
80                         self.length = float(value)
81
82         if self.width is None or self.height is None or self.fps is None or self.length is None:
83             self.update_content_metadata()
84
85     def write(self):
86         try:
87             os.mkdir(self.data)
88         except OSError:
89             pass
90
91         f = open(os.path.join(self.data, 'info'), 'w')
92         self.write_datum(f, 'name', self.name)
93         self.write_datum(f, 'content', self.content)
94         self.write_datum(f, 'dvd', int(self.dvd))
95         self.write_datum(f, 'dvd_title', self.dvd_title)
96         self.write_datum(f, 'left_crop', self.left_crop)
97         self.write_datum(f, 'top_crop', self.top_crop)
98         self.write_datum(f, 'right_crop', self.right_crop)
99         self.write_datum(f, 'bottom_crop', self.bottom_crop)
100         self.write_datum(f, 'deinterlace', int(self.deinterlace))
101         self.write_datum(f, 'ratio', self.ratio)
102         self.write_datum(f, 'aid', self.aid)
103         self.write_datum(f, 'width', self.width)
104         self.write_datum(f, 'height', self.height)
105         self.write_datum(f, 'fps', self.fps)
106         self.write_datum(f, 'length', self.length)
107
108     def write_datum(self, f, key, value):
109         if value is not None:
110             print >>f,'%s %s' % (key, str(value))
111
112     def thumbs_dir(self):
113         t = os.path.join(self.data, 'thumbs')
114
115         try:
116             os.mkdir(t)
117         except OSError:
118             pass
119
120         return t
121
122     def thumb(self, n):
123         return os.path.join(self.thumbs_dir(), str('%08d.png' % (n + 1)))
124
125     def thumbs(self):
126         return len(os.listdir(self.thumbs_dir()))
127
128     def remove_thumbs(self):
129         shutil.rmtree(self.thumbs_dir())
130
131     def make_thumbs(self):
132         num_thumbs = 128
133         cl = self.player_command_line()
134         if self.length is not None:
135             sstep = self.length / num_thumbs
136         else:
137             sstep = 100
138         cl.extra = '-vo png -frames %d -sstep %d -nosound' % (num_thumbs, sstep)
139         os.chdir(self.thumbs_dir())
140         os.system(cl.get(True))
141
142     def set_dvd(self, d):
143         self.dvd = d
144         self.remove_thumbs()
145
146     def set_dvd_title(self, t):
147         self.dvd_title = t
148         self.remove_thumbs()
149
150     def set_content(self, c):
151         if c == self.content:
152             return
153
154         self.content = c
155         self.update_content_metadata()
156
157     def player_command_line(self):
158         cl = player.CommandLine()
159         cl.dvd = self.dvd
160         cl.dvd_title = self.dvd_title
161         cl.content = self.content
162         return cl
163     
164     def update_content_metadata(self):
165         if self.content is None:
166             return
167
168         self.width = None
169         self.height = None
170         self.fps = None
171         self.length = None
172
173         cl = self.player_command_line()
174         cl.extra = '-identify -vo null -ao null -frames 0'
175         text = subprocess.check_output(shlex.split(cl.get(True))).decode('utf-8')
176         lines = text.split('\n')
177         for l in lines:
178             s = l.strip()
179             b = s.split('=')
180             if len(b) == 2:
181                 if b[0] == 'ID_VIDEO_WIDTH':
182                     self.width = int(b[1])
183                 elif b[0] == 'ID_VIDEO_HEIGHT':
184                     self.height = int(b[1])
185                 elif b[0] == 'ID_VIDEO_FPS':
186                     self.fps = float(b[1])
187                 elif b[0] == 'ID_LENGTH':
188                     self.length = float(b[1])