Difference between revisions of "Building Plugins:HelloMyth"

From MythTV Official Wiki
Jump to: navigation, search
(mythhello.pro Files)
 
(47 intermediate revisions by 19 users not shown)
Line 8: 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 mythplugin directory from [http://svn.mythtv.org/trac/ SVN] and create the following directory tree within its:
+
Before you start you may need to install some development tools if you don't already have them (Qt5 development tools and headers) (For reference you can see a full list of dependencies the Ubuntu packaging needs to build [https://github.com/MythTV/packaging/blob/fixes/31/deb/debian/control#L11 here]. For example:
 +
<pre>
 +
sudo apt-get install qt5-qmake libqt5-dev ccache git g++ libmyth-dev
 +
</pre>
 +
 
 +
NOTE: a quick way for those using Ubuntu to install all the required build dependencies is to use this (you will have to find and uncomment the correct '''deb-src''' line from /etc/apt/sources.list.d/ for this to work):
 +
<pre>
 +
sudo apt-get build-dep mythtv
 +
</pre>
 +
 
 +
Now lets get a copy of the MythTV source code from the git repository at [https://github.com/organizations/MythTV github]:
 +
 
 +
<pre>
 +
git clone git://github.com/MythTV/mythtv.git
 +
</pre>
 +
 
 +
By default a new checkout from git will use the master branch but you can choose any branch you require for example to use the fixes/31 branch do this:
 +
<pre>
 +
git checkout fixes/31
 +
</pre>
 +
 
 +
At this point it would be wise to make sure you can build, install and run the clean sources before making any changes (change the configure parameters as required - the example assumes you want to install to the same place as some packages like Ubuntu do).
 +
<pre>
 +
cd mythtv
 +
./configure --prefix=/usr
 +
make -j4
 +
sudo make install
 +
cd ../mythplugins
 +
./configure --prefix=/usr
 +
make -j4
 +
sudo make install
 +
</pre>
 +
You can now test the install to make sure everything is working correctly.
  
 +
Now lets add our new plugin - create the following directory tree within the mythplugins directory:
 
<pre>
 
<pre>
mythplugins/
+
cd mythtv/mythplugins
  mythhello/
+
mkdir -p mythhello/mythhello
    mythhello/
 
 
</pre>
 
</pre>
  
Line 25: Line 57:
  
 
# Directories
 
# Directories
SUBDIRS = <strong>mythhello</strong>
+
SUBDIRS = mythhello
 
</pre>
 
</pre>
  
Line 31: Line 63:
  
 
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 widgets
  
 
TEMPLATE = lib
 
TEMPLATE = lib
Line 41: Line 77:
 
INSTALLS += target
 
INSTALLS += target
  
uifiles.path = $${PREFIX}/share/mythtv/themes/default
+
INCLUDEPATH += $${PREFIX}/include/mythtv
uifiles.files = hello-ui.xml
+
INCLUDEPATH += $${PREFIX}/include/mythtv/libmythui
installfiles.path = $${PREFIX}/share/mythtv
+
INCLUDEPATH += $${PREFIX}/include/mythtv/libmythbase
 +
 
 +
installfiles.path = $${PREFIX}/share/mythtv/themes/default
 
installfiles.files = hello-ui.xml
 
installfiles.files = hello-ui.xml
  
INSTALLS += uifiles
+
INSTALLS += installfiles
  
 
# Input
 
# Input
Line 52: Line 90:
 
SOURCES += main.cpp mythhello.cpp
 
SOURCES += main.cpp mythhello.cpp
  
macx {
+
DEFINES += MPLUGIN_API
     QMAKE_LFLAGS += -flat_namespace -undefined suppress
+
 
 +
use_hidesyms {
 +
     QMAKE_CXXFLAGS += -fvisibility=hidden
 
}
 
}
</pre>
 
  
 +
android {
 +
    # to discriminate plugins in a flat directory structure
 +
    TARGET = mythplugin$${TARGET}
 +
}
  
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:
+
include ( ../../libs-targetfix.pro )
<pre>
 
PREFIX=/usr/
 
LIBDIR=/usr/lib/
 
 
</pre>
 
</pre>
 +
}}
  
 
=== CPP Files ===
 
=== CPP Files ===
Line 68: Line 109:
 
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/.
  
