Support turbo2.
[vuplus_dvbapp] / lib / python / Plugins / Extensions / DLNAServer / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2
3 import os
4 from enigma import eTimer
5
6 from Screens.Screen import Screen
7 from Screens.MessageBox import MessageBox
8
9 from Components.Button import Button
10 from Components.Label import Label
11 from Components.ConfigList import ConfigListScreen
12 from Components.Sources.StaticText import StaticText
13 from Components.ActionMap import NumberActionMap, ActionMap
14 from Components.config import config, ConfigSelection, getConfigListEntry, ConfigText, ConfigDirectory, ConfigYesNo, ConfigSubsection
15 from Components.FileList import FileList
16
17 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
18
19 config.plugins.dlnaserver = ConfigSubsection()
20 config.plugins.dlnaserver.autostart = ConfigYesNo(default = False)
21
22 runcherBin = resolveFilename(SCOPE_PLUGINS, "Extensions/DLNAServer/dlnaserver")
23
24 def isRunning():
25         ps_str = os.popen('ps -ef | grep minidlna | grep -v grep').read()
26         if ps_str.strip() != '':
27                 return True
28         return False
29
30 class SelectDirectoryWindow(Screen):
31         skin =  """
32                 <screen name="SelectDirectoryWindow" position="center,center" size="560,320" title="Select Directory">
33                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
34                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
35                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
36                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
37                         <widget name="currentDir" position="10,60" size="530,22" valign="center" font="Regular;22" />
38                         <widget name="filelist" position="0,100" zPosition="1" size="560,220" scrollbarMode="showOnDemand"/>
39                         <widget render="Label" source="key_red" position="0,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;20" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
40                         <widget render="Label" source="key_green" position="140,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;20" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
41                 </screen>
42                 """
43         def __init__(self, session, currentDir):
44                 Screen.__init__(self, session)
45                 inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/lib", "/proc", "/sbin", "/sys", "/usr", "/var"]
46                 self["filelist"] = FileList(currentDir, showDirectories = True, showFiles = False, inhibitMounts=[], inhibitDirs=inhibitDirs)
47                 self["actions"]  = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"], {
48                         "back"  : self.cancel,
49                         "left"  : self.left,
50                         "right" : self.right,
51                         "up"    : self.up,
52                         "down"  : self.down,
53                         "ok"    : self.ok,
54                         "green" : self.green,
55                         "red"   : self.cancel
56                 }, -1)
57
58                 self["currentDir"] = Label()
59                 self["key_green"]  = StaticText(_("OK"))
60                 self["key_red"]    = StaticText(_("Cancel"))
61
62                 self.onLayoutFinish.append(self.layoutFinished)
63
64         def layoutFinished(self):
65                 self.updateCurrentDirectory()
66
67         def cancel(self):
68                 self.close(None)
69
70         def green(self):
71                 self.close(self["filelist"].getSelection()[0])
72
73         def up(self):
74                 self["filelist"].up()
75                 self.updateCurrentDirectory()
76
77         def down(self):
78                 self["filelist"].down()
79                 self.updateCurrentDirectory()
80
81         def left(self):
82                 self["filelist"].pageUp()
83                 self.updateCurrentDirectory()
84
85         def right(self):
86                 self["filelist"].pageDown()
87                 self.updateCurrentDirectory()
88
89         def ok(self):
90                 if self["filelist"].canDescent():
91                         self["filelist"].descent()
92                         self.updateCurrentDirectory()
93
94         def updateCurrentDirectory(self):
95                 currentDir = self["filelist"].getSelection()[0]
96                 if currentDir is None or currentDir.strip() == '':
97                         currentDir = "Invalid Location"
98                 self["currentDir"].setText(currentDir)
99
100 class DLNAServer(ConfigListScreen, Screen):
101         skin=   """
102                 <screen position="center,center" size="600,350" title="DLNA Server">
103                         <ePixmap pixmap="skin_default/buttons/red.png" position="5,0" size="140,40" alphatest="on" />
104                         <ePixmap pixmap="skin_default/buttons/green.png" position="155,0" size="140,40" alphatest="on" />
105                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,0" size="140,40" alphatest="on" />
106                         <ePixmap pixmap="skin_default/buttons/blue.png" position="455,0" size="140,40" alphatest="on" />
107
108                         <widget source="key_red" render="Label" position="5,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
109                         <widget source="key_green" render="Label" position="155,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
110                         <widget source="key_yellow" render="Label" position="305,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" foregroundColor="#ffffff" transparent="1" />
111                         <widget source="key_blue" render="Label" position="455,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
112
113                         <widget name="config" position="0,50" size="600,200" scrollbarMode="showOnDemand" />
114                         <widget name="information" position="0,250" size="600,100" valign="center" font="Regular;20" />
115                 </screen>
116                 """
117         def __init__(self, session): 
118                 self.session = session
119                 Screen.__init__(self, session)
120
121                 self.oldConfig = {}
122                 self.menulist = []
123                 ConfigListScreen.__init__(self, self.menulist)
124
125                 self.configFileName = "/etc/minidlna.conf"
126                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ], {
127                         "red"    : self.keyExit,
128                         "green"  : self.keyGreen,
129                         "blue"   : self.keyBlue,
130                         "yellow" : self.keyYellow,
131                         "cancel" : self.keyExit,
132                         "ok"     : self.keyOK
133                 }, -2)
134                 self["key_red"]     = StaticText(_("Exit"))
135                 self["key_green"]   = StaticText(_("Start"))
136                 self["key_yellow"]  = StaticText(_("Save"))
137                 self["key_blue"]    = StaticText(_("Reset"))
138                 self["information"] = Label()
139
140                 self.makeMenuEntry()
141                 self.onLayoutFinish.append(self.layoutFinished)
142
143                 self.updateGreenTimer = eTimer()
144                 self.updateGreenTimer.timeout.get().append(self.cbGreenTimer)
145
146         def layoutFinished(self):
147                 green_btm_str = 'Start'
148                 if isRunning():
149                         green_btm_str = 'Stop'
150                 self["key_green"].setText(green_btm_str)
151                 #self["information"].setText(' ')
152
153         def cbGreenTimer(self):
154                 self.updateGreenTimer.stop()
155                 self["information"].setText("")
156                 self.layoutFinished()
157
158         def keyExit(self):
159                 config.plugins.dlnaserver.autostart.save()
160                 self.close()
161         
162         def keyOK(self):
163                 currentItem  = self.getCurrentItem()
164                 if currentItem is not None:
165                         self.session.openWithCallback(self.cbChangeDirectory, SelectDirectoryWindow, currentItem.value)
166
167         def keyGreen(self):
168                 args = '-e'
169                 if self["key_green"].getText().strip() == 'Start':
170                         args = '-s'
171                         self.saveConfigFile()
172                 rc = os.popen('%s %s'%(runcherBin, args)).read()
173                 self["information"].setText(rc)
174                 self.updateGreenTimer.start(1000)
175
176         def keyYellow(self):
177                 self.saveConfigFile()
178                 self["information"].setText('finished saving!!')
179
180         def keyBlue(self):
181                 self.menuItemServerName.value = self.oldConfig.get('friendly_name')
182                 self.menuItemVideoDir.value   = self.oldConfig.get('media_dirV')
183                 self.menuItemMusicDir.value   = self.oldConfig.get('media_dirA')
184                 self.menuItemPictureDir.value = self.oldConfig.get('media_dirP')
185
186                 log_level_list = self.oldConfig.get('log_level').split('=')
187                 enable_log = False
188                 log_level  = log_level_list[1]
189                 if log_level != 'off':
190                         enable_log = True
191                 if log_level not in ('off', 'error', 'warn', 'debug'):
192                         log_level = 'error'
193                 self.menuItemEnableLog.value = enable_log
194                 self.menuItemLogLevel.value  = log_level
195                 self.menuItemLogDir.value    = self.oldConfig.get('log_dir')
196                 config.plugins.dlnaserver.autostart.value = False
197                 self.resetMenuList()
198
199         def keyRed(self):
200                 self.keyExit()
201
202         def keyLeft(self):
203                 ConfigListScreen.keyLeft(self)
204                 self.resetMenuList()
205
206         def keyRight(self):
207                 ConfigListScreen.keyRight(self)
208                 self.resetMenuList()
209
210         def saveConfigFile(self):
211                 serverName = self.menuItemServerName.value
212                 videoDir   = self.menuItemVideoDir.value
213                 auditDir   = self.menuItemMusicDir.value
214                 pictureDir = self.menuItemPictureDir.value
215                 logDir     = self.menuItemLogDir.value
216                 logLevel   = self.menuItemLogLevel.value
217                 if not self.menuItemEnableLog.value:
218                         logDir,logLevel = None, None
219                 self.writeConfigFile(serverName=serverName, videoDir=videoDir, auditDir=auditDir, pictureDir=pictureDir, logDir=logDir, logLevel=logLevel)
220
221         def getCurrentItem(self):
222                 currentEntry = self["config"].getCurrent()
223                 if currentEntry == self.menuEntryVideoDir:
224                         return self.menuItemVideoDir
225                 elif currentEntry == self.menuEntryMusicDir:
226                         return self.menuItemMusicDir
227                 elif currentEntry == self.menuEntryPictureDir:
228                         return self.menuItemPictureDir
229                 elif currentEntry == self.menuEntryLogDir:
230                         return self.menuItemLogDir
231                 return None
232
233         def cbChangeDirectory(self, pathStr):
234                 if pathStr is None or pathStr.strip() == '':
235                         return
236
237                 currentItem  = self.getCurrentItem()
238                 if currentItem is not None:
239                         currentItem.value = pathStr
240
241         def makeMenuEntry(self):
242                 self.readConfigFile()
243                 if not os.path.exists('/media/dlna'):
244                         os.system('mkdir -p /media/dlna/.minidlna/')
245                         os.system('mkdir -p /media/dlna/Videos/')
246                         os.system('mkdir -p /media/dlna/Musics/')
247                         os.system('mkdir -p /media/dlna/Pictures/')
248                 self.menuItemServerName = ConfigText(default=self.oldConfig.get('friendly_name'))
249                 self.menuItemVideoDir   = ConfigDirectory(default = self.oldConfig.get('media_dirV'))
250                 self.menuItemMusicDir   = ConfigDirectory(default = self.oldConfig.get('media_dirA'))
251                 self.menuItemPictureDir = ConfigDirectory(default = self.oldConfig.get('media_dirP'))
252
253                 log_level_list = self.oldConfig.get('log_level').split('=')
254                 enable_log = False
255                 log_level  = log_level_list[1]
256                 if log_level != 'off':
257                         enable_log = True
258                 if log_level not in ('off', 'error', 'warn', 'debug'):
259                         log_level = 'error'
260                 self.menuItemEnableLog = ConfigYesNo(default = enable_log)
261                 self.menuItemLogLevel  = ConfigSelection(default = log_level, choices = [("off", _("off")), ("error", _("error")), ("warn", _("warn")), ("debug", _("debug"))])
262                 self.menuItemLogDir    = ConfigDirectory(default = self.oldConfig.get('log_dir'))
263
264                 self.menuEntryServerName = getConfigListEntry(_("Server Name"), self.menuItemServerName)
265                 self.menuEntryVideoDir   = getConfigListEntry(_("Video Directory"), self.menuItemVideoDir)
266                 self.menuEntryMusicDir   = getConfigListEntry(_("Music Directory"), self.menuItemMusicDir)
267                 self.menuEntryPictureDir = getConfigListEntry(_("Picture Directory"), self.menuItemPictureDir)
268                 self.menuEntryEnableLog  = getConfigListEntry(_("Enable Logging"), self.menuItemEnableLog)
269                 self.menuEntryLogLevel   = getConfigListEntry(_("    - Log Level"), self.menuItemLogLevel)
270                 self.menuEntryLogDir     = getConfigListEntry(_("    - Log Directory"), self.menuItemLogDir)
271                 self.menuEntryAutoStart  = getConfigListEntry(_("Enable Autostart for DLNA Server"), config.plugins.dlnaserver.autostart)
272                 self.resetMenuList()
273
274         def resetMenuList(self):
275                 self.menulist = []
276                 self.menulist.append(self.menuEntryServerName)
277                 self.menulist.append(self.menuEntryVideoDir)
278                 self.menulist.append(self.menuEntryMusicDir)
279                 self.menulist.append(self.menuEntryPictureDir)
280                 self.menulist.append(self.menuEntryEnableLog)
281                 if self.menuItemEnableLog.value:
282                         self.menulist.append(self.menuEntryLogLevel)
283                         self.menulist.append(self.menuEntryLogDir)
284                 self.menulist.append(self.menuEntryAutoStart)
285                 self["config"].list = self.menulist
286                 self["config"].l.setList(self.menulist)
287
288         def writeConfigFile(self, serverName=None, videoDir=None, auditDir=None, pictureDir=None, logDir=None, logLevel='error'):
289                 configString = ""
290                 def configDataAppend(origin, key, value):
291                         if key.strip() != '' and value.strip() != '':
292                                 origin += "%s=%s\n" % (key,value)
293                         return origin
294                 configString = configDataAppend(configString, "friendly_name", serverName)
295                 if videoDir is not None and videoDir.strip() != '':
296                         configString = configDataAppend(configString, "media_dir", "V,%s"%(videoDir))
297                 if auditDir is not None and auditDir.strip() != '':
298                         configString = configDataAppend(configString, "media_dir", "A,%s"%(auditDir))
299                 if pictureDir is not None and pictureDir.strip() != '':
300                         configString = configDataAppend(configString, "media_dir", "P,%s"%(pictureDir))
301                 if logDir is not None and logDir.strip() != '':
302                         configString = configDataAppend(configString, "log_dir", logDir)
303                         configString = configDataAppend(configString, "log_level", "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=%s"%(logLevel))
304                 configString = configDataAppend(configString, "port", self.oldConfig.get('port'))
305                 configString = configDataAppend(configString, "db_dir", self.oldConfig.get('db_dir'))
306                 configString = configDataAppend(configString, "album_art_names", self.oldConfig.get('album_art_names'))
307                 configString = configDataAppend(configString, "inotify", self.oldConfig.get('inotify'))
308                 configString = configDataAppend(configString, "enable_tivo", self.oldConfig.get('enable_tivo'))
309                 configString = configDataAppend(configString, "strict_dlna", self.oldConfig.get('strict_dlna'))
310                 configString = configDataAppend(configString, "notify_interval", self.oldConfig.get('notify_interval'))
311                 configString = configDataAppend(configString, "serial", self.oldConfig.get('serial'))
312                 configString = configDataAppend(configString, "model_number", self.oldConfig.get('model_number'))
313                 print configString
314                 confFile = file(self.configFileName, 'w')
315                 confFile.write(configString)
316                 confFile.close()
317
318         def readConfigFile(self):
319                 if not os.path.exists(self.configFileName):
320                         return
321                 self.oldConfig = {}
322                 for line in file(self.configFileName).readlines():
323                         line = line.strip()
324                         if line == '' or line[0] == '#':
325                                 continue
326                         try:
327                                 i   = line.find('=')
328                                 k,v = line[:i],line[i+1:]
329                                 if k == 'media_dir':
330                                         k += v[0]
331                                         v  = v[2:]
332                                 self.oldConfig[k] = v
333                         except : pass
334                 def setDefault(key, default):
335                         try:
336                                 value = self.oldConfig.get(key)
337                                 if value == None or value.strip() == '':
338                                         self.oldConfig[key] = default
339                         except: self.oldConfig[key] = default
340                         
341                 try:
342                         model = os.popen('cat /proc/stb/info/vumodel').read().strip()
343                 except: model = 'My'
344                 setDefault('friendly_name', '%s DLNA Server'%(model.upper()))
345                 setDefault('media_dirV', '/media/dlna/Videos')
346                 setDefault('media_dirA', '/media/dlna/Musics')
347                 setDefault('media_dirP', '/media/dlna/Pictures')
348                 setDefault('log_dir', '/media/dlna/.minidlnalog')
349                 setDefault('log_level', 'general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=error')
350                 setDefault('port', '8200')
351                 setDefault('db_dir', '/var/cache/minidlna')
352                 setDefault('album_art_names', 'Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg')
353                 setDefault('inotify', 'yes')
354                 setDefault('enable_tivo', 'no')
355                 setDefault('strict_dlna', 'no')
356                 setDefault('notify_interval', '900')
357                 setDefault('serial', '12345678')
358                 setDefault('model_number', '1')
359                 print "Current Config : ", self.oldConfig
360
361 def main(session, **kwargs):
362         session.open(DLNAServer)
363
364 def autostart(reason, **kwargs):
365         if reason == 0:
366                 if isRunning():
367                         args = " -e"
368                         is_running = True
369                 else:
370                         args = " -s"
371                         is_running = False
372                 cmd = runcherBin + args
373
374                 if config.plugins.dlnaserver.autostart.value:
375                         if is_running:
376                                 print "[DLNAServer] already started"
377                         else:
378                                 print "[DLNAServer] starting ..."
379                                 os.system(cmd)
380                 elif config.plugins.dlnaserver.autostart.value == False and is_running == True:
381                                 print "[DLNAServer] stopping ..."
382                                 os.system(cmd)
383
384 def Plugins(**kwargs):
385         return [PluginDescriptor(name="DLNA Server", description="This is dlna server using minidlna.", where = PluginDescriptor.WHERE_PLUGINMENU, needsRestart = False, fnc=main),
386                 PluginDescriptor(where = [PluginDescriptor.WHERE_AUTOSTART], fnc = autostart)]