Index: libs/libmythui/mythmainwindow.cpp =================================================================== --- libs/libmythui/mythmainwindow.cpp (revision 16103) +++ libs/libmythui/mythmainwindow.cpp (working copy) @@ -8,6 +8,8 @@ #include #include #include +#include + #ifdef QWS #include #endif @@ -504,6 +507,83 @@ d->repaintRegion = d->repaintRegion.unite(pe->region()); } +bool MythMainWindow::screenShot(QString fname, int x, int y, int x2, int y2, int w, int h) +{ + bool ret = false; + + QString extension = fname.section('.', -1, -1); + if (extension == "jpg") + extension = "JPEG"; + else + extension = "PNG"; + + VERBOSE(VB_GENERAL, QString("MythMainWindow::screenShot saving winId %1 to %2 (%3 x %4) [ %5/%6 - %7/%8] type %9") + .arg(QApplication::desktop()->winId()) + .arg(fname) + .arg(w) + .arg(h) + .arg(x) + .arg(y) + .arg(x2) + .arg(y2) + .arg(extension)); + + QPixmap p; + p = QPixmap::grabWindow( QApplication::desktop()->winId(), x, y, x2, y2); + + QImage img = p.convertToImage(); + + if ( w == 0 ) + w = img.width(); + + if ( h == 0 ) + h = img.height(); + + VERBOSE(VB_GENERAL, QString("Scaling to %1 x %2 from %3 x %4") + .arg(w) + .arg(h) + .arg(img.width()) + .arg(img.height())); + + img = img.smoothScale( w, h , QImage::ScaleMin); + + if (img.save(fname ,extension,100)) + { + VERBOSE(VB_GENERAL, "MythMainWindow::screenShot succeeded"); + ret = true; + } + else + { + VERBOSE(VB_GENERAL, "MythMainWindow::screenShot Failed!"); + ret = false; + } + + return ret; +} + +bool MythMainWindow::screenShot(int x, int y, int x2, int y2) +{ + QString fPath = gContext->GetSetting("ScreenShotPath","/tmp/"); + QString fName = QString("/%1/myth-screenshot-%2.png") + .arg(fPath) + .arg(QDateTime::currentDateTime().toString("yyyy-mm-ddThh-mm-ss.zzz")); + + return screenShot(fName, x, y, x2, y2, 0, 0); +} + +bool MythMainWindow::screenShot(QString fname, int w, int h) +{ + QRect sLoc = qApp->mainWidget()->geometry(); + return screenShot(fname, sLoc.left(),sLoc.top(), sLoc.width(), sLoc.height(), w, h); +} + + +bool MythMainWindow::screenShot(void) +{ + QRect sLoc = qApp->mainWidget()->geometry(); + return screenShot(sLoc.left(),sLoc.top(), sLoc.width(), sLoc.height()); +} + #ifdef USING_APPLEREMOTE // This may be possible via installEventFilter() instead? Index: libs/libmythui/mythmainwindow.h =================================================================== --- libs/libmythui/mythmainwindow.h (revision 16103) +++ libs/libmythui/mythmainwindow.h (working copy) @@ -101,6 +101,11 @@ MythPainter *GetCurrentPainter(); + bool screenShot(QString fname, int x, int y, int x2, int y2, int w, int h); + bool screenShot(int x, int y, int x2, int y2); + bool screenShot(QString fname, int w, int h); + bool screenShot(void); + void AllowInput(bool allow); QRect GetUIScreenRect(); Index: programs/mythfrontend/mediarenderer.cpp =================================================================== --- programs/mythfrontend/mediarenderer.cpp (revision 16103) +++ programs/mythfrontend/mediarenderer.cpp (working copy) @@ -9,6 +9,7 @@ ///////////////////////////////////////////////////////////////////////////// #include "mediarenderer.h" +#include "mythfexml.h" #include "compat.h" ///////////////////////////////////////////////////////////////////////////// @@ -89,6 +90,11 @@ "http-get:*:video/mpeg:*," "http-get:*:video/nupplevideo:*," "http-get:*:video/x-ms-wmv:*"; + // ------------------------------------------------------------------ + // Register the MythFEXML protocol... + // ------------------------------------------------------------------ + VERBOSE(VB_UPNP, "MediaRenderer::Registering MythFEXML Service." ); + m_pHttpServer->RegisterExtension( new MythFEXML( RootDevice() )); // VERBOSE(VB_UPNP, QString( "MediaRenderer::Registering AVTransport Service." )); // m_pHttpServer->RegisterExtension( m_pUPnpAVT = new UPnpAVTransport( RootDevice() )); Index: programs/mythfrontend/MFEXML_scpd.xml =================================================================== --- programs/mythfrontend/MFEXML_scpd.xml (revision 0) +++ programs/mythfrontend/MFEXML_scpd.xml (revision 0) @@ -0,0 +1,34 @@ + + + + 1 + 0 + + + + GetScreenShot + + + Height + in + A_ARG_TYPE_Height + + + Width + in + A_ARG_TYPE_Width + + + + + + + A_ARG_TYPE_Height + i2 + + + A_ARG_TYPE_Width + i2 + + + Index: programs/mythfrontend/globalsettings.cpp =================================================================== --- programs/mythfrontend/globalsettings.cpp (revision 16103) +++ programs/mythfrontend/globalsettings.cpp (working copy) @@ -2220,6 +2220,15 @@ return ge; } +static HostLineEdit *ScreenShotPath() +{ + HostLineEdit *ge = new HostLineEdit("ScreenShotPath"); + ge->setLabel(QObject::tr("ScreenShotPath")); + ge->setValue("/tmp/"); + ge->setHelpText(QObject::tr("Path to screenshot storage location. Should be writable by the frontend")); + return ge; +} + static HostCheckBox *UseArrowAccels() { HostCheckBox *gc = new HostCheckBox("UseArrowAccels"); @@ -4502,6 +4511,7 @@ MythMediaSettings *mediaMon = new MythMediaSettings(); general->addChild(LircKeyPressedApp()); + general->addChild(ScreenShotPath()); general->addChild(row); general->addChild(NetworkControlPort()); general->addChild(mediaMon); Index: programs/mythfrontend/mythfexml.h =================================================================== --- programs/mythfrontend/mythfexml.h (revision 0) +++ programs/mythfrontend/mythfexml.h (revision 0) @@ -0,0 +1,66 @@ +////////////////////////////////////////////////////////////////////////////// +// Program Name: mythxml.h +// +// Purpose - Myth Frontend XML protocol HttpServerExtension +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef MYTHFEXML_H_ +#define MYTHFEXML_H_ + +#include +#include + +#include "upnp.h" +#include "eventing.h" +#include "mythcontext.h" + +typedef enum +{ + MFEXML_Unknown = 0, + MFEXML_GetScreenShot = 1 + +} MythFEXMLMethod; + +class MythFEXML : public Eventing +{ + private: + + QString m_sControlUrl; + QString m_sServiceDescFileName; + + protected: + + // Implement UPnpServiceImpl methods that we can + + virtual QString GetServiceType () { return "urn:schemas-mythtv-org:service:MythTv:1"; } + virtual QString GetServiceId () { return "urn:mythtv-org:serviceId:MYTHTV_1-0"; } + virtual QString GetServiceControlURL() { return m_sControlUrl.mid( 1 ); } + virtual QString GetServiceDescURL () { return m_sControlUrl.mid( 1 ) + "/GetServDesc"; } + + private: + + MythFEXMLMethod GetMethod( const QString &sURI ); + + void GetScreenShot ( HTTPRequest *pRequest ); + + public: + MythFEXML( UPnpDevice *pDevice ); + virtual ~MythFEXML(); + + bool ProcessRequest( HttpWorkerThread *pThread, HTTPRequest *pRequest ); + + // Static methods shared with HttpStatus + +}; + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +#endif + + Index: programs/mythfrontend/main.cpp =================================================================== --- programs/mythfrontend/main.cpp (revision 16103) +++ programs/mythfrontend/main.cpp (working copy) @@ -800,6 +800,11 @@ } } +void getScreenShot(void) +{ + (void) gContext->GetMainWindow()->screenShot(); +} + void InitJumpPoints(void) { REG_JUMP("Reload Theme", "", "", reloadTheme); @@ -818,6 +823,8 @@ REG_JUMP("Status Screen", "", "", showStatus); REG_JUMP("Previously Recorded", "", "", startPrevious); + REG_JUMPEX("ScreenShot","","",getScreenShot,false); + REG_KEY("qt", "DELETE", "Delete", "D"); REG_KEY("qt", "EDIT", "Edit", "E"); Index: programs/mythfrontend/mythfrontend.pro =================================================================== --- programs/mythfrontend/mythfrontend.pro (revision 16103) +++ programs/mythfrontend/mythfrontend.pro (working copy) @@ -15,7 +15,7 @@ setting.files += util_menu.xml info_settings.xml main_settings.xml setting.files += recpriorities_settings.xml tv_search.xml tv_lists.xml setting.files += library.xml manage_recordings.xml optical_menu.xml tvmenu.xml -setting.files += tv_settings.xml +setting.files += tv_settings.xml MFEXML_scpd.xml setting.extra = -ldconfig INSTALLS += setting @@ -26,13 +26,13 @@ HEADERS += manualbox.h playbackbox.h viewscheduled.h globalsettings.h HEADERS += manualschedule.h programrecpriority.h channelrecpriority.h HEADERS += statusbox.h networkcontrol.h custompriority.h -HEADERS += mediarenderer.h +HEADERS += mediarenderer.h mythfexml.h HEADERS += mythappearance.h SOURCES += main.cpp manualbox.cpp playbackbox.cpp viewscheduled.cpp SOURCES += globalsettings.cpp manualschedule.cpp programrecpriority.cpp SOURCES += channelrecpriority.cpp statusbox.cpp networkcontrol.cpp -SOURCES += mediarenderer.cpp +SOURCES += mediarenderer.cpp mythfexml.cpp SOURCES += custompriority.cpp SOURCES += mythappearance.cpp Index: programs/mythfrontend/mythfexml.cpp =================================================================== --- programs/mythfrontend/mythfexml.cpp (revision 0) +++ programs/mythfrontend/mythfexml.cpp (revision 0) @@ -0,0 +1,133 @@ +////////////////////////////////////////////////////////////////////////////// +// Program Name: MythXML.cpp +// +// Purpose - Html & XML status HttpServerExtension +// +// Created By : David Blain Created On : Oct. 24, 2005 +// Modified By : Daniel Kristjansson Modified On: Oct. 31, 2007 +// +////////////////////////////////////////////////////////////////////////////// + +#include "mythfexml.h" + +#include "libmyth/mythcontext.h" +#include "libmyth/util.h" +#include "libmyth/mythdbcon.h" + +#include "mythmainwindow.h" + +#include +#include +#include +#include +#include +#include + +#include "../../config.h" + +///////////////////////////////////////////////////////////////////////////// +// +///////////////////////////////////////////////////////////////////////////// + +MythFEXML::MythFEXML( UPnpDevice *pDevice ) : Eventing( "MythFEXML", "MYTHTV_Event" ) +{ + + QString sUPnpDescPath = UPnp::g_pConfig->GetValue( "UPnP/DescXmlPath", m_sSharePath ); + + m_sServiceDescFileName = sUPnpDescPath + "MFEXML_scpd.xml"; + m_sControlUrl = "/MythFE"; + + // Add our Service Definition to the device. + + RegisterService( pDevice ); +} + +///////////////////////////////////////////////////////////////////////////// +// +///////////////////////////////////////////////////////////////////////////// + +MythFEXML::~MythFEXML() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// +///////////////////////////////////////////////////////////////////////////// + +MythFEXMLMethod MythFEXML::GetMethod( const QString &sURI ) +{ + if (sURI == "GetScreenShot" ) return MFEXML_GetScreenShot; + + return( MFEXML_Unknown ); +} + +///////////////////////////////////////////////////////////////////////////// +// +///////////////////////////////////////////////////////////////////////////// + +bool MythFEXML::ProcessRequest( HttpWorkerThread *pThread, HTTPRequest *pRequest ) +{ + try + { + if (pRequest) + { + if (pRequest->m_sBaseUrl != m_sControlUrl) + return( false ); + + VERBOSE(VB_UPNP, QString("MythFEXML::ProcessRequest: %1 : %2") + .arg(pRequest->m_sMethod) + .arg(pRequest->m_sRawRequest)); + + switch( GetMethod( pRequest->m_sMethod )) + { + case MFEXML_GetScreenShot : GetScreenShot ( pRequest ); return true; + + + default: + { + UPnp::FormatErrorResponse( pRequest, UPnPResult_InvalidAction ); + + return true; + } + } + } + } + catch( ... ) + { + VERBOSE( VB_IMPORTANT, "MythFEXML::ProcessRequest() - Unexpected Exception" ); + } + + return( false ); +} + +// ========================================================================== +// Request handler Methods +// ========================================================================== + +///////////////////////////////////////////////////////////////////////////// +// +///////////////////////////////////////////////////////////////////////////// + +void MythFEXML::GetScreenShot( HTTPRequest *pRequest ) +{ + pRequest->m_eResponseType = ResponseTypeFile; + + // Optional Parameters + + int nWidth = pRequest->m_mapParams[ "Width" ].toInt(); + int nHeight = pRequest->m_mapParams[ "Height" ].toInt(); + + // Read Icon file path from database + + QString sFileName = QString("/%1/myth-screenshot-XML.jpg") + .arg(gContext->GetSetting("ScreenShotPath","/tmp/")); + + if (!gContext->GetMainWindow()->screenShot(sFileName,nWidth, nHeight)) + { + VERBOSE(VB_GENERAL, "MythFEXML: Failed to take screenshot. Aborting"); + return; + } + + pRequest->m_sFileName = sFileName; +} +