==== main.cpp ====
+
Here's the main file that takes care of initializing, running and destructing the plugin:
 +
 
 +
{{Code box|main.cpp|
 +
<pre>
 +
// C++ headers
 +
#include <unistd.h>
 +
 
 +
// QT headers
 +
#include <QApplication>
 +
 
 +
// MythTV headers
 +
#include <mythcontext.h>
 +
#include <mythcorecontext.h>
 +
#include <mythplugin.h>
 +
#include <mythpluginapi.h>
 +
#include <mythversion.h>
 +
#include <mythmainwindow.h>
  
Here's the main file that takes care of initializing, running and destructing the pluigin:
+
// MythHello headers
 +
#include "mythhello.h"
  
<pre>
 
#ifndef MAIN_CPP
 
#define MAIN_CPP
 
  
 
using namespace std;
 
using namespace std;
  
#include "mythhello.h"
+
static int RunHello(void)
#include <mythtv/mythcontext.h>
+
{
#include <mythtv/mythdbcon.h>
+
    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
#include <mythtv/lcddevice.h>
+
   
#include <mythtv/libmythui/myththemedmenu.h>
+
    MythHello *mythhello = new MythHello(mainStack, "hello");
 +
   
 +
    if (mythhello->Create())
 +
    {
 +
        mainStack->AddScreen(mythhello);
 +
        return 0;
 +
    }
 +
    else
 +
    {
 +
        delete mythhello;
 +
        return -1;
 +
    }
 +
}
 +
 
 +
static void runHello(void)
 +
{
 +
    RunHello();
 +
}
  
extern "C" {
+
static void setupKeys(void)
     int mythplugin_init(const char *libversion);
+
{
    int mythplugin_run(void);
+
     REG_JUMP("MythHello", QT_TRANSLATE_NOOP("MythHello",
    int mythplugin_config(void);
+
        "Sample plugin"), "", runHello);
 
}
 
}
  
 
int mythplugin_init(const char *libversion)
 
int mythplugin_init(const char *libversion)
 
{
 
{
     if (!gContext->TestPopupVersion("mythhello", libversion, MYTH_BINARY_VERSION))
+
     if (!gCoreContext->TestPluginVersion("mythhello",
 +
                                        libversion,
 +
                                        MYTH_BINARY_VERSION))
 
         return -1;
 
         return -1;
 
+
   
 +
    setupKeys();
 +
   
 
     return 0;
 
     return 0;
 
}
 
}
  
int mythplugin_run (void)
+
int mythplugin_run(void)
 
{
 
{
     gContext->addCurrentLocation("mythhello");
+
     return RunHello();
 +
}
  
    MythHello hello(gContext->GetMainWindow(), "hello", "hello-");
+
int mythplugin_config(void)
    hello.exec();
+
{
 
+
     return 0;
    gContext->removeCurrentLocation();
 
 
 
     return 1;
 
 
}
 
}
 
int mythplugin_config (void) { return 0; }
 
 
#endif
 
 
</pre>
 
</pre>
 +
}}
  
==== mythhello.h ====
+
{{Code box|mythhello.h|
 
 
 
<pre>
 
<pre>
 
#ifndef MYTHHELLO_H
 
#ifndef MYTHHELLO_H
 
#define MYTHHELLO_H
 
#define MYTHHELLO_H
  
#include <mythtv/uitypes.h>
+
// MythTV headers
#include <mythtv/uilistbtntype.h>
+
 
#include <mythtv/xmlparse.h>
+
#include <mythscreentype.h>
#include <mythtv/mythdialogs.h>
+
#include <mythuibutton.h>
  
  
class MythHello : virtual public MythThemedDialog
+
/** \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) override; // MythScreenType
 +
        bool keyPressEvent(QKeyEvent *) override; // MythScreenType
 +
   
 +
       
 +
    private:
 +
        MythUIText *m_titleText;
 +
        MythUIText *m_outText;
 +
        MythUIButton  *m_cancelButton;
 +
        MythUIButton  *m_okButton;
  
 +
    private slots:
 +
        void ok_clicked(void);
 +
        void cancel_clicked(void);
 +
};
  
public:
+
#endif /* MYTHHELLO_H */
 +
</pre>
 +
}}
  
    MythHello(MythMainWindow *parent, QString windowName,
+
{{Code box|mythhello.cpp|
          QString themeFilename, const char *name = 0);
+
<pre>
    ~MythHello();
+
// 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: ")
  
#endif
+
/** \brief Creates a new MythHello Screen
</pre>
+
*  \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)
  
==== mythhello.cpp ====
+
{
 +
    //example of how to find the configuration dir currently used.
 +
    QString confdir = GetConfDir();
 +
    LOG(VB_GENERAL, LOG_DEBUG, LOC + "Conf dir:"  + confdir);
 +
}
  
<pre>
+
bool MythHello::Create(void)
#ifndef MYTHHELLO_CPP
+
{
#define MYTHHELLO_CPP
+
    bool foundtheme = false;
  
/* QT includes */
+
    // Load the theme for this screen
#include <qnamespace.h>
+
    foundtheme = LoadWindowFromXML("hello-ui.xml", "hello", this);
#include <qstringlist.h>
+
   
#include <qapplication.h>
+
    if (!foundtheme)
#include <qbuttongroup.h>
+
        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);
  
/* MythTV includes */
+
    if (err)
#include <mythtv/mythcontext.h>
+
    {
#include <mythtv/mythdialogs.h>
+
        LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'hello'");
 +
        return false;
 +
    }
 +
   
  
using namespace std;
+
    BuildFocusList();
 +
    SetFocusWidget(m_cancelButton);
  
#include "mythhello.h"
+
    connect(m_okButton, SIGNAL(Clicked()), this, SLOT(ok_clicked()));
 +
    connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(cancel_clicked()));
  
 +
   
 +
    return true;
 +
}
  
