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