1 from Plugins.Plugin import PluginDescriptor
4 from enigma import eTimer
6 from Screens.Screen import Screen
7 from Screens.MessageBox import MessageBox
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
17 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
19 config.plugins.dlnaserver = ConfigSubsection()
20 config.plugins.dlnaserver.autostart = ConfigYesNo(default = False)
22 runcherBin = resolveFilename(SCOPE_PLUGINS, "Extensions/DLNAServer/dlnaserver")
25 ps_str = os.popen('ps -ef | grep minidlna | grep -v grep').read()
26 if ps_str.strip() != '':
30 class SelectDirectoryWindow(Screen):
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" />
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"], {
58 self["currentDir"] = Label()
59 self["key_green"] = StaticText(_("OK"))
60 self["key_red"] = StaticText(_("Cancel"))
62 self.onLayoutFinish.append(self.layoutFinished)
64 def layoutFinished(self):
65 self.updateCurrentDirectory()
71 self.close(self["filelist"].getSelection()[0])
75 self.updateCurrentDirectory()
78 self["filelist"].down()
79 self.updateCurrentDirectory()
82 self["filelist"].pageUp()
83 self.updateCurrentDirectory()
86 self["filelist"].pageDown()
87 self.updateCurrentDirectory()
90 if self["filelist"].canDescent():
91 self["filelist"].descent()
92 self.updateCurrentDirectory()
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)
100 class DLNAServer(ConfigListScreen, Screen):
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" />
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" />
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" />
117 def __init__(self, session):
118 self.session = session
119 Screen.__init__(self, session)
123 ConfigListScreen.__init__(self, self.menulist)
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,
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()
141 self.onLayoutFinish.append(self.layoutFinished)
143 self.updateGreenTimer = eTimer()
144 self.updateGreenTimer.timeout.get().append(self.cbGreenTimer)
146 def layoutFinished(self):
147 green_btm_str = 'Start'
149 green_btm_str = 'Stop'
150 self["key_green"].setText(green_btm_str)
151 #self["information"].setText(' ')
153 def cbGreenTimer(self):
154 self.updateGreenTimer.stop()
155 self["information"].setText("")
156 self.layoutFinished()
159 config.plugins.dlnaserver.autostart.save()
163 currentItem = self.getCurrentItem()
164 if currentItem is not None:
165 self.session.openWithCallback(self.cbChangeDirectory, SelectDirectoryWindow, currentItem.value)
169 if self["key_green"].getText().strip() == 'Start':
171 self.saveConfigFile()
172 rc = os.popen('%s %s'%(runcherBin, args)).read()
173 self["information"].setText(rc)
174 self.updateGreenTimer.start(1000)
177 self.saveConfigFile()
178 self["information"].setText('finished saving!!')
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')
186 log_level_list = self.oldConfig.get('log_level').split('=')
188 log_level = log_level_list[1]
189 if log_level != 'off':
191 if log_level not in ('off', 'error', 'warn', 'debug'):
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
203 ConfigListScreen.keyLeft(self)
207 ConfigListScreen.keyRight(self)
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)
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
233 def cbChangeDirectory(self, pathStr):
234 if pathStr is None or pathStr.strip() == '':
237 currentItem = self.getCurrentItem()
238 if currentItem is not None:
239 currentItem.value = pathStr
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'))
253 log_level_list = self.oldConfig.get('log_level').split('=')
255 log_level = log_level_list[1]
256 if log_level != 'off':
258 if log_level not in ('off', 'error', 'warn', 'debug'):
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'))
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)
274 def resetMenuList(self):
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)
288 def writeConfigFile(self, serverName=None, videoDir=None, auditDir=None, pictureDir=None, logDir=None, logLevel='error'):
290 def configDataAppend(origin, key, value):
291 if key.strip() != '' and value.strip() != '':
292 origin += "%s=%s\n" % (key,value)
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'))
314 confFile = file(self.configFileName, 'w')
315 confFile.write(configString)
318 def readConfigFile(self):
319 if not os.path.exists(self.configFileName):
322 for line in file(self.configFileName).readlines():
324 if line == '' or line[0] == '#':
328 k,v = line[:i],line[i+1:]
332 self.oldConfig[k] = v
334 def setDefault(key, default):
336 value = self.oldConfig.get(key)
337 if value == None or value.strip() == '':
338 self.oldConfig[key] = default
339 except: self.oldConfig[key] = default
342 model = os.popen('cat /proc/stb/info/vumodel').read().strip()
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
361 def main(session, **kwargs):
362 session.open(DLNAServer)
364 def autostart(reason, **kwargs):
372 cmd = runcherBin + args
374 if config.plugins.dlnaserver.autostart.value:
376 print "[DLNAServer] already started"
378 print "[DLNAServer] starting ..."
380 elif config.plugins.dlnaserver.autostart.value == False and is_running == True:
381 print "[DLNAServer] stopping ..."
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)]