MythHello::MythHello(MythMainWindow *parent, QString windowName,
+
bool MythHello::keyPressEvent(QKeyEvent *event)
                          QString themeFilename, const char *name)
 
        : MythThemedDialog(parent, windowName, themeFilename, name)
 
 
{
 
{
 +
    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;
 
}
 
}
  
MythHello::~MythHello() { }
+
void MythHello::ok_clicked(void)
 +
{
 +
    m_outText->SetText(QString("OK clicked"));
 +
}
  
#endif
+
void MythHello::cancel_clicked(void)
</pre>
+
{
 +
    m_outText->SetText(QString("Cancel clicked"));
 +
}</pre>
 +
}}
  
 
=== The UI File ===
 
=== The UI File ===
Line 180: Line 332:
 
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"?>
 
<mythuitheme>
 
<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>
  
  <window name="hello">
+
        <textarea name="outtext">
 +
            <area>0,300,800,100</area>
 +
            <font>large</font>
 +
            <align>allcenter</align>
 +
            <multiline>yes</multiline>
 +
        </textarea>
  
    <font name="title" face="Arial">
+
        <button name="cancel" from="basebutton">
    <color>#ffffff</color>
+
            <position>500,400</position>
    <size>24</size>
+
            <value>Cancel</value>
    <bold>yes</bold>
+
        </button>
    </font>
 
  
    <container name="hello">
+
        <button name="ok" from="basebutton">
      <area>20,20,780,450</area>
+
            <position>200,400</position>
 +
            <value>OK</value>
 +
        </button>
 +
    </window>
 +
</mythuitheme>
  
      <textarea name="title" draworder="1" align="center">
 
        <font>title</font>
 
        <area>0,0,780,40</area>
 
        <value>Hello MythTV!</value>
 
      </textarea>
 
  
    </container>
 
 
    </window>
 
</mythuitheme>
 
 
</pre>
 
</pre>
 +
}}
  
 
=== Building ===
 
=== Building ===
Line 212: Line 373:
  
 
<pre>
 
<pre>
su
 
 
qmake
 
qmake
 
make
 
make
make install
+
sudo make install
 
</pre>
 
</pre>
  
Make sure everything compiled OK and the files where copied to your mythtv installation directories.
+
Make sure everything compiled OK and the files where copied to your MythTV installation directories.
  
 
=== Adding MythHello to your Menus ===
 
=== 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/themes/classic/tvmenu.xml.  Add the following anywhere in the XML file between the <mythmenu> root tag:
+
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:
  
 
<pre>
 
<pre>
Line 239: Line 399:
  
 
- Mozmonkey
 
- Mozmonkey
 +
 +
== More about plugins ==
 +
 +
[[MythPlugin Architecture]]
 +
 +
[[Building_Plugins:MythNotes]] - Another plug-in tutorial
 +
 +
If you wish to compile the existing set of plugins, you will need at least the following packages (it is a long list):
 +
<pre>
 +
sudo apt-get install libxinerama-dev libxv-dev libxrandr-dev libxml2-dev libavahi-compat-libdnssd-dev libssl-dev libass-dev libfftw3-dev libmp3lame-dev libva-dev libasound2-dev libpulse-dev libsdl1.2-dev libfreetype6-dev libpng12-dev libx264-dev libvpx-dev libcrystalhd-dev libudev-dev uuid-dev libbz2-dev libmysqlclient-dev python-oauth libdate-manip-perl libdatetime-format-iso8601-perl libimage-size-perl libsoap-lite-perl libjson-perl dcraw libcdio-paranoia-dev libraw1394-dev libiec61883-dev libavc1394-dev libtag1-dev libflac-dev libvorbis-dev libexif-dev
 +
</pre>
 +
 +
