diff --git a/bin/install_hyperion.sh b/bin/install_hyperion.sh index 0448b7a1..8aca03b2 100644 --- a/bin/install_hyperion.sh +++ b/bin/install_hyperion.sh @@ -1,24 +1,27 @@ #!/bin/sh -# Script for removing the existing boblight library and replacing it with Hyperion +# Script for downloading and installing the latest Hyperion release -# First stop the current BobLight demon and XBMC -initctl stop xbmc -initctl stop boblight +# Make sure that the boblight daemon is no longer running +BOBLIGHT_PROCNR=$(ps -e | grep "boblight" | wc -l) +if [ $BOBLIGHT_PROCNR -eq 1 ]; +then + echo 'Found running instance of boblight. Please stop boblight via XBMC menu before installing hyperion' + exit +fi -# Install the RapsiLight library -cp libbob2hyperion.so /usr/lib/libbob2hyperion.so -chmod 755 /usr/lib/libbob2hyperion.so -cp hyperion.config.json /etc/ -cp hyperion.schema.json /etc/ +# Stop hyperion daemon if it is running +initctl stop hyperion -# Remove the existing boblight client library (make backup) -cp /usr/lib/libboblight.so.0.0.0 /usr/lib/libboblight.old -# Rename the settings file to ensure that the boblight-deamon does not start -mv /etc/bobconfig.txt /etc/bobconfig.txt.old +# Copy the hyperion-binaries to the /usr/bin +wget github.com/tvdzwan/hyperion/tree/master/deploy/hyperiond -P /usr/bin/ +wget github.com/tvdzwan/hyperion/tree/master/deploy/hyperion-remote -P /usr/bin/ -# Link libboblight to the new installed library -ln -s /usr/lib/libbob2hyperion.so /usr/lib/libboblight.so.0.0.0 +# Copy the hyperion configuration file to /etc +wget github.com/tvdzwan/hyperion/tree/master/config/hyperion.config.json -P /etc/ -# Restart only XBMC -initctl start xbmc +# Copy the service control configuration to /etc/int +wget github.com/tvdzwan/hyperion/tree/master/bin/hyperion.conf -P /etc/init/ + +# Start the hyperion daemon +initctl start hyperion diff --git a/deploy/hyperion-remote b/deploy/hyperion-remote new file mode 100755 index 00000000..51d6553d Binary files /dev/null and b/deploy/hyperion-remote differ diff --git a/deploy/hyperiond b/deploy/hyperiond new file mode 100755 index 00000000..ad8fe284 Binary files /dev/null and b/deploy/hyperiond differ diff --git a/include/dispmanx-grabber/DispmanxWrapper.h b/include/dispmanx-grabber/DispmanxWrapper.h index 6dc433cd..b5487945 100644 --- a/include/dispmanx-grabber/DispmanxWrapper.h +++ b/include/dispmanx-grabber/DispmanxWrapper.h @@ -55,10 +55,10 @@ public slots: void stop(); /// - /// \brief Set the grabbing mode - /// \param mode The new grabbing mode + /// Set the grabbing mode + /// @param[in] mode The new grabbing mode /// - void setGrabbingMode(GrabbingMode mode); + void setGrabbingMode(const GrabbingMode mode); private: /// The update rate [Hz] diff --git a/include/utils/GrabbingMode.h b/include/utils/GrabbingMode.h index 7e7a8786..fe3b09ee 100644 --- a/include/utils/GrabbingMode.h +++ b/include/utils/GrabbingMode.h @@ -1,8 +1,13 @@ #pragma once +/** + * Enumeration of the possible modes in which frame-grabbing is performed. + */ enum GrabbingMode { + /** Frame grabbing is switched off */ GRABBINGMODE_OFF, + /** Frame grabbing during video */ GRABBINGMODE_VIDEO, GRABBINGMODE_PHOTO, GRABBINGMODE_AUDIO, diff --git a/libsrc/dispmanx-grabber/DispmanxFrameGrabber.cpp b/libsrc/dispmanx-grabber/DispmanxFrameGrabber.cpp index d497b876..204346fe 100644 --- a/libsrc/dispmanx-grabber/DispmanxFrameGrabber.cpp +++ b/libsrc/dispmanx-grabber/DispmanxFrameGrabber.cpp @@ -1,9 +1,22 @@ #include "DispmanxFrameGrabber.h" +// Because the shapshot function is incompatible between versions (use of different enum as +// third argument) and no proper version number is available as preprocessor define we cast the +// function to the same function with the third argument as 'int'. +// This way we can call the function in both versions of the VideoCore library without +// switching. +static int my_vc_dispmanx_snapshot(DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_RESOURCE_HANDLE_T snapshot_resource, int transform) +{ + typedef int (*SnapshotFunctionPtr)(DISPMANX_DISPLAY_HANDLE_T, DISPMANX_RESOURCE_HANDLE_T, int); + SnapshotFunctionPtr snapshot = (SnapshotFunctionPtr) &vc_dispmanx_snapshot; + return (*snapshot)(display, snapshot_resource, transform); +} + DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) : _vc_display(0), _vc_resource(0), + _vc_flags(0), _width(width), _height(height) { @@ -50,6 +63,11 @@ DispmanxFrameGrabber::~DispmanxFrameGrabber() bcm_host_deinit(); } +void DispmanxFrameGrabber::setFlags(const int vc_flags) +{ + _vc_flags = vc_flags; +} + void DispmanxFrameGrabber::grabFrame(RgbImage& image) { // Sanity check of the given image size @@ -59,7 +77,7 @@ void DispmanxFrameGrabber::grabFrame(RgbImage& image) _vc_display = vc_dispmanx_display_open(0); // Create the snapshot (incl down-scaling) - vc_dispmanx_snapshot(_vc_display, _vc_resource, VC_IMAGE_ROT0); + my_vc_dispmanx_snapshot(_vc_display, _vc_resource, _vc_flags); // Read the snapshot into the memory void* image_ptr = image.memptr(); diff --git a/libsrc/dispmanx-grabber/DispmanxFrameGrabber.h b/libsrc/dispmanx-grabber/DispmanxFrameGrabber.h index 50c90ce4..fee6be91 100644 --- a/libsrc/dispmanx-grabber/DispmanxFrameGrabber.h +++ b/libsrc/dispmanx-grabber/DispmanxFrameGrabber.h @@ -26,6 +26,13 @@ public: DispmanxFrameGrabber(const unsigned width, const unsigned height); ~DispmanxFrameGrabber(); + /// + /// Updates the frame-grab flags as used by the VC library for frame grabbing + /// + /// @param vc_flags The snapshot grabbing mask + /// + void setFlags(const int vc_flags); + /// /// Captures a single snapshot of the display and writes the data to the given image. The /// provided image should have the same dimensions as the configured values (_width and @@ -46,8 +53,12 @@ private: /// Rectangle of the captured resource that is transfered to user space VC_RECT_T _rectangle; + /// Flags (transforms) for creating snapshots + int _vc_flags; + /// With of the captured snapshot [pixels] unsigned _width; /// Height of the captured snapshot [pixels] unsigned _height; + }; diff --git a/libsrc/dispmanx-grabber/DispmanxWrapper.cpp b/libsrc/dispmanx-grabber/DispmanxWrapper.cpp index f04e3dce..ba4bd1f1 100644 --- a/libsrc/dispmanx-grabber/DispmanxWrapper.cpp +++ b/libsrc/dispmanx-grabber/DispmanxWrapper.cpp @@ -61,10 +61,23 @@ void DispmanxWrapper::stop() _timer.stop(); } -void DispmanxWrapper::setGrabbingMode(GrabbingMode mode) +void DispmanxWrapper::setGrabbingMode(const GrabbingMode mode) { - if (mode == GRABBINGMODE_VIDEO) + switch (mode) + { + case GRABBINGMODE_VIDEO: + _frameGrabber->setFlags(DISPMANX_SNAPSHOT_NO_RGB|DISPMANX_SNAPSHOT_FILL); start(); - else + case GRABBINGMODE_AUDIO: + case GRABBINGMODE_PHOTO: + case GRABBINGMODE_MENU: + _frameGrabber->setFlags(0); + start(); + break; + case GRABBINGMODE_OFF: stop(); + break; + case GRABBINGMODE_INVALID: + break; + } } diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json index fdfb127e..f3923a90 100644 --- a/libsrc/hyperion/hyperion.schema.json +++ b/libsrc/hyperion/hyperion.schema.json @@ -200,6 +200,42 @@ } }, "additionalProperties" : false + }, + "bootsequence" : + { + "type" : "object", + "required" : true, + "properties" : { + "type" : { + "type" : "string", + "required" : true + }, + "duration_ms" : { + "type" : "integer", + "required" : true + } + }, + "additionalProperties" : false + }, + "framegrabber" : + { + "type" : "object", + "required" : true, + "properties" : { + "width" : { + "type" : "integer", + "required" : true + }, + "height" : { + "type" : "integer", + "required" : true + }, + "frequency_Hz" : { + "type" : "integer", + "required" : true + } + }, + "additionalProperties" : false } }, "additionalProperties" : false diff --git a/test/TestConfigFile.cpp b/test/TestConfigFile.cpp index afe71143..be1e8880 100644 --- a/test/TestConfigFile.cpp +++ b/test/TestConfigFile.cpp @@ -2,50 +2,64 @@ // STL includes #include +// QT includes +#include + // JsonSchema includes #include // hyperion includes #include -int main() +Json::Value loadConfig(const std::string & configFile) { - std::string homeDir = getenv("RASPILIGHT_HOME"); + // make sure the resources are loaded (they may be left out after static linking) + Q_INIT_RESOURCE(resource); - const std::string schemaFile = homeDir + "/hyperion.schema.json"; - const std::string configFile = homeDir + "/hyperion.config.json"; - - Json::Value config; - if (JsonFactory::load(schemaFile, configFile, config) < 0) + // read the json schema from the resource + QResource schemaData(":/hyperion-schema"); + if (!schemaData.isValid()) \ { - std::cerr << "UNABLE TO LOAD CONFIGURATION" << std::endl; - return -1; + throw std::runtime_error("Schema not found"); } - const Json::Value& deviceConfig = config["device"]; - if (deviceConfig.empty()) + Json::Reader jsonReader; + Json::Value schemaJson; + if (!jsonReader.parse(reinterpret_cast(schemaData.data()), reinterpret_cast(schemaData.data()) + schemaData.size(), schemaJson, false)) { - std::cout << "Missing DEVICE configuration 'device'" << std::endl; + throw std::runtime_error("Schema error: " + jsonReader.getFormattedErrorMessages()) ; } - const Json::Value& ledConfig = config["leds"]; - if (ledConfig.empty()) + JsonSchemaChecker schemaChecker; + schemaChecker.setSchema(schemaJson); + + const Json::Value jsonConfig = JsonFactory::readJson(configFile); + schemaChecker.validate(jsonConfig); + + return jsonConfig; +} + +int main(int argc, char** argv) +{ + if (argc != 2) { - std::cout << "Missing LEDS configuration 'leds'" << std::endl; + std::cerr << "Missing required configuration file to test" << std::endl; + std::cerr << "Usage: test_configfile [configfile]" << std::endl; + return 0; } - const Json::Value& colorConfig = config["color"]; - if (colorConfig.empty()) + const std::string configFile(argv[1]); + std::cout << "Configuration file selected: " << configFile.c_str() << std::endl; + std::cout << "Attemp to load...\t"; + try { - std::cout << "Missing COLORS configuration 'colors'" << std::endl; + Json::Value value = loadConfig(configFile); + (void)value; + std::cout << "PASSED" << std::endl; } - else + catch (std::runtime_error exception) { - std::cout << "COLOR CONFIGURATION: " << colorConfig.toStyledString() << std::endl; - - const Json::Value& redConfig = colorConfig["red"]; - double redGamma = redConfig["gamma"].asDouble(); - std::cout << "RED GAMMA = " << redGamma << std::endl; - std::cout << "RED GAMMA = " << colorConfig["red.gamma"].asDouble() << std::endl; + std::cout << "FAILED" << std::endl; + std::cout << exception.what() << std::endl; } return 0;