1 #include <enigma_plugins.h>
14 #include <enigma_lcd.h>
15 #include <enigma_main.h>
16 #include <lib/base/eerror.h>
17 #include <lib/gdi/lcd.h>
18 #include <lib/gdi/font.h>
19 #include <lib/gdi/grc.h>
20 #include <lib/driver/rc.h>
21 #include <lib/driver/streamwd.h>
22 #include <lib/dvb/edvb.h>
23 #include <lib/dvb/decoder.h>
24 #include <lib/gui/eskin.h>
25 #include <lib/gui/eprogress.h>
26 #include <lib/system/info.h>
28 ePluginThread
*ePluginThread::instance
= NULL
;
30 ePlugin::ePlugin(eListBox
<ePlugin
> *parent
, const char *cfgfile
, eSimpleConfigFile
&config
, const char* descr
)
31 : eListBoxEntryText((eListBox
<eListBoxEntryText
>*)parent
)
35 name
= text
= config
.getInfo("name");
38 text
="(" + eString(cfgfile
) + " is invalid)";
40 desc
= config
.getInfo("desc");
47 depend
= config
.getInfo("depend");
49 requires
= config
.getInfo("requires");
50 needfb
= atoi(config
.getInfo("needfb").c_str());
51 needlcd
= atoi(config
.getInfo("needlcd").c_str());
52 needrc
= atoi(config
.getInfo("needrc").c_str());
53 needvtxtpid
= atoi(config
.getInfo("needvtxtpid").c_str());
54 needoffsets
= atoi(config
.getInfo("needoffsets").c_str());
55 version
= atoi(config
.getInfo("pluginversion").c_str());
56 type
= atoi(config
.getInfo("type").c_str());
57 showpig
= atoi(config
.getInfo("pigon").c_str());
59 if (type
== eZapPlugins::ScriptPlugin
)
60 sopath
= eString(cfgfile
).left(strlen(cfgfile
) - 4) + ".sh";
62 sopath
= eString(cfgfile
).left(strlen(cfgfile
) - 4) + ".so";
64 pluginname
= eString(cfgfile
).mid(eString(cfgfile
).rfind('/') + 1);
66 pluginname
= pluginname
.left(pluginname
.length() - 4);
68 eConfig::getInstance()->getKey(eString().sprintf("/enigma/plugins/sortpos/%s",pluginname
.c_str()).c_str(), sortpos
);
72 ePluginContextMenu::ePluginContextMenu(ePlugin
* current_plugin
, int reordering
)
73 : eListBoxWindow
<eListBoxEntryMenu
>(_("Plugin Menu"), 6, 400, true)
75 init_ePluginContextMenu(current_plugin
, reordering
);
77 void ePluginContextMenu::init_ePluginContextMenu(ePlugin
* current_plugin
, int reordering
)
79 eListBoxEntry
*prev
=0;
81 move(ePoint(150, 80));
83 prev
= new eListBoxEntryMenu(&list
, _("disable move mode"), _("switch move mode off"), 0, (void*)1);
85 prev
= new eListBoxEntryMenu(&list
, _("enable move mode"), _("activate mode to simply change the entry order"), 0, (void*)1);
87 if (!::stat64(current_plugin
->cfgname
.c_str(),&s
) && ((s
.st_mode
& S_IWUSR
) == S_IWUSR
))
89 prev
= new eListBoxEntryMenu(&list
, _("rename"), _("rename the selected plugin"), 0,(void*)2);
91 new eListBoxEntryMenuSeparator(&list
, eSkin::getActive()->queryImage("listbox.separator"), 0, true );
92 int ColorButtonsFirst
=0;
93 eConfig::getInstance()->getKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst
);
94 if (ColorButtonsFirst
)
95 prev
= new eListBoxEntryMenu(&list
, _("number buttons first"), _("use number buttons as first shortcuts"),0,(void*)3);
97 prev
= new eListBoxEntryMenu(&list
, _("color buttons first"), _("use color buttons as first shortcuts"),0,(void*)3);
98 list
.setFlags(eListBoxBase::flagHasShortcuts
);
99 CONNECT(list
.selected
, ePluginContextMenu::entrySelected
);
102 void ePluginContextMenu::entrySelected(eListBoxEntryMenu
*test
)
107 close((int)test
->getKey());
110 const char *eZapPlugins::PluginPath
[] = { "/var/tuxbox/plugins/", PLUGINDIR
"/", "" };
112 eZapPlugins::eZapPlugins(Types type
, eWidget
* lcdTitle
, eWidget
* lcdElement
)
113 :eListBoxWindow
<ePlugin
>(type
== StandardPlugin
? _("Plugins") : _("Games"), 8, 400,true), type(type
),reordering(0)
115 setHelpText(_("select plugin and press ok"));
117 setLCD(lcdTitle
, lcdElement
);
119 list
.setFlags(eListBoxBase::flagHasShortcuts
);
120 int ColorButtonsFirst
=0;
121 eConfig::getInstance()->getKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst
);
122 if (ColorButtonsFirst
)
123 list
.setFlags(eListBoxBase::flagColorShortcutsFirst
);
124 CONNECT(list
.selected
, eZapPlugins::selected
);
128 int eZapPlugins::listPlugins(Types type
, std::vector
<eString
> &list
)
131 for (int i
= 0; i
< 2; i
++)
133 DIR *d
= opendir(PluginPath
[i
]);
138 while (struct dirent
*e
= readdir(d
))
140 eString FileName
= e
->d_name
;
141 if (FileName
.find(".cfg") == FileName
.size() - 4)
143 eString cfgname
= (eString(PluginPath
[i
]) + FileName
).c_str();
144 eSimpleConfigFile
config(cfgname
.c_str());
145 if (atoi(config
.getInfo("type").c_str()) == (int)type
)
147 list
.push_back(cfgname
);
157 int eZapPlugins::getAutostartPlugins(std::vector
<eString
> &list
)
159 int cnt
= listPlugins(AutostartPlugin
, list
);
160 for (unsigned int i
= 0; i
< list
.size(); i
++)
162 list
[i
] = list
[i
].left(list
[i
].length() - 4) + ".so";
167 int eZapPlugins::getFileExtensionPlugins(std::vector
<FileExtensionScriptInfo
> &list
)
169 std::vector
<eString
> cfgfilelist
;
170 int cnt
= listPlugins(FileExtensionScriptPlugin
, cfgfilelist
);
171 for (unsigned int i
= 0; i
< cfgfilelist
.size(); i
++)
173 FileExtensionScriptInfo info
;
174 eSimpleConfigFile
config(cfgfilelist
[i
].c_str());
175 info
.file_pattern
= config
.getInfo("pattern");
176 info
.directory_pattern
= config
.getInfo("dirpattern");
177 info
.needfb
= atoi(config
.getInfo("needfb").c_str());
178 info
.needrc
= atoi(config
.getInfo("needrc").c_str());
179 info
.needlcd
= atoi(config
.getInfo("needlcd").c_str());
180 info
.command
= config
.getInfo("command");
181 list
.push_back(info
);
186 int eZapPlugins::find(bool ignore_requires
)
190 std::set
<eString
> exist
;
192 eConfig::getInstance()->getKey("/elitedvb/network/connectionType", connType
);
193 bool hasNetwork
= eSystemInfo::getInstance()->hasNetwork();
196 for ( int i
= 0; i
< 2; i
++ )
198 DIR *d
=opendir(PluginPath
[i
]);
202 err
.sprintf(_("Couldn't read plugin directory %s"), PluginPath
[i
]);
206 eMessageBox
msg(err
, _("Error"), eMessageBox::iconError
|eMessageBox::btOK
);
214 while (struct dirent
*e
=readdir(d
))
216 eString FileName
= e
->d_name
;
217 if (FileName
.find(".cfg") == FileName
.size() - 4)
219 eString cfgname
= (eString(PluginPath
[i
]) + FileName
).c_str();
220 eSimpleConfigFile
config(cfgname
.c_str());
222 int current_type
= (Types
)atoi(config
.getInfo("type").c_str());
224 //Scripts should be treated as normal plugins in this context
225 if (current_type
== ScriptPlugin
)
226 current_type
= StandardPlugin
;
228 if ((type
== AnyPlugin
) || (type
== current_type
))
230 // do not add existing plugins twice
231 if (exist
.find(FileName
) != exist
.end())
234 exist
.insert(FileName
);
235 // check for required specifications
236 eString requires
= config
.getInfo("requires");
237 if (!ignore_requires
)
239 if ((!hasNetwork
) && (requires
.find("network") != eString::npos
))
241 if ((!connType
) && (requires
.find("dsl") != eString::npos
))
244 plg
= new ePlugin(&list
, cfgname
.c_str(), config
);
255 int eZapPlugins::execSelectPrevious(eString
&previous
)
260 previousPlugin
= previous
;
263 if ((type
== StandardPlugin
) && (cnt
== GamePlugin
))
265 selected(list
.getFirst());
269 ePlugin
*it
= list
.getFirst();
272 while (it
->pluginname
!= previous
)
275 if (it
== list
.getFirst()) break;
279 res
=eListBoxWindow
<ePlugin
>::exec();
282 previous
= previousPlugin
;
286 int eZapPlugins::exec()
292 if ((type
== StandardPlugin
) && (cnt
== GamePlugin
))
294 selected(list
.getFirst());
296 list
.setCurrent(list
.getFirst());
298 res
=eListBoxWindow
<ePlugin
>::exec();
304 eString
eZapPlugins::execPluginByName(const char* name
, bool onlySearch
)
309 for ( int i
= 0; i
< 3; i
++ )
313 FILE *fp
=fopen(Path
.c_str(), "rb");
317 eSimpleConfigFile
config(Path
.c_str());
318 ePlugin
p(0, Path
.c_str(), config
);
319 if (ePluginThread::getInstance())
321 eDebug("currently one plugin is running.. dont start another one!!");
322 return _("E: currently another plugin is running...");
329 return eString().sprintf(_("plugin '%s' not found"), name
);
332 return _("E: no name given");
335 void eZapPlugins::execPlugin(ePlugin
* plugin
)
337 if (plugin
->type
== ScriptPlugin
)
339 //The current plugin is a script
340 if ((access(plugin
->sopath
.c_str(), X_OK
) == 0))
343 eScriptOutputWindow
wnd(plugin
);
351 eDebug("can't execute %s",plugin
->sopath
.c_str());
352 eMessageBox
mbox(eString().sprintf(_("Cannot execute %s (check rights)"), plugin
->sopath
.c_str()), (_("Error")), eMessageBox::iconError
| eMessageBox::btOK
, eMessageBox::btOK
, 5);
360 ePluginThread
*p
= new ePluginThread(plugin
, PluginPath
, in_loop
?this:0);
364 class eSetPluginSortOrder
368 eSetPluginSortOrder(): n(0) { }
369 bool operator()(ePlugin
&e
)
372 eConfig::getInstance()->setKey(eString().sprintf("/enigma/plugins/sortpos/%s",e
.pluginname
.c_str()).c_str(), e
.sortpos
);
377 void eZapPlugins::selected(ePlugin
*plugin
)
383 list
.setActiveColor(eSkin::getActive()->queryColor("eServiceSelector.entrySelectedToMove"),gColor(0));
388 list
.setActiveColor(selectedBackColor
,gColor(0));
390 list
.forEachEntry(eSetPluginSortOrder());
394 if (!plugin
|| !plugin
->pluginname
)
400 previousPlugin
= plugin
->pluginname
;
402 void eZapPlugins::toggleMoveMode()
406 selectedBackColor
= list
.getActiveBackColor();
412 void eZapPlugins::renamePlugin()
414 ePlugin
* plugin
= (ePlugin
*)list
.getCurrent();
415 eSimpleConfigFile
config(plugin
->cfgname
.c_str());
416 TextEditWindow
wnd(_("Enter new name for the plugin:"));
417 wnd
.setText(_("Rename plugin"));
419 wnd
.setEditText(config
.getInfo("name"));
420 int ret
= wnd
.exec();
422 if ( !ret
&& config
.getInfo("name") != wnd
.getEditText())
424 config
.setInfo("name",wnd
.getEditText().c_str());
425 config
.Save(plugin
->cfgname
.c_str());
426 plugin
->SetText(wnd
.getEditText());
430 void eZapPlugins::showContextMenu()
432 ePluginContextMenu
m((ePlugin
*)list
.getCurrent(), reordering
);
437 int ColorButtonsFirst
=0;
440 case 1: // enable/disable movemode
443 case 2: // rename plugin
447 eConfig::getInstance()->getKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst
);
448 ColorButtonsFirst
= 1-ColorButtonsFirst
;
449 eConfig::getInstance()->setKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst
);
450 if (ColorButtonsFirst
)
451 list
.setFlags(eListBoxBase::flagColorShortcutsFirst
);
453 list
.removeFlags(eListBoxBase::flagColorShortcutsFirst
);
461 int eZapPlugins::eventHandler(const eWidgetEvent
&event
)
465 case eWidgetEvent::evtAction
:
466 if (list
.eventHandlerShortcuts(event
))
468 else if (event
.action
== &i_cursorActions
->cancel
)
470 else if (event
.action
== &i_shortcutActions
->menu
)
478 return eWindow::eventHandler(event
);
482 PluginParam
*ePluginThread::first
= NULL
, *ePluginThread::tmp
= NULL
;
484 void ePluginThread::MakeParam(const char * const id
, int val
)
486 PluginParam
* p
= new PluginParam
;
493 sprintf(buf
, "%i", val
);
494 p
->val
= new char[strlen(buf
)+1];
504 void ePluginThread::start()
506 wasVisible
= wnd
? wnd
->isVisible() : 0;
508 if (!thread_running())
519 strcpy(depstring
, depend
.c_str());
529 for ( int i
=0; i
< 3; i
++ )
533 str
.assign( p
, np
-p
);
537 FILE *fp
=fopen((eString(PluginPath
[i
])+str
).c_str(), "rb");
541 argv
[argc
++] = eString(PluginPath
[i
])+str
;
552 eDebug("pluginname is %s %d", pluginname
.c_str(), wasVisible
);
554 for (i
=0; i
<argc
; i
++)
556 eDebug("loading %s" , argv
[i
].c_str());
557 libhandle
[i
]=dlopen(argv
[i
].c_str(), RTLD_GLOBAL
|RTLD_NOW
);
560 const char *de
=dlerror();
562 eMessageBox
msg(de
, "plugin loading failed", eMessageBox::btOK
, eMessageBox::btOK
, 5 );
569 if (i
<argc
) // loading of one dependencie failed... close the other
572 dlclose(libhandle
[--i
]);
578 // this is ugly code.. but i have no other idea to detect enigma plugins..
579 bool isEnigmaPlugin
=false;
580 int fd
= open(sopath
.c_str(), O_RDONLY
);
584 while(!isEnigmaPlugin
)
586 int rd
= ::read(fd
, buf
, 8192);
587 for (int i
=0; i
< rd
-15; ++i
)
589 if (!strcmp(buf
+i
, "_ZN7eWidgetD0Ev"))
598 eDebug("would exec (%s) plugin %s",
599 isEnigmaPlugin
? "ENIGMA" : "NORMAL",
602 PluginExec execPlugin
= (PluginExec
) dlsym(libhandle
[i
-1], "plugin_exec");
604 // show messagebox.. and close after 5 seconds...
606 eMessageBox
msg("The symbol plugin_exec was not found. sorry.", "plugin executing failed", eMessageBox::btOK
, eMessageBox::btOK
, 5 );
614 MakeParam(P_ID_RCINPUT
, eRCInput::getInstance()->lock());
620 if (needlcd
&& eSystemInfo::getInstance()->hasLCD())
621 MakeParam(P_ID_LCD
, eDBoxLCD::getInstance()->lock() );
626 if(Decoder::current
.tpid
==-1)
627 MakeParam(P_ID_VTXTPID
, 0);
629 MakeParam(P_ID_VTXTPID
, Decoder::current
.tpid
);
630 // stop teletext subtitles, if activated
631 eSubtitleWidget
*i
= eSubtitleWidget::getInstance();
633 // stop vtxt reinsertion
634 tpid
= Decoder::current
.tpid
;
637 eDebug("stop vtxt reinsertion");
638 Decoder::parms
.tpid
=-1;
644 MakeParam(P_ID_FBUFFER
, fbClass::getInstance()->lock());
648 int left
=20, top
=20, right
=699, bottom
=555;
649 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/left", left
);
650 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/top", top
);
651 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/right", right
);
652 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/bottom", bottom
);
653 MakeParam(P_ID_OFF_X
, left
);
654 MakeParam(P_ID_OFF_Y
, top
);
655 MakeParam(P_ID_END_X
, right
);
656 MakeParam(P_ID_END_Y
, bottom
);
659 /* for(PluginParam *par = first; par; par=par->next )
661 printf ("id: %s - val: %s\n", par->id, par->val);
662 printf("%p\n", par->next);
665 if ( isEnigmaPlugin
)
667 eDebug("start plugin in current thread");
673 eDebug("start plugin thread...");
674 run(); // start thread
680 eDebug("don't start plugin.. another one is running");
683 void ePluginThread::thread()
685 if ( thread_running() )
686 eDebug("plugin thread running.. execute plugin now");
688 eDebug("execute plugin now");
689 PluginExec execPlugin
= (PluginExec
) dlsym(libhandle
[argc
-1], "plugin_exec");
691 eDebug("execute plugin finished");
694 void ePluginThread::recv_msg(const int &)
699 void ePluginThread::thread_finished()
704 void ePluginThread::finalize_plugin()
707 dlclose(libhandle
[--argc
]);
709 while (first
) // Parameter Liste freigegeben
712 delete [] first
->val
;
718 fbClass::getInstance()->unlock();
721 if (needlcd
&& eSystemInfo::getInstance()->hasLCD())
723 eDBoxLCD::getInstance()->unlock();
724 eZapLCD::getInstance()->invalidate();
732 eRCInput::getInstance()->unlock();
736 // start teletext subtitles, if activated
737 eSubtitleWidget
*i
= eSubtitleWidget::getInstance();
738 if (i
) i
->startttx(-1);
739 // start vtxt reinsertion
740 if (tpid
!= -1 && Decoder::current
.tpid
== -1)
742 eDebug("restart vtxt reinsertion");
743 Decoder::parms
.tpid
= tpid
;
750 eScriptOutputWindow::eScriptOutputWindow(ePlugin
*plugin
):
753 cresize(eSize(580, 420));
755 setText(eString().sprintf(_("Output from %s"), plugin
->sopath
.c_str()));
757 scrollbar
= new eProgress(this);
758 scrollbar
->setName("scrollbar");
759 scrollbar
->setStart(0);
760 scrollbar
->setPerc(100);
761 scrollbar
->move(ePoint(width() - 30, 5));
762 scrollbar
->resize(eSize(20, height() - 100));
763 scrollbar
->setProperty("direction", "1");
765 visible
= new eWidget(this);
766 visible
->setName("visible");
767 visible
->move(ePoint(10, 5));
768 visible
->resize(eSize(width() - 40, height() - 100));
770 label
= new eLabel(visible
);
771 label
->setFlags(RS_WRAP
);
772 float lineheight
= fontRenderClass::getInstance()->getLineHeight(label
->getFont());
773 int lines
= (int) (visible
->getSize().height() / lineheight
);
774 pageHeight
= (int) (lines
* lineheight
);
775 visible
->resize(eSize(visible
->getSize().width(), pageHeight
+ (int) (lineheight
/ 6)));
776 label
->resize(eSize(visible
->getSize().width(), pageHeight
* 16));
779 label
->move(ePoint(0, 0));
780 label
->setText(eString().sprintf(_("Executing %s. Please wait..."), plugin
->sopath
.c_str()));
781 script
= new eConsoleAppContainer(plugin
->sopath
);
782 if (!script
->running())
783 label
->setText(eString().sprintf(_("Could not execute %s"), plugin
->sopath
.c_str()));
786 eDebug("%s started", plugin
->sopath
.c_str());
787 CONNECT(script
->dataAvail
, eScriptOutputWindow::getData
);
788 CONNECT(script
->appClosed
, eScriptOutputWindow::scriptClosed
);
796 int eScriptOutputWindow::eventHandler(const eWidgetEvent
& event
)
800 case eWidgetEvent::evtAction
:
801 if (total
&& event
.action
== &i_cursorActions
->up
)
803 ePoint curPos
= label
->getPosition();
806 label
->move(ePoint(curPos
.x(), curPos
.y() + pageHeight
));
810 else if (total
&& event
.action
== &i_cursorActions
->down
)
812 ePoint curPos
= label
->getPosition();
813 if ((total
- pageHeight
) >= abs(curPos
.y() - pageHeight
))
815 label
->move(ePoint(curPos
.x(), curPos
.y() - pageHeight
));
819 else if (event
.action
== &i_cursorActions
->cancel
)
827 return eWindow::eventHandler(event
);
830 void eScriptOutputWindow::updateScrollbar()
834 while (total
< label
->getExtend().height())
840 int start
= -label
->getPosition().y() * 100 / total
;
841 int vis
= pageHeight
* 100 / total
;
842 scrollbar
->setParams(start
, vis
);
849 void eScriptOutputWindow::getData(eString str
)
854 void eScriptOutputWindow::scriptClosed(int state
)
862 label
->move(ePoint(0, 0));
863 label
->setText(scriptOutput
);
866 scriptOutput
.clear();
869 eScriptOutputWindow::~eScriptOutputWindow()
873 if (script
->running())