Difference between revisions of "Building Plugins:HelloMyth"
(→The UI File) |
(→CPP Files: VERBOSE is apparently deprecated and you should use LOG instead) |
||
(9 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
− | |||
[[Category:HOWTO]] | [[Category:HOWTO]] | ||
[[Category:Developer_Documentation]] | [[Category:Developer_Documentation]] | ||
Line 9: | Line 8: | ||
As a '''disclaimer''', I am also very new to plugin development and so please correct me where I might be wrong. | As a '''disclaimer''', I am also very new to plugin development and so please correct me where I might be wrong. | ||
− | To start, download the | + | To start, download a copy of the MythTV source code repository from [https://github.com/organizations/MythTV github] and create the following directory tree within its: |
<pre> | <pre> | ||
− | + | git clone git://github.com/MythTV/mythtv.git | |
− | mkdir -p mythplugins/mythhello/mythhello | + | mkdir -p mythtv/mythplugins/mythhello/mythhello |
</pre> | </pre> | ||
− | You will also need to install some development tools if you don't already have them ( | + | You will also need to install some development tools if you don't already have them (Qt4 development tools and headers). For example: |
− | <pre>sudo apt-get install qt4-qmake | + | <pre> |
+ | sudo apt-get install qt4-qmake libqt4-dev | ||
</pre> | </pre> | ||
Line 35: | Line 35: | ||
2) Create another file called mythhello.pro in the second mythhello (mythplugins/mythhello/mythhello/mythhello.pro) directory | 2) Create another file called mythhello.pro in the second mythhello (mythplugins/mythhello/mythhello/mythhello.pro) directory | ||
+ | {{Code box|mythhello.pro| | ||
<pre> | <pre> | ||
include ( ../../mythconfig.mak ) | include ( ../../mythconfig.mak ) | ||
include ( ../../settings.pro ) | include ( ../../settings.pro ) | ||
+ | include ( ../../programs-libs.pro ) | ||
+ | |||
QT += network sql xml | QT += network sql xml | ||
TEMPLATE = lib | TEMPLATE = lib | ||
Line 60: | Line 63: | ||
} | } | ||
</pre> | </pre> | ||
+ | }} | ||
+ | {{Note box|In my case also "''include ( ../../programs-libs.pro )''" was needed to compile it}} | ||
− | The following items are specific to your plugin: 'uifiles.files', 'installfiles.files', 'HEADERS', 'SOURCES'. Be sure that $${LIBDIR} and $${PREFIX} are set in mythplugins/mythconfig.mak to be the | + | The following items are specific to your plugin: 'uifiles.files', 'installfiles.files', 'HEADERS', 'SOURCES'. Be sure that $${LIBDIR} and $${PREFIX} are set in mythplugins/mythconfig.mak to be the MythTV install prefix and library directory. Mine are set to: |
<pre> | <pre> | ||
PREFIX=/usr/ | PREFIX=/usr/ | ||
Line 70: | Line 75: | ||
''(Note: I didn't find a mythplugins/mythconfig.mak but adding the above two lines to the top of my mythhello.mak worked to set the paths correctly - using a 0.21 system.)'' | ''(Note: I didn't find a mythplugins/mythconfig.mak but adding the above two lines to the top of my mythhello.mak worked to set the paths correctly - using a 0.21 system.)'' | ||
− | ''(Note2: You can execute the configure script in mythplugins to generate the mythconfig.mak file. Depending on where your | + | ''(Note2: You can execute the configure script in mythplugins to generate the mythconfig.mak file. Depending on where your MythTV is located it may be necessary to add the argument --prefix=/usr)'' |
=== CPP Files === | === CPP Files === | ||
Now we create the cpp/h files which should be put in mythplugins/mythhello/mythhello/. | Now we create the cpp/h files which should be put in mythplugins/mythhello/mythhello/. | ||
− | |||
− | |||
Here's the main file that takes care of initializing, running and destructing the pluigin: | Here's the main file that takes care of initializing, running and destructing the pluigin: | ||
+ | {{Code box|main.cpp| | ||
<pre> | <pre> | ||
Line 154: | Line 158: | ||
} | } | ||
− | |||
− | |||
− | |||
</pre> | </pre> | ||
+ | }} | ||
− | + | {{Code box|mythhello.h| | |
− | |||
<pre> | <pre> | ||
#ifndef MYTHHELLO_H | #ifndef MYTHHELLO_H | ||
Line 199: | Line 200: | ||
</pre> | </pre> | ||
+ | }} | ||
− | + | {{Code box|mythhello.cpp| | |
− | |||
<pre> | <pre> | ||
// POSIX headers | // POSIX headers | ||
Line 231: | Line 232: | ||
//example of how to find the configuration dir currently used. | //example of how to find the configuration dir currently used. | ||
QString confdir = GetConfDir(); | QString confdir = GetConfDir(); | ||
− | + | LOG(VB_GENERAL, LOG_DEBUG, LOC + "Conf dir:" + confdir); | |
} | } | ||
Line 252: | Line 253: | ||
if (err) | if (err) | ||
{ | { | ||
− | + | LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'hello'"); | |
return false; | return false; | ||
} | } | ||
− | + | BuildFocusList(); | |
− | |||
− | |||
− | |||
− | |||
− | |||
SetFocusWidget(m_cancelButton); | SetFocusWidget(m_cancelButton); | ||
Line 271: | Line 267: | ||
return true; | return true; | ||
} | } | ||
+ | |||
bool MythHello::keyPressEvent(QKeyEvent *event) | bool MythHello::keyPressEvent(QKeyEvent *event) | ||
{ | { | ||
Line 306: | Line 303: | ||
m_outText->SetText(QString("Cancel clicked")); | m_outText->SetText(QString("Cancel clicked")); | ||
} | } | ||
− | |||
− | |||
</pre> | </pre> | ||
+ | }} | ||
=== The UI File === | === The UI File === | ||
Line 315: | Line 311: | ||
What would a plugin be without a UI? Now create hello-ui.xml and put it in mythplugins/mythhello/mythhello/. | What would a plugin be without a UI? Now create hello-ui.xml and put it in mythplugins/mythhello/mythhello/. | ||
+ | {{Code box|hello-ui.xml| | ||
<pre> | <pre> | ||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
Line 348: | Line 345: | ||
</pre> | </pre> | ||
+ | }} | ||
=== Building === | === Building === | ||
Line 360: | Line 358: | ||
</pre> | </pre> | ||
− | Make sure everything compiled OK and the files where copied to your | + | Make sure everything compiled OK and the files where copied to your MythTV installation directories. |
{{Note box|For newer versions of MythTV, ''qmake'' should be replaced by ''qmake-qt4''.}} | {{Note box|For newer versions of MythTV, ''qmake'' should be replaced by ''qmake-qt4''.}} | ||
Line 387: | Line 385: | ||
[[MythPlugin Architecture]] | [[MythPlugin Architecture]] | ||
+ | |||
+ | [[Building_Plugins:MythNotes]] - Another plug-in tutorial | ||
[[Category:HOWTO]] | [[Category:HOWTO]] |
Revision as of 19:48, 17 August 2013
Contents
Creating Your First Plugin: Hello Myth
This is a really simple skeleton plugin that doesn't do anything. It'll show you what is absolutely necessary to create a plugin, then you can expand on that by dissecting others.
As a disclaimer, I am also very new to plugin development and so please correct me where I might be wrong.
To start, download a copy of the MythTV source code repository from github and create the following directory tree within its:
git clone git://github.com/MythTV/mythtv.git mkdir -p mythtv/mythplugins/mythhello/mythhello
You will also need to install some development tools if you don't already have them (Qt4 development tools and headers). For example:
sudo apt-get install qt4-qmake libqt4-dev
mythhello.pro Files
The *.pro files are used by qmake to create the Makefiles.
1) Create a file called mythhello.pro in the first mythhello directory:
TEMPLATE = subdirs # Directories SUBDIRS = mythhello
"mythhello" refers to the second mythhello directory.
2) Create another file called mythhello.pro in the second mythhello (mythplugins/mythhello/mythhello/mythhello.pro) directory
include ( ../../mythconfig.mak ) include ( ../../settings.pro ) include ( ../../programs-libs.pro ) QT += network sql xml TEMPLATE = lib CONFIG += plugin thread TARGET = mythhello target.path = $${LIBDIR}/mythtv/plugins INSTALLS += target uifiles.path = $${PREFIX}/share/mythtv/themes/default uifiles.files = hello-ui.xml installfiles.path = $${PREFIX}/share/mythtv installfiles.files = hello-ui.xml INSTALLS += uifiles # Input HEADERS += mythhello.h SOURCES += main.cpp mythhello.cpp macx { QMAKE_LFLAGS += -flat_namespace -undefined suppress }
The following items are specific to your plugin: 'uifiles.files', 'installfiles.files', 'HEADERS', 'SOURCES'. Be sure that $${LIBDIR} and $${PREFIX} are set in mythplugins/mythconfig.mak to be the MythTV install prefix and library directory. Mine are set to:
PREFIX=/usr/ LIBDIR=/usr/lib/
(Note: I didn't find a mythplugins/mythconfig.mak but adding the above two lines to the top of my mythhello.mak worked to set the paths correctly - using a 0.21 system.)
(Note2: You can execute the configure script in mythplugins to generate the mythconfig.mak file. Depending on where your MythTV is located it may be necessary to add the argument --prefix=/usr)
CPP Files
Now we create the cpp/h files which should be put in mythplugins/mythhello/mythhello/.
Here's the main file that takes care of initializing, running and destructing the pluigin:
// C++ headers #include <unistd.h> // QT headers #include <QApplication> // MythTV headers #include <mythcontext.h> #include <mythplugin.h> #include <mythpluginapi.h> #include <mythversion.h> #include <mythmainwindow.h> // MythHello headers #include "mythhello.h" using namespace std; void runHello(void); int RunHello(void); void setupKeys(void) { REG_JUMP("MythHello", QT_TRANSLATE_NOOP("MythHello", "Sample plugin"), "", runHello); } int mythplugin_init(const char *libversion) { if (!gContext->TestPopupVersion("mythhello", libversion, MYTH_BINARY_VERSION)) return -1; setupKeys(); return 0; } void runHello(void) { RunHello(); } int RunHello(void) { MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); MythHello *mythhello = new MythHello(mainStack, "hello"); if (mythhello->Create()) { mainStack->AddScreen(mythhello); return 0; } else { delete mythhello; return -1; } } int mythplugin_run(void) { return RunHello(); } int mythplugin_config(void) { }
#ifndef MYTHHELLO_H #define MYTHHELLO_H // MythTV headers #include <mythscreentype.h> #include <mythuibutton.h> /** \class MythHello * \brief Example plugin. Shows how to use Text areas and buttons */ class MythHello : public MythScreenType { Q_OBJECT public: MythHello(MythScreenStack *parent, QString name); bool Create(void); bool keyPressEvent(QKeyEvent *); private: MythUIText *m_titleText; MythUIText *m_outText; MythUIButton *m_cancelButton; MythUIButton *m_okButton; private slots: void ok_clicked(void); void cancel_clicked(void); }; #endif /* MYTHHELLO_H */
// POSIX headers #include <unistd.h> // MythTV headers #include <mythuibutton.h> #include <mythuitext.h> #include <mythmainwindow.h> #include <mythcontext.h> #include <mythdirs.h> // MythHello headers #include "mythhello.h" #define LOC QString("MythHello: ") #define LOC_WARN QString("MythHello, Warning: ") #define LOC_ERR QString("MythHello, Error: ") /** \brief Creates a new MythHello Screen * \param parent Pointer to the screen stack * \param name The name of the window */ MythHello::MythHello(MythScreenStack *parent, QString name) : MythScreenType(parent, name), m_cancelButton(NULL) { //example of how to find the configuration dir currently used. QString confdir = GetConfDir(); LOG(VB_GENERAL, LOG_DEBUG, LOC + "Conf dir:" + confdir); } bool MythHello::Create(void) { bool foundtheme = false; // Load the theme for this screen foundtheme = LoadWindowFromXML("hello-ui.xml", "hello", this); if (!foundtheme) return false; bool err = false; UIUtilE::Assign(this, m_titleText, "title", &err); UIUtilE::Assign(this, m_outText, "outtext", &err); UIUtilE::Assign(this, m_cancelButton, "cancel", &err); UIUtilE::Assign(this, m_okButton, "ok", &err); if (err) { LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'hello'"); return false; } BuildFocusList(); SetFocusWidget(m_cancelButton); connect(m_okButton, SIGNAL(Clicked()), this, SLOT(ok_clicked())); connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(cancel_clicked())); return true; } bool MythHello::keyPressEvent(QKeyEvent *event) { if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event)) return true; bool handled = false; QStringList actions; handled = GetMythMainWindow()->TranslateKeyPress("Hello", event, actions); for (int i = 0; i < actions.size() && !handled; i++) { QString action = actions[i]; handled = true; if (action == "ESCAPE") Close(); else handled = false; } if (!handled && MythScreenType::keyPressEvent(event)) handled = true; return handled; } void MythHello::ok_clicked(void) { m_outText->SetText(QString("OK clicked")); } void MythHello::cancel_clicked(void) { m_outText->SetText(QString("Cancel clicked")); }
The UI File
What would a plugin be without a UI? Now create hello-ui.xml and put it in mythplugins/mythhello/mythhello/.
<?xml version="1.0" encoding="utf-8"?> <mythuitheme> <window name="hello"> <textarea name="title"> <area>0,10,800,100</area> <font>large</font> <align>allcenter</align> <multiline>yes</multiline> <value>Hello World</value> </textarea> <textarea name="outtext"> <area>0,300,800,100</area> <font>large</font> <align>allcenter</align> <multiline>yes</multiline> </textarea> <button name="cancel" from="basebutton"> <position>500,400</position> <value>Cancel</value> </button> <button name="ok" from="basebutton"> <position>200,400</position> <value>OK</value> </button> </window> </mythuitheme>
Building
Go to the top mythhello directory (mythplugins/mythhello) and run these commands:
su qmake-qt4 make make install
Make sure everything compiled OK and the files where copied to your MythTV installation directories.
Adding MythHello to your Menus
As a final step you have to add your plugin to the main MythTv menu -- in my case /usr/share/mythtv/mainmenu.xml. Add the following anywhere in the XML file between the <mythmenu> root tag:
<button> <type>HELLO_MYTH</type> <text>Hello Myth</text> <action>PLUGIN mythhello</action> </button>
Finishing Up
Now restart MythFrontend and you should see a 'Hello Myth' button on the main menu.
Good Luck
- Mozmonkey
More about plugins
Building_Plugins:MythNotes - Another plug-in tutorial