[[Category:HOWTO]]

Latest revision as of 15:36, 10 May 2020


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.

Before you start you may need to install some development tools if you don't already have them (Qt5 development tools and headers) (For reference you can see a full list of dependencies the Ubuntu packaging needs to build here. For example:

sudo apt-get install qt5-qmake libqt5-dev ccache git g++ libmyth-dev

NOTE: a quick way for those using Ubuntu to install all the required build dependencies is to use this (you will have to find and uncomment the correct deb-src line from /etc/apt/sources.list.d/ for this to work):

sudo apt-get build-dep mythtv

Now lets get a copy of the MythTV source code from the git repository at github:

git clone git://github.com/MythTV/mythtv.git

By default a new checkout from git will use the master branch but you can choose any branch you require for example to use the fixes/31 branch do this:

git checkout fixes/31

At this point it would be wise to make sure you can build, install and run the clean sources before making any changes (change the configure parameters as required - the example assumes you want to install to the same place as some packages like Ubuntu do).

cd mythtv
./configure --prefix=/usr
make -j4
sudo make install
cd ../mythplugins
./configure --prefix=/usr
make -j4
sudo make install

You can now test the install to make sure everything is working correctly.

Now lets add our new plugin - create the following directory tree within the mythplugins directory:

cd mythtv/mythplugins
mkdir -p mythhello/mythhello

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

Script.png mythhello.pro

include ( ../../mythconfig.mak )
include ( ../../settings.pro )
include ( ../../programs-libs.pro )

QT += network sql xml widgets

TEMPLATE = lib
CONFIG += plugin thread
TARGET = mythhello
target.path = $${LIBDIR}/mythtv/plugins
INSTALLS += target

INCLUDEPATH += $${PREFIX}/include/mythtv
INCLUDEPATH += $${PREFIX}/include/mythtv/libmythui
INCLUDEPATH += $${PREFIX}/include/mythtv/libmythbase

installfiles.path = $${PREFIX}/share/mythtv/themes/default
installfiles.files = hello-ui.xml

INSTALLS += installfiles

# Input
HEADERS += mythhello.h
SOURCES += main.cpp mythhello.cpp

DEFINES += MPLUGIN_API

use_hidesyms {
    QMAKE_CXXFLAGS += -fvisibility=hidden
}

android {
    # to discriminate plugins in a flat directory structure
    TARGET = mythplugin$${TARGET}
}

include ( ../../libs-targetfix.pro )

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 plugin:


Script.png main.cpp

// C++ headers
#include <unistd.h>

// QT headers
#include <QApplication>

// MythTV headers
#include <mythcontext.h>
#include <mythcorecontext.h>
#include <mythplugin.h>
#include <mythpluginapi.h>
#include <mythversion.h>
#include <mythmainwindow.h>

// MythHello headers
#include "mythhello.h"


using namespace std;

static 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;
    }
}

static void runHello(void)
{
    RunHello();
}

static void setupKeys(void)
{
    REG_JUMP("MythHello", QT_TRANSLATE_NOOP("MythHello",
        "Sample plugin"), "", runHello);
}

int mythplugin_init(const char *libversion)
{
    if (!gCoreContext->TestPluginVersion("mythhello",
                                         libversion,
                                         MYTH_BINARY_VERSION))
        return -1;
    
    setupKeys();
    
    return 0;
}

int mythplugin_run(void)
{
    return RunHello();
}

int mythplugin_config(void)
{
    return 0;
}


Script.png mythhello.h

#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) override; // MythScreenType
        bool keyPressEvent(QKeyEvent *) override; // MythScreenType
    
        
    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 */


Script.png mythhello.cpp

// 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/.


Script.png hello-ui.xml

<?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:

qmake
make
sudo 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

MythPlugin Architecture

Building_Plugins:MythNotes - Another plug-in tutorial

If you wish to compile the existing set of plugins, you will need at least the following packages (it is a long list):

sudo apt-get install libxinerama-dev libxv-dev libxrandr-dev libxml2-dev libavahi-compat-libdnssd-dev libssl-dev libass-dev libfftw3-dev libmp3lame-dev libva-dev libasound2-dev libpulse-dev libsdl1.2-dev libfreetype6-dev libpng12-dev libx264-dev libvpx-dev libcrystalhd-dev libudev-dev uuid-dev libbz2-dev libmysqlclient-dev python-oauth libdate-manip-perl libdatetime-format-iso8601-perl libimage-size-perl libsoap-lite-perl libjson-perl dcraw libcdio-paranoia-dev libraw1394-dev libiec61883-dev libavc1394-dev libtag1-dev libflac-dev libvorbis-dev libexif-dev