mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Merge remote-tracking branch 'remotes/origin/master'
Former-commit-id: e159c4757880a0f77f59c6b23775856e4fd4b8fe
This commit is contained in:
commit
b1b6de7ce6
@ -46,3 +46,6 @@ add_subdirectory(dependencies)
|
||||
add_subdirectory(libsrc)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
|
||||
# Add the doxygen generation directory
|
||||
add_subdirectory(doc)
|
||||
|
32
doc/CMakeLists.txt
Normal file
32
doc/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
# Find doxygen
|
||||
find_package(Doxygen QUIET)
|
||||
|
||||
# This processes our hyperion-cmake.doxyfile and subsitutes variables to generate a final hyperion.doxyfile
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hyperion.in.doxygen ${CMAKE_CURRENT_BINARY_DIR}/hyperion.doxygen)
|
||||
|
||||
# This processes the shell script that is used to build the documentation and check the result
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hyperion-build-doc.in.sh ${CMAKE_CURRENT_BINARY_DIR}/hyperion-build-doc.sh)
|
||||
|
||||
# Define all static (i.e. not generated) documentation files
|
||||
set(StaticDocumentationFiles hyperion-header.html hyperion-footer.html hyperion-stylesheet.css)
|
||||
|
||||
# Loop over all static documentation files
|
||||
foreach(StaticDocumentationFile ${StaticDocumentationFiles})
|
||||
# Copy the file to the bindary documentation directory
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${StaticDocumentationFile} ${CMAKE_CURRENT_BINARY_DIR}/html/${StaticDocumentationFile} COPYONLY)
|
||||
endforeach()
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
option(BuildDocumentationSearchEngine "Enable doxygen's search engine (requires that documentation to be installed on a php enabled web server)" OFF)
|
||||
if(BuildDocumentationSearchEngine)
|
||||
set(DOXYGEN_SEARCHENGINE YES)
|
||||
else(BuildDocumentationSearchEngine)
|
||||
set(DOXYGEN_SEARCHENGINE NO)
|
||||
endif(BuildDocumentationSearchEngine)
|
||||
|
||||
#Create a custom target to build documentation. It runs doxygen aginast the generated hyperion.doxyfile and checks its return value
|
||||
add_custom_target(doc sh ${CMAKE_CURRENT_BINARY_DIR}/hyperion-build-doc.sh)
|
||||
else(DOXYGEN_FOUND)
|
||||
message(WARNING "Doxygen not found, unable to generate documenation!")
|
||||
endif(DOXYGEN_FOUND)
|
30
doc/hyperion-build-doc.in.sh
Normal file
30
doc/hyperion-build-doc.in.sh
Normal file
@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Fail on error.
|
||||
set -e
|
||||
|
||||
# Log file containing documentation errors and warnings (if any).
|
||||
log_file=${CMAKE_CURRENT_BINARY_DIR}/hyperion-doxygen.log
|
||||
|
||||
# Remove the log file before building the documentation.
|
||||
rm -f $log_file
|
||||
|
||||
# Generate the documentation.
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/hyperion.doxygen
|
||||
|
||||
# At this point, the log file should have been generated.
|
||||
# If not, an error is displayed on stderr and 1 is returned to indicate an error.
|
||||
if [ -f $log_file ] ; then
|
||||
# So the log file exists. If its size is > 0, show its contents on stderr and exit 1.
|
||||
if [ -s $log_file ] ; then
|
||||
cat $log_file 1>&2
|
||||
exit 1;
|
||||
else
|
||||
# The log file exists, but its size is zero, meaning there were no documentation warnings or errors.
|
||||
# Exit with 0 to indicate success.
|
||||
exit 0;
|
||||
fi
|
||||
else
|
||||
echo "The doxygen log file ($log_file) does not exist. Ensure that WARN_LOGFILE is set correctly in hyperion-cmake.doxyfile." 1>&2
|
||||
exit 1;
|
||||
fi
|
8
doc/hyperion-footer.html
Normal file
8
doc/hyperion-footer.html
Normal file
@ -0,0 +1,8 @@
|
||||
<hr>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><address style="text-align: right;"><small>Generated at $datetime for $projectname by <a href="http://www.doxygen.org">doxygen</a> $doxygenversion.</small></address></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
9
doc/hyperion-header.html
Normal file
9
doc/hyperion-header.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<title>$title</title>
|
||||
<link href="$relpath$doxygen.css" rel="stylesheet" type="text/css">
|
||||
<link href="$relpath$tabs.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
472
doc/hyperion-stylesheet.css
Normal file
472
doc/hyperion-stylesheet.css
Normal file
@ -0,0 +1,472 @@
|
||||
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
|
||||
font-family: Geneva, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
BODY,TD {
|
||||
font-size: 90%;
|
||||
}
|
||||
H1 {
|
||||
text-align: center;
|
||||
font-size: 160%;
|
||||
}
|
||||
H2 {
|
||||
font-size: 120%;
|
||||
}
|
||||
H3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
CAPTION {
|
||||
font-weight: bold
|
||||
}
|
||||
DIV.qindex {
|
||||
width: 100%;
|
||||
background-color: #e8eef2;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
DIV.navpath {
|
||||
width: 100%;
|
||||
background-color: #e8eef2;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
DIV.navtab {
|
||||
background-color: #e8eef2;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
margin-right: 15px;
|
||||
padding: 2px;
|
||||
}
|
||||
TD.navtab {
|
||||
font-size: 70%;
|
||||
}
|
||||
A.qindex {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #1A419D;
|
||||
}
|
||||
A.qindex:visited {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #1A419D
|
||||
}
|
||||
A.qindex:hover {
|
||||
text-decoration: none;
|
||||
background-color: #ddddff;
|
||||
}
|
||||
A.qindexHL {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
border: 1px double #9295C2;
|
||||
}
|
||||
A.qindexHL:hover {
|
||||
text-decoration: none;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
}
|
||||
A.qindexHL:visited {
|
||||
text-decoration: none;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff
|
||||
}
|
||||
A.el {
|
||||
text-decoration: none;
|
||||
font-weight: bold
|
||||
}
|
||||
A.elRef {
|
||||
font-weight: bold
|
||||
}
|
||||
A.code:link {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
color: #0000FF
|
||||
}
|
||||
A.code:visited {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
color: #0000FF
|
||||
}
|
||||
A.codeRef:link {
|
||||
font-weight: normal;
|
||||
color: #0000FF
|
||||
}
|
||||
A.codeRef:visited {
|
||||
font-weight: normal;
|
||||
color: #0000FF
|
||||
}
|
||||
A:hover {
|
||||
text-decoration: none;
|
||||
background-color: #f2f2ff
|
||||
}
|
||||
DL.el {
|
||||
margin-left: -1cm
|
||||
}
|
||||
.fragment {
|
||||
font-family: monospace, fixed;
|
||||
font-size: 95%;
|
||||
}
|
||||
PRE.fragment {
|
||||
border: 1px solid #CCCCCC;
|
||||
background-color: #f5f5f5;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
margin-left: 2px;
|
||||
margin-right: 8px;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
DIV.ah {
|
||||
background-color: black;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin-bottom: 3px;
|
||||
margin-top: 3px
|
||||
}
|
||||
|
||||
DIV.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
DIV.groupText {
|
||||
margin-left: 16px;
|
||||
font-style: italic;
|
||||
font-size: 90%
|
||||
}
|
||||
BODY {
|
||||
background: white;
|
||||
color: black;
|
||||
margin-right: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
TD.indexkey {
|
||||
background-color: #e8eef2;
|
||||
font-weight: bold;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
TD.indexvalue {
|
||||
background-color: #e8eef2;
|
||||
font-style: italic;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
TR.memlist {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
P.formulaDsp {
|
||||
text-align: center;
|
||||
}
|
||||
IMG.formulaDsp {
|
||||
}
|
||||
IMG.formulaInl {
|
||||
vertical-align: middle;
|
||||
}
|
||||
SPAN.keyword { color: #008000 }
|
||||
SPAN.keywordtype { color: #604020 }
|
||||
SPAN.keywordflow { color: #e08000 }
|
||||
SPAN.comment { color: #800000 }
|
||||
SPAN.preprocessor { color: #806020 }
|
||||
SPAN.stringliteral { color: #002080 }
|
||||
SPAN.charliteral { color: #008080 }
|
||||
SPAN.vhdldigit { color: #ff00ff }
|
||||
SPAN.vhdlchar { color: #000000 }
|
||||
SPAN.vhdlkeyword { color: #700070 }
|
||||
SPAN.vhdllogic { color: #ff0000 }
|
||||
|
||||
.mdescLeft {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.mdescRight {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.memItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplParams {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
color: #606060;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 80%;
|
||||
}
|
||||
.search {
|
||||
color: #003399;
|
||||
font-weight: bold;
|
||||
}
|
||||
FORM.search {
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
INPUT.search {
|
||||
font-size: 75%;
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
background-color: #e8eef2;
|
||||
}
|
||||
TD.tiny {
|
||||
font-size: 75%;
|
||||
}
|
||||
a {
|
||||
color: #1A41A8;
|
||||
}
|
||||
a:visited {
|
||||
color: #2A3798;
|
||||
}
|
||||
.dirtab {
|
||||
padding: 4px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #84b0c7;
|
||||
}
|
||||
TH.dirtab {
|
||||
background: #e8eef2;
|
||||
font-weight: bold;
|
||||
}
|
||||
HR {
|
||||
height: 1px;
|
||||
border: none;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
/* Style for detailed member documentation */
|
||||
.memtemplate {
|
||||
font-size: 80%;
|
||||
color: #606060;
|
||||
font-weight: normal;
|
||||
margin-left: 3px;
|
||||
}
|
||||
.memnav {
|
||||
background-color: #e8eef2;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
margin-right: 15px;
|
||||
padding: 2px;
|
||||
}
|
||||
.memitem {
|
||||
padding: 4px;
|
||||
background-color: #eef3f5;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #dedeee;
|
||||
-moz-border-radius: 8px 8px 8px 8px;
|
||||
}
|
||||
.memname {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
}
|
||||
.memdoc {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.memproto {
|
||||
background-color: #d5e1e8;
|
||||
width: 100%;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #84b0c7;
|
||||
font-weight: bold;
|
||||
-moz-border-radius: 8px 8px 8px 8px;
|
||||
}
|
||||
.paramkey {
|
||||
text-align: right;
|
||||
}
|
||||
.paramtype {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.paramname {
|
||||
color: #602020;
|
||||
font-style: italic;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* End Styling for detailed member documentation */
|
||||
|
||||
/* for the tree view */
|
||||
.ftvtree {
|
||||
font-family: sans-serif;
|
||||
margin:0.5em;
|
||||
}
|
||||
/* these are for tree view when used as main index */
|
||||
.directory {
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
.directory h3 {
|
||||
margin: 0px;
|
||||
margin-top: 1em;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
/* The following two styles can be used to replace the root node title */
|
||||
/* with an image of your choice. Simply uncomment the next two styles, */
|
||||
/* specify the name of your image and be sure to set 'height' to the */
|
||||
/* proper pixel height of your image. */
|
||||
|
||||
/* .directory h3.swap { */
|
||||
/* height: 61px; */
|
||||
/* background-repeat: no-repeat; */
|
||||
/* background-image: url("yourimage.gif"); */
|
||||
/* } */
|
||||
/* .directory h3.swap span { */
|
||||
/* display: none; */
|
||||
/* } */
|
||||
|
||||
.directory > h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.directory p {
|
||||
margin: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.directory div {
|
||||
display: none;
|
||||
margin: 0px;
|
||||
}
|
||||
.directory img {
|
||||
vertical-align: -30%;
|
||||
}
|
||||
/* these are for tree view when not used as main index */
|
||||
.directory-alt {
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
.directory-alt h3 {
|
||||
margin: 0px;
|
||||
margin-top: 1em;
|
||||
font-size: 11pt;
|
||||
}
|
||||
.directory-alt > h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.directory-alt p {
|
||||
margin: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.directory-alt div {
|
||||
display: none;
|
||||
margin: 0px;
|
||||
}
|
||||
.directory-alt img {
|
||||
vertical-align: -30%;
|
||||
}
|
1421
doc/hyperion.in.doxygen
Normal file
1421
doc/hyperion.in.doxygen
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@
|
||||
// Utils includes
|
||||
#include <utils/RgbColor.h>
|
||||
#include <utils/RgbImage.h>
|
||||
#include <utils/GrabbingMode.h>
|
||||
|
||||
// Forward class declaration
|
||||
class DispmanxFrameGrabber;
|
||||
@ -22,33 +23,64 @@ class DispmanxWrapper: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
/// Constructs the dispmanx frame grabber with a specified grab size and update rate.
|
||||
///
|
||||
/// @param[in] grabWidth The width of the grabbed image [pixels]
|
||||
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
||||
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
||||
/// @param[in] hyperion The instance of Hyperion used to write the led values
|
||||
///
|
||||
DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion);
|
||||
|
||||
///
|
||||
/// Destructor of this dispmanx frame grabber. Releases any claimed resources.
|
||||
///
|
||||
virtual ~DispmanxWrapper();
|
||||
|
||||
signals:
|
||||
void ledValues(const unsigned priority, const std::vector<RgbColor> ledColors, const unsigned timeout_ms);
|
||||
|
||||
public slots:
|
||||
///
|
||||
/// Starts the grabber wich produces led values with the specified update rate
|
||||
///
|
||||
void start();
|
||||
|
||||
///
|
||||
/// Performs a single frame grab and computes the led-colors
|
||||
///
|
||||
void action();
|
||||
|
||||
///
|
||||
/// Stops the grabber
|
||||
///
|
||||
void stop();
|
||||
|
||||
///
|
||||
/// \brief Set the grabbing mode
|
||||
/// \param mode The new grabbing mode
|
||||
///
|
||||
void setGrabbingMode(GrabbingMode mode);
|
||||
|
||||
private:
|
||||
/// The update rate [Hz]
|
||||
const int _updateInterval_ms;
|
||||
/// The timeout of the led colors [ms]
|
||||
const int _timeout_ms;
|
||||
/// The priority of the led colors [ms]
|
||||
const int _priority;
|
||||
|
||||
/// The timer for generating events with the specified update rate
|
||||
QTimer _timer;
|
||||
|
||||
/// The image used for grabbing frames
|
||||
RgbImage _image;
|
||||
/// The actual grabber
|
||||
DispmanxFrameGrabber * _frameGrabber;
|
||||
/// The processor for transforming images to led colors
|
||||
ImageProcessor * _processor;
|
||||
|
||||
/// The list with computed led colors
|
||||
std::vector<RgbColor> _ledColors;
|
||||
|
||||
/// Pointer to Hyperion for writing led values
|
||||
Hyperion * _hyperion;
|
||||
};
|
||||
|
||||
|
@ -19,65 +19,161 @@
|
||||
class HsvTransform;
|
||||
class ColorTransform;
|
||||
|
||||
///
|
||||
/// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through
|
||||
/// the priority muxer.
|
||||
///
|
||||
class Hyperion : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/// Type definition of the info structure used by the priority muxer
|
||||
typedef PriorityMuxer::InputInfo InputInfo;
|
||||
|
||||
///
|
||||
/// RGB-Color channel enumeration
|
||||
///
|
||||
enum Color
|
||||
{
|
||||
RED, GREEN, BLUE, INVALID
|
||||
};
|
||||
|
||||
///
|
||||
/// Enumeration of the possible color (color-channel) transforms
|
||||
///
|
||||
enum Transform
|
||||
{
|
||||
SATURATION_GAIN, VALUE_GAIN, THRESHOLD, GAMMA, BLACKLEVEL, WHITELEVEL
|
||||
};
|
||||
|
||||
///
|
||||
/// Constructs the Hyperion instance based on the given Json configuration
|
||||
///
|
||||
/// @param[in] jsonConfig The Json configuration
|
||||
///
|
||||
Hyperion(const Json::Value& jsonConfig);
|
||||
|
||||
///
|
||||
/// Destructor; cleans up resourcess
|
||||
///
|
||||
~Hyperion();
|
||||
|
||||
///
|
||||
/// Returns the number of attached leds
|
||||
///
|
||||
unsigned getLedCount() const;
|
||||
|
||||
void setColor(int priority, RgbColor &ledColor, const int timeout_ms);
|
||||
///
|
||||
/// Writes a single color to all the leds for the given time and priority
|
||||
///
|
||||
/// @param[in] priority The priority of the written color
|
||||
/// @param[in] ledColor The color to write to the leds
|
||||
/// @param[in] timeout_ms The time the leds are set to the given color [ms]
|
||||
///
|
||||
void setColor(int priority, const RgbColor &ledColor, const int timeout_ms);
|
||||
|
||||
void setColors(int priority, std::vector<RgbColor> &ledColors, const int timeout_ms);
|
||||
///
|
||||
/// Writes the given colors to all leds for the given time and priority
|
||||
///
|
||||
/// @param[in] priority The priority of the written colors
|
||||
/// @param[in] ledColors The colors to write to the leds
|
||||
/// @param[in] timeout_ms The time the leds are set to the given colors [ms]
|
||||
///
|
||||
void setColors(int priority, const std::vector<RgbColor> &ledColors, const int timeout_ms);
|
||||
|
||||
///
|
||||
/// Sets/Updates a part of the color transformation.
|
||||
///
|
||||
/// @param[in] transform The type of transform to configure
|
||||
/// @param[in] color The color channel to which the transform applies (only applicable for
|
||||
/// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL,
|
||||
/// Transform::WHITELEVEL)
|
||||
/// @param[in] value The new value for the given transform
|
||||
///
|
||||
void setTransform(Transform transform, Color color, double value);
|
||||
|
||||
///
|
||||
/// Clears the given priority channel. This will switch the led-colors to the colors of the next
|
||||
/// lower priority channel (or off if no more channels are set)
|
||||
///
|
||||
/// @param[in] priority The priority channel
|
||||
///
|
||||
void clear(int priority);
|
||||
|
||||
///
|
||||
/// Clears all priority channels. This will switch the leds off until a new priority is written.
|
||||
///
|
||||
void clearall();
|
||||
|
||||
///
|
||||
/// Returns the value of a specific color transform
|
||||
///
|
||||
/// @param[in] transform The type of transform
|
||||
/// @param[in] color The color channel to which the transform applies (only applicable for
|
||||
/// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL,
|
||||
/// Transform::WHITELEVEL)
|
||||
///
|
||||
/// @return The value of the specified color transform
|
||||
///
|
||||
double getTransform(Transform transform, Color color) const;
|
||||
|
||||
///
|
||||
/// Returns a list of active priorities
|
||||
///
|
||||
/// @return The list with priorities
|
||||
///
|
||||
QList<int> getActivePriorities() const;
|
||||
|
||||
///
|
||||
/// Returns the information of a specific priorrity channel
|
||||
///
|
||||
/// @param[in] priority The priority channel
|
||||
///
|
||||
/// @return The information of the given
|
||||
///
|
||||
/// @throw std::runtime_error when the priority channel does not exist
|
||||
///
|
||||
const InputInfo& getPriorityInfo(const int priority) const;
|
||||
|
||||
static LedDevice* constructDevice(const Json::Value & deviceConfig);
|
||||
static LedDevice * constructDevice(const Json::Value & deviceConfig);
|
||||
static LedString createLedString(const Json::Value & ledsConfig);
|
||||
static HsvTransform * createHsvTransform(const Json::Value & hsvConfig);
|
||||
static ColorTransform* createColorTransform(const Json::Value & colorConfig);
|
||||
static ColorTransform * createColorTransform(const Json::Value & colorConfig);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Updates the priority muxer with the current time and (re)writes the led color with applied
|
||||
/// transforms.
|
||||
///
|
||||
void update();
|
||||
|
||||
private:
|
||||
///
|
||||
/// Applies all color transmforms to the given list of colors. The transformation is performed
|
||||
/// in place.
|
||||
///
|
||||
/// @param colors The colors to be transformed
|
||||
///
|
||||
void applyTransform(std::vector<RgbColor>& colors) const;
|
||||
|
||||
/// The specifiation of the led frame construction and picture integration
|
||||
LedString _ledString;
|
||||
|
||||
/// The priority muxer
|
||||
PriorityMuxer _muxer;
|
||||
|
||||
/// The HSV Transform for applying Saturation and Value transforms
|
||||
HsvTransform * _hsvTransform;
|
||||
/// The RED-Channel (RGB) transform
|
||||
ColorTransform * _redTransform;
|
||||
/// The GREEN-Channel (RGB) transform
|
||||
ColorTransform * _greenTransform;
|
||||
/// The BLUE-Channel (RGB) transform
|
||||
ColorTransform * _blueTransform;
|
||||
|
||||
/// The actual LedDevice
|
||||
LedDevice* _device;
|
||||
|
||||
/// The timer for handling priority channel timeouts
|
||||
QTimer _timer;
|
||||
};
|
||||
|
@ -14,57 +14,72 @@ namespace hyperion {
|
||||
class BlackBorderProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ImageProcessor translates an RGB-image to RGB-values for the leds. The processing is
|
||||
* performed in two steps. First the average color per led-region is computed. Second a
|
||||
* color-tranform is applied based on a gamma-correction.
|
||||
*/
|
||||
///
|
||||
/// The ImageProcessor translates an RGB-image to RGB-values for the leds. The processing is
|
||||
/// performed in two steps. First the average color per led-region is computed. Second a
|
||||
/// color-tranform is applied based on a gamma-correction.
|
||||
///
|
||||
class ImageProcessor
|
||||
{
|
||||
public:
|
||||
~ImageProcessor();
|
||||
|
||||
/**
|
||||
* Specifies the width and height of 'incomming' images. This will resize the buffer-image to
|
||||
* match the given size.
|
||||
* NB All earlier obtained references will be invalid.
|
||||
*
|
||||
* @param[in] width The new width of the buffer-image
|
||||
* @param[in] height The new height of the buffer-image
|
||||
*/
|
||||
///
|
||||
/// Specifies the width and height of 'incomming' images. This will resize the buffer-image to
|
||||
/// match the given size.
|
||||
/// NB All earlier obtained references will be invalid.
|
||||
///
|
||||
/// @param[in] width The new width of the buffer-image
|
||||
/// @param[in] height The new height of the buffer-image
|
||||
///
|
||||
void setSize(const unsigned width, const unsigned height);
|
||||
|
||||
/**
|
||||
* Processes the image to a list of led colors. This will update the size of the buffer-image
|
||||
* if required and call the image-to-leds mapping to determine the mean color per led.
|
||||
*
|
||||
* @param[in] image The image to translate to led values
|
||||
*
|
||||
* @return The color value per led
|
||||
*/
|
||||
///
|
||||
/// Processes the image to a list of led colors. This will update the size of the buffer-image
|
||||
/// if required and call the image-to-leds mapping to determine the mean color per led.
|
||||
///
|
||||
/// @param[in] image The image to translate to led values
|
||||
///
|
||||
/// @return The color value per led
|
||||
///
|
||||
std::vector<RgbColor> process(const RgbImage& image);
|
||||
|
||||
/**
|
||||
* Determines the led colors of the image in the buffer.
|
||||
*
|
||||
* @param[out] ledColors The color value per led
|
||||
*/
|
||||
///
|
||||
/// Determines the led colors of the image in the buffer.
|
||||
///
|
||||
/// @param[in] image The image to translate to led values
|
||||
/// @param[out] ledColors The color value per led
|
||||
///
|
||||
void process(const RgbImage& image, std::vector<RgbColor>& ledColors);
|
||||
|
||||
private:
|
||||
/// Friend declaration of the factory for creating ImageProcessor's
|
||||
friend class ImageProcessorFactory;
|
||||
|
||||
///
|
||||
/// Constructs an image-processor for translating an image to led-color values based on the
|
||||
/// given led-string specification
|
||||
///
|
||||
/// @param[in] ledString The led-string specification
|
||||
///
|
||||
ImageProcessor(const LedString &ledString);
|
||||
|
||||
///
|
||||
/// Performs black-border detection (if enabled) on the given image
|
||||
///
|
||||
/// @param[in] image The image to perform black-border detection on
|
||||
///
|
||||
void verifyBorder(const RgbImage& image);
|
||||
private:
|
||||
/// The Led-string specification
|
||||
const LedString mLedString;
|
||||
|
||||
/// Flag the enables(true)/disabled(false) blackborder detector
|
||||
bool _enableBlackBorderRemoval;
|
||||
|
||||
/// The processor for black border detection
|
||||
hyperion::BlackBorderProcessor* _borderProcessor;
|
||||
|
||||
/// The mapping of image-pixels to leds
|
||||
hyperion::ImageToLedsMap* mImageToLeds;
|
||||
};
|
||||
|
||||
|
@ -11,16 +11,36 @@
|
||||
// Forward class declaration
|
||||
class ImageProcessor;
|
||||
|
||||
///
|
||||
/// The ImageProcessor is a singleton factor for creating ImageProcessors that translate images to
|
||||
/// led color values.
|
||||
///
|
||||
class ImageProcessorFactory
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Returns the 'singleton' instance (creates the singleton if it does not exist)
|
||||
///
|
||||
/// @return The singleton instance of the ImageProcessorFactory
|
||||
///
|
||||
static ImageProcessorFactory& getInstance();
|
||||
|
||||
public:
|
||||
///
|
||||
/// Initialises this factory with the given led-configuration
|
||||
///
|
||||
/// @param[in] ledString The led configuration
|
||||
///
|
||||
void init(const LedString& ledString);
|
||||
|
||||
///
|
||||
/// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller.
|
||||
///
|
||||
/// @return The newly created ImageProcessor
|
||||
///
|
||||
ImageProcessor* newImageProcessor() const;
|
||||
|
||||
private:
|
||||
/// The Led-string specification
|
||||
LedString _ledString;
|
||||
};
|
||||
|
@ -6,22 +6,27 @@
|
||||
// Utility includes
|
||||
#include <utils/RgbColor.h>
|
||||
|
||||
///
|
||||
/// Interface (pure virtual base class) for LedDevices.
|
||||
///
|
||||
class LedDevice
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Empty virtual destructor for pure virtual base class
|
||||
*/
|
||||
///
|
||||
/// Empty virtual destructor for pure virtual base class
|
||||
///
|
||||
virtual ~LedDevice()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the RGB-Color values to the leds.
|
||||
*
|
||||
* @param[in] ledValues The RGB-color per led
|
||||
*/
|
||||
///
|
||||
/// Writes the RGB-Color values to the leds.
|
||||
///
|
||||
/// @param[in] ledValues The RGB-color per led
|
||||
///
|
||||
/// @return Zero on success else negative
|
||||
///
|
||||
virtual int write(const std::vector<RgbColor>& ledValues) = 0;
|
||||
};
|
||||
|
@ -12,49 +12,67 @@
|
||||
// Forward class declarations
|
||||
namespace Json { class Value; }
|
||||
|
||||
/**
|
||||
* The Led structure contains the definition of the image portion used to determine a single led's
|
||||
* color.
|
||||
* <pre>
|
||||
* |--------------------image--|
|
||||
* | minX maxX |
|
||||
* | |-----|minY |
|
||||
* | | | |
|
||||
* | |-----|maxY |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* |---------------------------|
|
||||
* <endpre>
|
||||
*/
|
||||
///
|
||||
/// The Led structure contains the definition of the image portion used to determine a single led's
|
||||
/// color.
|
||||
/// @verbatim
|
||||
/// |--------------------image--|
|
||||
/// | minX maxX |
|
||||
/// | |-----|minY |
|
||||
/// | | | |
|
||||
/// | |-----|maxY |
|
||||
/// | |
|
||||
/// | |
|
||||
/// | |
|
||||
/// |---------------------------|
|
||||
/// @endverbatim
|
||||
///
|
||||
struct Led
|
||||
{
|
||||
/** The index of the led */
|
||||
/// The index of the led
|
||||
unsigned index;
|
||||
|
||||
/** The minimum vertical scan line included for this leds color */
|
||||
/// The minimum vertical scan line included for this leds color
|
||||
double minX_frac;
|
||||
/** The maximum vertical scan line included for this leds color */
|
||||
/// The maximum vertical scan line included for this leds color
|
||||
double maxX_frac;
|
||||
/** The minimum horizontal scan line included for this leds color */
|
||||
/// The minimum horizontal scan line included for this leds color
|
||||
double minY_frac;
|
||||
/** The maximum horizontal scan line included for this leds color */
|
||||
/// The maximum horizontal scan line included for this leds color
|
||||
double maxY_frac;
|
||||
};
|
||||
|
||||
///
|
||||
/// The LedString contains the image integration information of the leds
|
||||
///
|
||||
class LedString
|
||||
{
|
||||
public:
|
||||
static LedString construct(const Json::Value& ledConfig);
|
||||
|
||||
///
|
||||
/// Constructs the LedString with no leds
|
||||
///
|
||||
LedString();
|
||||
|
||||
///
|
||||
/// Destructor of this LedString
|
||||
///
|
||||
~LedString();
|
||||
|
||||
///
|
||||
/// Returns the led specifications
|
||||
///
|
||||
/// @return The list with led specifications
|
||||
///
|
||||
std::vector<Led>& leds();
|
||||
|
||||
///
|
||||
/// Returns the led specifications
|
||||
///
|
||||
/// @return The list with led specifications
|
||||
///
|
||||
const std::vector<Led>& leds() const;
|
||||
|
||||
private:
|
||||
/// The list with led specifications
|
||||
std::vector<Led> mLeds;
|
||||
};
|
||||
|
@ -15,43 +15,112 @@
|
||||
// Hyperion includes
|
||||
#include <hyperion/LedDevice.h>
|
||||
|
||||
///
|
||||
/// The PriorityMuxer handles the priority channels. Led values input is written to the priority map
|
||||
/// and the muxer keeps track of all active priorities. The current priority can be queried and per
|
||||
/// priority the led colors.
|
||||
///
|
||||
class PriorityMuxer
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// The information structure for a single priority channel
|
||||
///
|
||||
struct InputInfo
|
||||
{
|
||||
/// The priority of this channel
|
||||
int priority;
|
||||
|
||||
/// The absolute timeout of the channel
|
||||
int64_t timeoutTime_ms;
|
||||
/// The colors for each led of the channel
|
||||
std::vector<RgbColor> ledColors;
|
||||
};
|
||||
|
||||
///
|
||||
/// Constructs the PriorityMuxer for the given number of leds (used to switch to black when
|
||||
/// there are no priority channels
|
||||
///
|
||||
/// @param ledCount The number of leds
|
||||
///
|
||||
PriorityMuxer(int ledCount);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~PriorityMuxer();
|
||||
|
||||
///
|
||||
/// Returns the current priority
|
||||
///
|
||||
/// @return The current priority
|
||||
///
|
||||
int getCurrentPriority() const;
|
||||
|
||||
///
|
||||
/// Returns the state (enabled/disabled) of a specific priority channel
|
||||
/// @param priority The priority channel
|
||||
/// @return True if the priority channel exists else false
|
||||
///
|
||||
bool hasPriority(const int priority) const;
|
||||
|
||||
///
|
||||
/// Returns the number of active priorities
|
||||
///
|
||||
/// @return The list with active priorities
|
||||
///
|
||||
QList<int> getPriorities() const;
|
||||
|
||||
///
|
||||
/// Returns the information of a specified priority channel
|
||||
///
|
||||
/// @param priority The priority channel
|
||||
///
|
||||
/// @return The information for the specified priority channel
|
||||
///
|
||||
/// @throws std::runtime_error if the priority channel does not exist
|
||||
///
|
||||
const InputInfo& getInputInfo(const int priority) const;
|
||||
|
||||
///
|
||||
/// Sets/Updates the data for a priority channel
|
||||
///
|
||||
/// @param[in] priority The priority of the channel
|
||||
/// @param[in] ledColors The led colors of the priority channel
|
||||
/// @param[in] timeoutTime_ms The absolute timeout time of the channel
|
||||
///
|
||||
void setInput(const int priority, const std::vector<RgbColor>& ledColors, const int64_t timeoutTime_ms=-1);
|
||||
|
||||
///
|
||||
/// Clears the specified priority channel
|
||||
///
|
||||
/// @param[in] priority The priority of the channel to clear
|
||||
///
|
||||
void clearInput(const int priority);
|
||||
|
||||
///
|
||||
/// Clears all priority channels
|
||||
///
|
||||
void clearAll();
|
||||
|
||||
///
|
||||
/// Updates the current time. Channels with a configured time out will be checked and cleared if
|
||||
/// required.
|
||||
///
|
||||
/// @param[in] now The current time
|
||||
///
|
||||
void setCurrentTime(const int64_t& now);
|
||||
|
||||
private:
|
||||
/// The current priority (lowest value in _activeInputs)
|
||||
int _currentPriority;
|
||||
|
||||
/// The mapping from priority channel to led-information
|
||||
QMap<int, InputInfo> _activeInputs;
|
||||
|
||||
/// The information of the lowest priority channel
|
||||
InputInfo _lowestPriorityInfo;
|
||||
|
||||
/// The lowest possible priority, which is used when no priority channels are active
|
||||
const static int LOWEST_PRIORITY = std::numeric_limits<int>::max();
|
||||
};
|
||||
|
@ -12,25 +12,48 @@
|
||||
|
||||
class JsonClientConnection;
|
||||
|
||||
///
|
||||
/// This class creates a TCP server which accepts connections wich can then send
|
||||
/// in JSON encoded commands. This interface to Hyperion is used by hyperion-remote
|
||||
/// to control the leds
|
||||
///
|
||||
class JsonServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// JsonServer constructor
|
||||
/// @param hyperion Hyperion instance
|
||||
/// @param port port number on which to start listening for connections
|
||||
///
|
||||
JsonServer(Hyperion * hyperion, uint16_t port = 19444);
|
||||
~JsonServer();
|
||||
|
||||
///
|
||||
/// @return the port number on which this TCP listens for incoming connections
|
||||
///
|
||||
uint16_t getPort() const;
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Slot which is called when a client tries to create a new connection
|
||||
///
|
||||
void newConnection();
|
||||
|
||||
///
|
||||
/// Slot which is called when a client closes a connection
|
||||
/// @param connection The Connection object which is being closed
|
||||
///
|
||||
void closedConnection(JsonClientConnection * connection);
|
||||
|
||||
private:
|
||||
/// Hyperion instance
|
||||
Hyperion * _hyperion;
|
||||
|
||||
/// The TCP server object
|
||||
QTcpServer _server;
|
||||
|
||||
/// List with open connections
|
||||
QSet<JsonClientConnection *> _openConnections;
|
||||
};
|
||||
|
@ -15,36 +15,65 @@
|
||||
class ColorTransform
|
||||
{
|
||||
public:
|
||||
/// Default constructor
|
||||
ColorTransform();
|
||||
|
||||
/// Constructor
|
||||
/// @param threshold
|
||||
/// @param gamma
|
||||
/// @param blacklevel
|
||||
/// @param whitelevel
|
||||
ColorTransform(double threshold, double gamma, double blacklevel, double whitelevel);
|
||||
|
||||
/// Destructor
|
||||
~ColorTransform();
|
||||
|
||||
/// @return The current threshold value
|
||||
double getThreshold() const;
|
||||
|
||||
/// @param threshold New threshold value
|
||||
void setThreshold(double threshold);
|
||||
|
||||
/// @return The current gamma value
|
||||
double getGamma() const;
|
||||
|
||||
/// @param gamma New gamma value
|
||||
void setGamma(double gamma);
|
||||
|
||||
/// @return The current blacklevel value
|
||||
double getBlacklevel() const;
|
||||
|
||||
/// @param blacklevel New blacklevel value
|
||||
void setBlacklevel(double blacklevel);
|
||||
|
||||
/// @return The current whitelevel value
|
||||
double getWhitelevel() const;
|
||||
|
||||
/// @param whitelevel New whitelevel value
|
||||
void setWhitelevel(double whitelevel);
|
||||
|
||||
/// get the transformed value for the given byte value
|
||||
/// Transform the given byte value
|
||||
/// @param input The input color byte
|
||||
/// @return The transformed byte value
|
||||
uint8_t transform(uint8_t input) const
|
||||
{
|
||||
return _mapping[input];
|
||||
}
|
||||
|
||||
private:
|
||||
/// (re)-initilize the color mapping
|
||||
void initializeMapping();
|
||||
|
||||
private:
|
||||
/// The threshold value
|
||||
double _threshold;
|
||||
/// The gamma value
|
||||
double _gamma;
|
||||
/// The blacklevel
|
||||
double _blacklevel;
|
||||
/// The whitelevel
|
||||
double _whitelevel;
|
||||
|
||||
/// The mapping from input color to output color
|
||||
uint8_t _mapping[256];
|
||||
};
|
||||
|
11
include/utils/GrabbingMode.h
Normal file
11
include/utils/GrabbingMode.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
enum GrabbingMode
|
||||
{
|
||||
GRABBINGMODE_OFF,
|
||||
GRABBINGMODE_VIDEO,
|
||||
GRABBINGMODE_PHOTO,
|
||||
GRABBINGMODE_AUDIO,
|
||||
GRABBINGMODE_MENU,
|
||||
GRABBINGMODE_INVALID
|
||||
};
|
@ -3,28 +3,104 @@
|
||||
// STL includes
|
||||
#include <cstdint>
|
||||
|
||||
///
|
||||
/// Color transformation to adjust the saturation and value of a RGB color value
|
||||
///
|
||||
class HsvTransform
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Default constructor
|
||||
///
|
||||
HsvTransform();
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
/// @param saturationGain The used saturation gain
|
||||
/// @param valueGain The used value gain
|
||||
///
|
||||
HsvTransform(double saturationGain, double valueGain);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~HsvTransform();
|
||||
|
||||
///
|
||||
/// Updates the saturation gain
|
||||
///
|
||||
/// @param saturationGain New saturationGain
|
||||
///
|
||||
void setSaturationGain(double saturationGain);
|
||||
|
||||
///
|
||||
/// Returns the saturation gain
|
||||
///
|
||||
/// @return The current Saturation gain
|
||||
///
|
||||
double getSaturationGain() const;
|
||||
|
||||
///
|
||||
/// Updates the value gain
|
||||
///
|
||||
/// @param valueGain New value gain
|
||||
///
|
||||
void setValueGain(double valueGain);
|
||||
|
||||
///
|
||||
/// Returns the value gain
|
||||
///
|
||||
/// @return The current value gain
|
||||
///
|
||||
double getValueGain() const;
|
||||
|
||||
///
|
||||
/// Apply the transform the the given RGB values.
|
||||
///
|
||||
/// @param red The red color component
|
||||
/// @param green The green color component
|
||||
/// @param blue The blue color component
|
||||
///
|
||||
/// @note The values are updated in place.
|
||||
///
|
||||
void transform(uint8_t & red, uint8_t & green, uint8_t & blue) const;
|
||||
|
||||
/// integer version of the conversion are faster, but a little less accurate
|
||||
/// all values are unsigned 8 bit values and scaled between 0 and 255 except
|
||||
/// for the hue which is a 16 bit number and scaled between 0 and 360
|
||||
///
|
||||
/// Translates an RGB (red, green, blue) color to an HSV (hue, saturation, value) color
|
||||
///
|
||||
/// @param[in] red The red RGB-component
|
||||
/// @param[in] green The green RGB-component
|
||||
/// @param[in] blue The blue RGB-component
|
||||
/// @param[out] hue The hue HSV-component
|
||||
/// @param[out] saturation The saturation HSV-component
|
||||
/// @param[out] value The value HSV-component
|
||||
///
|
||||
/// @note Integer version of the conversion are faster, but a little less accurate all values
|
||||
/// are unsigned 8 bit values and scaled between 0 and 255 except for the hue which is a 16 bit
|
||||
/// number and scaled between 0 and 360
|
||||
///
|
||||
static void rgb2hsv(uint8_t red, uint8_t green, uint8_t blue, uint16_t & hue, uint8_t & saturation, uint8_t & value);
|
||||
|
||||
///
|
||||
/// Translates an HSV (hue, saturation, value) color to an RGB (red, green, blue) color
|
||||
///
|
||||
/// @param[in] hue The hue HSV-component
|
||||
/// @param[in] saturation The saturation HSV-component
|
||||
/// @param[in] value The value HSV-component
|
||||
/// @param[out] red The red RGB-component
|
||||
/// @param[out] green The green RGB-component
|
||||
/// @param[out] blue The blue RGB-component
|
||||
///
|
||||
/// @note Integer version of the conversion are faster, but a little less accurate all values
|
||||
/// are unsigned 8 bit values and scaled between 0 and 255 except for the hue which is a 16 bit
|
||||
/// number and scaled between 0 and 360
|
||||
///
|
||||
static void hsv2rgb(uint16_t hue, uint8_t saturation, uint8_t value, uint8_t & red, uint8_t & green, uint8_t & blue);
|
||||
|
||||
private:
|
||||
/// The saturation gain
|
||||
double _saturationGain;
|
||||
/// The value gain
|
||||
double _valueGain;
|
||||
};
|
||||
|
@ -8,31 +8,57 @@
|
||||
// Forward class declaration
|
||||
struct RgbColor;
|
||||
|
||||
///
|
||||
/// Plain-Old-Data structure containing the red-green-blue color specification. Size of the
|
||||
/// structure is exactly 3-bytes for easy writing to led-device
|
||||
///
|
||||
struct RgbColor
|
||||
{
|
||||
/// The red color channel
|
||||
uint8_t red;
|
||||
/// The green color channel
|
||||
uint8_t green;
|
||||
/// The blue color channel
|
||||
uint8_t blue;
|
||||
|
||||
/// 'Black' RgbColor (0, 0, 0)
|
||||
static RgbColor BLACK;
|
||||
/// 'Red' RgbColor (255, 0, 0)
|
||||
static RgbColor RED;
|
||||
/// 'Green' RgbColor (0, 255, 0)
|
||||
static RgbColor GREEN;
|
||||
/// 'Blue' RgbColor (0, 0, 255)
|
||||
static RgbColor BLUE;
|
||||
/// 'Yellow' RgbColor (255, 255, 0)
|
||||
static RgbColor YELLOW;
|
||||
/// 'White' RgbColor (255, 255, 255)
|
||||
static RgbColor WHITE;
|
||||
|
||||
///
|
||||
/// Checks is this exactly matches another color
|
||||
///
|
||||
/// @param other The other color
|
||||
///
|
||||
/// @return True if the colors are identical
|
||||
///
|
||||
inline bool operator==(const RgbColor& other) const
|
||||
{
|
||||
return red == other.red && green == other.green && blue == other.blue;
|
||||
}
|
||||
};
|
||||
|
||||
/// Assert to ensure that the size of the structure is 'only' 3 bytes
|
||||
static_assert(sizeof(RgbColor) == 3, "Incorrect size of RgbColor");
|
||||
|
||||
|
||||
///
|
||||
/// Stream operator to write RgbColor to an outputstream (format "'{'[red]','[green]','[blue]'}'")
|
||||
///
|
||||
/// @param os The output stream
|
||||
/// @param color The color to write
|
||||
/// @return The output stream (with the color written to it)
|
||||
///
|
||||
inline std::ostream& operator<<(std::ostream& os, const RgbColor& color)
|
||||
{
|
||||
os << "{" << unsigned(color.red) << "," << unsigned(color.green) << "," << unsigned(color.blue) << "}";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
@ -8,57 +8,127 @@
|
||||
// Local includes
|
||||
#include "RgbColor.h"
|
||||
|
||||
///
|
||||
/// The RgbImage holds a 2D matrix of RgbColors's (or image). Width and height of the image are
|
||||
/// fixed at construction.
|
||||
///
|
||||
class RgbImage
|
||||
{
|
||||
public:
|
||||
|
||||
///
|
||||
/// Constructor for an image with specified width and height
|
||||
///
|
||||
/// @param width The width of the image
|
||||
/// @param height The height of the image
|
||||
/// @param background The color of the image (default = BLACK)
|
||||
///
|
||||
RgbImage(const unsigned width, const unsigned height, const RgbColor background = RgbColor::BLACK);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~RgbImage();
|
||||
|
||||
///
|
||||
/// Returns the width of the image
|
||||
///
|
||||
/// @return The width of the image
|
||||
///
|
||||
inline unsigned width() const
|
||||
{
|
||||
return mWidth;
|
||||
return _width;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns the height of the image
|
||||
///
|
||||
/// @return The height of the image
|
||||
///
|
||||
inline unsigned height() const
|
||||
{
|
||||
return mHeight;
|
||||
return _height;
|
||||
}
|
||||
|
||||
///
|
||||
/// Sets the color of a specific pixel in the image
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
/// @param color The new color
|
||||
///
|
||||
void setPixel(const unsigned x, const unsigned y, const RgbColor color);
|
||||
|
||||
///
|
||||
/// Returns a const reference to a specified pixel in the image
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return const reference to specified pixel
|
||||
///
|
||||
const RgbColor& operator()(const unsigned x, const unsigned y) const;
|
||||
|
||||
///
|
||||
/// Returns a reference to a specified pixel in the image
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return reference to specified pixel
|
||||
///
|
||||
RgbColor& operator()(const unsigned x, const unsigned y);
|
||||
|
||||
///
|
||||
/// Copies another image into this image. The images should have exactly the same size.
|
||||
///
|
||||
/// @param other The image to copy into this
|
||||
///
|
||||
inline void copy(const RgbImage& other)
|
||||
{
|
||||
assert(other.mWidth == mWidth);
|
||||
assert(other.mHeight == mHeight);
|
||||
assert(other._width == _width);
|
||||
assert(other._height == _height);
|
||||
|
||||
memcpy(mColors, other.mColors, mWidth*mHeight*sizeof(RgbColor));
|
||||
memcpy(mColors, other.mColors, _width*_height*sizeof(RgbColor));
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a memory pointer to the first pixel in the image
|
||||
/// @return The memory pointer to the first pixel
|
||||
///
|
||||
RgbColor* memptr()
|
||||
{
|
||||
return mColors;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a const memory pointer to the first pixel in the image
|
||||
/// @return The const memory pointer to the first pixel
|
||||
///
|
||||
const RgbColor* memptr() const
|
||||
{
|
||||
return mColors;
|
||||
}
|
||||
private:
|
||||
|
||||
///
|
||||
/// Translate x and y coordinate to index of the underlying vector
|
||||
///
|
||||
/// @param x The x index
|
||||
/// @param y The y index
|
||||
///
|
||||
/// @return The index into the underlying data-vector
|
||||
///
|
||||
inline unsigned toIndex(const unsigned x, const unsigned y) const
|
||||
{
|
||||
return y*mWidth + x;
|
||||
return y*_width + x;
|
||||
}
|
||||
|
||||
private:
|
||||
const unsigned mWidth;
|
||||
const unsigned mHeight;
|
||||
/// The width of the image
|
||||
const unsigned _width;
|
||||
/// The height of the image
|
||||
const unsigned _height;
|
||||
|
||||
/** The colors of the image */
|
||||
RgbColor* mColors;
|
||||
|
@ -7,61 +7,186 @@
|
||||
// jsoncpp includes
|
||||
#include <json/json.h>
|
||||
|
||||
/**
|
||||
* JsonSchemaChecker is a very basic implementation of json schema.
|
||||
* The json schema definition draft can be found at
|
||||
* http://tools.ietf.org/html/draft-zyp-json-schema-03
|
||||
*
|
||||
* The following keywords are supported:
|
||||
* - type
|
||||
* - required
|
||||
* - properties
|
||||
* - items
|
||||
* - enum
|
||||
* - minimum
|
||||
* - maximum
|
||||
*/
|
||||
|
||||
/// JsonSchemaChecker is a very basic implementation of json schema.
|
||||
/// The json schema definition draft can be found at
|
||||
/// http://tools.ietf.org/html/draft-zyp-json-schema-03
|
||||
///
|
||||
/// The following keywords are supported:
|
||||
/// - type
|
||||
/// - required
|
||||
/// - properties
|
||||
/// - items
|
||||
/// - enum
|
||||
/// - minimum
|
||||
/// - maximum
|
||||
/// - addtionalProperties
|
||||
/// - minItems
|
||||
/// - maxItems
|
||||
///
|
||||
/// And the non-standard:
|
||||
/// - dependencies
|
||||
class JsonSchemaChecker
|
||||
{
|
||||
public:
|
||||
JsonSchemaChecker();
|
||||
virtual ~JsonSchemaChecker();
|
||||
|
||||
///
|
||||
/// @param schema The schema to use
|
||||
/// @return true upon succes
|
||||
///
|
||||
bool setSchema(const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// @brief Validate a JSON structure
|
||||
/// @param value The JSON value to check
|
||||
/// @return true when the arguments is valid according to the schema
|
||||
///
|
||||
bool validate(const Json::Value & value);
|
||||
|
||||
///
|
||||
/// @return A list of error messages
|
||||
///
|
||||
const std::list<std::string> & getMessages() const;
|
||||
|
||||
private:
|
||||
void collectReferences(const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Validates a json-value against a given schema. Results are stored in the members of this
|
||||
/// class (_error & _messages)
|
||||
///
|
||||
/// @param[in] value The value to validate
|
||||
/// @param[in] schema The schema against which the value is validated
|
||||
///
|
||||
void validate(const Json::Value &value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Adds the given message to the message-queue (with reference to current line-number)
|
||||
///
|
||||
/// @param[in] message The message to add to the queue
|
||||
///
|
||||
void setMessage(const std::string & message);
|
||||
|
||||
///
|
||||
/// Retrieves all references from the json-value as specified by the schema
|
||||
///
|
||||
/// @param[in] value The json-value
|
||||
/// @param[in] schema The schema
|
||||
///
|
||||
void collectDependencies(const Json::Value & value, const Json::Value &schema);
|
||||
|
||||
private:
|
||||
// attribute check functions
|
||||
///
|
||||
/// Checks if the given value is of the specified type. If the type does not match _error is set
|
||||
/// to true and an error-message is added to the message-queue
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The specified type (as json-value)
|
||||
///
|
||||
void checkType(const Json::Value & value, const Json::Value & schema);
|
||||
///
|
||||
/// Checks is required properties of an json-object exist and if all properties are of the
|
||||
/// correct format. If this is not the case _error is set to true and an error-message is added
|
||||
/// to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given json-object
|
||||
/// @param[in] schema The schema of the json-object
|
||||
///
|
||||
void checkProperties(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Verifies the additional configured properties of an json-object. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The given json-object
|
||||
/// @param schema The schema for the json-object
|
||||
/// @param ignoredProperties The properties that were ignored
|
||||
///
|
||||
void checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties);
|
||||
|
||||
///
|
||||
/// Checks if references are configued and used correctly. If this is not the case _error is set
|
||||
/// to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The given json-object
|
||||
/// @param schemaLink The schema of the json-object
|
||||
///
|
||||
void checkDependencies(const Json::Value & value, const Json::Value & schemaLink);
|
||||
|
||||
///
|
||||
/// Checks if the given value is larger or equal to the specified value. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The minimum value (as json-value)
|
||||
///
|
||||
void checkMinimum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if the given value is smaller or equal to the specified value. If this is not the
|
||||
/// case _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param[in] value The given value
|
||||
/// @param[in] schema The maximum value (as json-value)
|
||||
///
|
||||
void checkMaximum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Validates all the items of an array.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The schema for the items in the array
|
||||
///
|
||||
void checkItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array has at least a minimum number of items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The minimum size specification (as json-value)
|
||||
///
|
||||
void checkMinItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array has at most a maximum number of items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema The maximum size specification (as json-value)
|
||||
///
|
||||
void checkMaxItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if a given array contains only unique items. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The json-array
|
||||
/// @param schema Bool to enable the check (as json-value)
|
||||
///
|
||||
void checkUniqueItems(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
///
|
||||
/// Checks if an enum value is actually a valid value for that enum. If this is not the case
|
||||
/// _error is set to true and an error-message is added to the message-queue.
|
||||
///
|
||||
/// @param value The enum value
|
||||
/// @param schema The enum schema definition
|
||||
///
|
||||
void checkEnum(const Json::Value & value, const Json::Value & schema);
|
||||
|
||||
private:
|
||||
/// The schema of the entire json-configuration
|
||||
Json::Value _schema;
|
||||
|
||||
/// The current location into a json-configuration structure being checked
|
||||
std::list<std::string> _currentPath;
|
||||
/// The result messages collected during the schema verification
|
||||
std::list<std::string> _messages;
|
||||
/// Flag indicating an error occured during validation
|
||||
bool _error;
|
||||
|
||||
/// A list with references (string => json-value)
|
||||
std::map<std::string, const Json::Value *> _references; // ref 2 value
|
||||
};
|
||||
|
@ -14,37 +14,80 @@
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
/// Check if XBMC is playing something. When it does not, this class will send all black data Hyperion to
|
||||
/// override (grabbed) data with a lower priority
|
||||
// Utils includes
|
||||
#include <utils/GrabbingMode.h>
|
||||
|
||||
///
|
||||
/// This class will check if XBMC is playing something. When it does not, this class will send all black data to Hyperion.
|
||||
/// This allows grabbed screen data to be overriden while in the XBMC menus.
|
||||
///
|
||||
/// Note: The json TCP server needs to be enabled manually in XBMC in System/Settings/Network/Services
|
||||
///
|
||||
class XBMCVideoChecker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XBMCVideoChecker(const std::string & address, uint16_t port, uint64_t interval, Hyperion * hyperion, int priority);
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
/// @param address Network address of the XBMC instance
|
||||
/// @param port Port number to use (XBMC default = 9090)
|
||||
/// @param interval The interval at which XBMC is polled
|
||||
/// @param grabVideo Whether or not to grab when the XBMC video player is playing
|
||||
/// @param grabPhoto Whether or not to grab when the XBMC photo player is playing
|
||||
/// @param grabAudio Whether or not to grab when the XBMC audio player is playing
|
||||
/// @param grabMenu Whether or not to grab when nothing is playing (in XBMC menu)
|
||||
///
|
||||
XBMCVideoChecker(const std::string & address, uint16_t port, uint64_t interval, bool grabVideo, bool grabPhoto, bool grabAudio, bool grabMenu);
|
||||
|
||||
///
|
||||
/// Start polling XBMC
|
||||
///
|
||||
void start();
|
||||
|
||||
signals:
|
||||
void grabbingMode(GrabbingMode grabbingMode);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Send a request to XBMC
|
||||
///
|
||||
void sendRequest();
|
||||
|
||||
///
|
||||
/// Receive a reply from XBMC
|
||||
///
|
||||
void receiveReply();
|
||||
|
||||
private:
|
||||
/// The network address of the XBMC instance
|
||||
const QString _address;
|
||||
|
||||
/// The port number of XBMC
|
||||
const uint16_t _port;
|
||||
|
||||
/// The JSON-RPC request message
|
||||
const QByteArray _request;
|
||||
|
||||
/// The timer that schedules XBMC queries
|
||||
QTimer _timer;
|
||||
|
||||
/// The QT TCP Socket with connection to XBMC
|
||||
QTcpSocket _socket;
|
||||
|
||||
Hyperion * _hyperion;
|
||||
/// Flag indicating whether or not to grab when the XBMC video player is playing
|
||||
bool _grabVideo;
|
||||
|
||||
const int _priority;
|
||||
/// Flag indicating whether or not to grab when the XBMC photo player is playing
|
||||
bool _grabPhoto;
|
||||
|
||||
/// Flag indicating whether or not to grab when the XBMC audio player is playing
|
||||
bool _grabAudio;
|
||||
|
||||
/// Flag indicating whether or not to grab when XBMC is playing nothing (in menu)
|
||||
bool _grabMenu;
|
||||
|
||||
/// Previous emitted grab state
|
||||
GrabbingMode _previousMode;
|
||||
};
|
||||
|
||||
|
35
libsrc/bootsequence/AbstractBootSequence.cpp
Normal file
35
libsrc/bootsequence/AbstractBootSequence.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "AbstractBootSequence.h"
|
||||
|
||||
AbstractBootSequence::AbstractBootSequence(Hyperion * hyperion, const int64_t interval, const unsigned iterationCnt) :
|
||||
_timer(),
|
||||
_hyperion(hyperion),
|
||||
_priority(0),
|
||||
_iterationCounter(iterationCnt)
|
||||
{
|
||||
_timer.setInterval(interval);
|
||||
_timer.setSingleShot(false);
|
||||
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
|
||||
}
|
||||
|
||||
void AbstractBootSequence::start()
|
||||
{
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void AbstractBootSequence::update()
|
||||
{
|
||||
if (_iterationCounter == 0)
|
||||
{
|
||||
_timer.stop();
|
||||
_hyperion->clear(_priority);
|
||||
return;
|
||||
}
|
||||
|
||||
// Obtain the next led-colors from the child-class
|
||||
const std::vector<RgbColor>& colors = nextColors();
|
||||
// Write the colors to hyperion
|
||||
_hyperion->setColors(_priority, colors, -1);
|
||||
|
||||
// Decrease the loop count
|
||||
--_iterationCounter;
|
||||
}
|
62
libsrc/bootsequence/AbstractBootSequence.h
Normal file
62
libsrc/bootsequence/AbstractBootSequence.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
// QT includes
|
||||
#include <QTimer>
|
||||
|
||||
// Bootsequence includes
|
||||
#include <bootsequence/BootSequence.h>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
///
|
||||
/// The AbstractBootSequence is an 'abstract' implementation of the BootSequence that handles the
|
||||
/// event generation and Hyperion connection. Subclasses only need to specify the interval and
|
||||
/// return the colors for the leds for each iteration.
|
||||
///
|
||||
class AbstractBootSequence : public QObject, public BootSequence
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructs the AbstractBootSequence with the given parameters
|
||||
///
|
||||
/// @param hyperion The Hyperion instance
|
||||
/// @param interval The interval between new led colors
|
||||
/// @param iterationCnt The number of iteration performed by the boot sequence
|
||||
///
|
||||
AbstractBootSequence(Hyperion * hyperion, const int64_t interval, const unsigned iterationCnt);
|
||||
|
||||
///
|
||||
/// Starts the boot-sequence
|
||||
///
|
||||
virtual void start();
|
||||
|
||||
protected slots:
|
||||
///
|
||||
/// Timer slot for handling each interval of the boot-sequence
|
||||
///
|
||||
void update();
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Child-classes must implement this by returning the next led colors in the sequence
|
||||
///
|
||||
/// @return The next led colors in the boot sequence
|
||||
///
|
||||
virtual const std::vector<RgbColor>& nextColors() = 0;
|
||||
|
||||
private:
|
||||
/// The timer used to generate an 'update' signal every interval
|
||||
QTimer _timer;
|
||||
|
||||
/// The Hyperion instance
|
||||
Hyperion * _hyperion;
|
||||
/// The priority of the boot sequence
|
||||
int _priority;
|
||||
|
||||
/// The counter of the number of iterations left
|
||||
int _iterationCounter;
|
||||
};
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
// Local Bootsequence includes
|
||||
#include "RainbowBootSequence.h"
|
||||
#include "KittBootSequence.h"
|
||||
|
||||
BootSequence * BootSequenceFactory::createBootSequence(Hyperion * hyperion, const Json::Value & jsonConfig)
|
||||
{
|
||||
@ -20,11 +21,8 @@ BootSequence * BootSequenceFactory::createBootSequence(Hyperion * hyperion, cons
|
||||
}
|
||||
else if (type == "knightrider")
|
||||
{
|
||||
std::cout << "KNIGHT RIDER NOT IMPLEMENTED YET" << std::endl;
|
||||
return nullptr;
|
||||
// const unsigned duration_ms = jsonConfig["duration_ms"].asUint();
|
||||
// const std::string colorStr = jsonConfig["color"].asString();
|
||||
// return new KnightRiderSequence(hyperion, duration_ms);
|
||||
const unsigned duration_ms = jsonConfig["duration_ms"].asUInt();
|
||||
return new KittBootSequence(hyperion, duration_ms);
|
||||
}
|
||||
|
||||
std::cerr << "Unknown boot-sequence selected; boot-sequence disabled." << std::endl;
|
||||
|
@ -5,17 +5,21 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/bootsequence)
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
SET(BootsequenceQT_HEADERS
|
||||
${CURRENT_SOURCE_DIR}/RainbowBootSequence.h
|
||||
${CURRENT_SOURCE_DIR}/AbstractBootSequence.h
|
||||
)
|
||||
|
||||
SET(BootsequenceHEADERS
|
||||
${CURRENT_HEADER_DIR}/BootSequence.h
|
||||
${CURRENT_HEADER_DIR}/BootSequenceFactory.h
|
||||
${CURRENT_SOURCE_DIR}/RainbowBootSequence.h
|
||||
${CURRENT_SOURCE_DIR}/KittBootSequence.h
|
||||
)
|
||||
|
||||
SET(BootsequenceSOURCES
|
||||
${CURRENT_SOURCE_DIR}/AbstractBootSequence.cpp
|
||||
${CURRENT_SOURCE_DIR}/BootSequenceFactory.cpp
|
||||
${CURRENT_SOURCE_DIR}/RainbowBootSequence.cpp
|
||||
${CURRENT_SOURCE_DIR}/KittBootSequence.cpp
|
||||
)
|
||||
|
||||
QT4_WRAP_CPP(BootsequenceHEADERS_MOC ${BootsequenceQT_HEADERS})
|
||||
|
67
libsrc/bootsequence/KittBootSequence.cpp
Normal file
67
libsrc/bootsequence/KittBootSequence.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/ImageProcessorFactory.h>
|
||||
|
||||
// Local-Bootsequence includes
|
||||
#include "KittBootSequence.h"
|
||||
|
||||
KittBootSequence::KittBootSequence(Hyperion * hyperion, const unsigned duration_ms) :
|
||||
AbstractBootSequence(hyperion, 100, duration_ms/100),
|
||||
_processor(ImageProcessorFactory::getInstance().newImageProcessor()),
|
||||
_image(9, 1),
|
||||
_ledColors(hyperion->getLedCount(), RgbColor::BLACK),
|
||||
_forwardMove(false),
|
||||
_currentLight(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
KittBootSequence::~KittBootSequence()
|
||||
{
|
||||
delete _processor;
|
||||
}
|
||||
|
||||
const std::vector<RgbColor>& KittBootSequence::nextColors()
|
||||
{
|
||||
|
||||
// Switch the previous light 'off'
|
||||
_image(_currentLight, 0) = RgbColor::BLACK;
|
||||
|
||||
// Move the current to the next light
|
||||
moveNextLight();
|
||||
|
||||
// Switch the current light 'on'
|
||||
_image(_currentLight, 0) = RgbColor::RED;
|
||||
|
||||
|
||||
// Translate the 'image' to led colors
|
||||
_processor->process(_image, _ledColors);
|
||||
|
||||
// Return the colors
|
||||
return _ledColors;
|
||||
}
|
||||
|
||||
void KittBootSequence::moveNextLight()
|
||||
{
|
||||
// Increase/Decrease the current light
|
||||
if (_forwardMove)
|
||||
{
|
||||
++_currentLight;
|
||||
if (_currentLight == _image.width())
|
||||
{
|
||||
_forwardMove = false;
|
||||
--_currentLight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_currentLight == 0)
|
||||
{
|
||||
_forwardMove = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
--_currentLight;
|
||||
}
|
||||
}
|
||||
}
|
56
libsrc/bootsequence/KittBootSequence.h
Normal file
56
libsrc/bootsequence/KittBootSequence.h
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Bootsequence includes
|
||||
#include "AbstractBootSequence.h"
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
///
|
||||
/// The KITT BootSequence is a boot sequence inspired by the Knight Rider car: Knight Industries Two
|
||||
/// Thousand (aka KITT)
|
||||
///
|
||||
class KittBootSequence : public AbstractBootSequence
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructs the KITT BootSequence
|
||||
///
|
||||
/// @param[in] hyperion The Hyperion instance
|
||||
/// @param[in] duration_ms The length of the sequence [ms]
|
||||
///
|
||||
KittBootSequence(Hyperion * hyperion, const unsigned duration_ms);
|
||||
|
||||
///
|
||||
/// Destructor, deletes the processor
|
||||
///
|
||||
virtual ~KittBootSequence();
|
||||
|
||||
///
|
||||
/// Returns the next led color sequence
|
||||
///
|
||||
/// @return The next colors for the leds
|
||||
///
|
||||
virtual const std::vector<RgbColor>& nextColors();
|
||||
|
||||
private:
|
||||
/// Image processor to compute led-colors from the image
|
||||
ImageProcessor * _processor;
|
||||
|
||||
/// 1D-Image of the KITT-grill contains a single red pixel and the rest black
|
||||
RgbImage _image;
|
||||
|
||||
/// The vector with led-colors
|
||||
std::vector<RgbColor> _ledColors;
|
||||
|
||||
/// Direction the red-light is currently moving
|
||||
bool _forwardMove = true;
|
||||
/// The location of the current red-light
|
||||
unsigned _currentLight = 0;
|
||||
|
||||
/// Moves the current light to the next (increase or decrease depending on direction)
|
||||
void moveNextLight();
|
||||
};
|
||||
|
@ -6,49 +6,25 @@
|
||||
#include "RainbowBootSequence.h"
|
||||
|
||||
RainbowBootSequence::RainbowBootSequence(Hyperion * hyperion, const unsigned duration_ms) :
|
||||
_timer(),
|
||||
_hyperion(hyperion),
|
||||
_priority(0),
|
||||
_ledColors(hyperion->getLedCount()),
|
||||
_iterationCounter(hyperion->getLedCount())
|
||||
AbstractBootSequence(hyperion, duration_ms/hyperion->getLedCount(), hyperion->getLedCount()),
|
||||
_ledColors(hyperion->getLedCount())
|
||||
{
|
||||
for (unsigned iLed=0; iLed<_hyperion->getLedCount(); ++iLed)
|
||||
for (unsigned iLed=0; iLed<hyperion->getLedCount(); ++iLed)
|
||||
{
|
||||
RgbColor& color = _ledColors[iLed];
|
||||
HsvTransform::hsv2rgb(iLed*360/_hyperion->getLedCount(), 255, 255, color.red, color.green, color.blue);
|
||||
HsvTransform::hsv2rgb(iLed*360/hyperion->getLedCount(), 255, 255, color.red, color.green, color.blue);
|
||||
}
|
||||
|
||||
_timer.setInterval(duration_ms/_hyperion->getLedCount());
|
||||
_timer.setSingleShot(false);
|
||||
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
|
||||
}
|
||||
|
||||
void RainbowBootSequence::start()
|
||||
const std::vector<RgbColor>& RainbowBootSequence::nextColors()
|
||||
{
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
void RainbowBootSequence::update()
|
||||
{
|
||||
if (_iterationCounter == 0)
|
||||
// Rotate the colors left
|
||||
const RgbColor headColor = _ledColors.front();
|
||||
for (unsigned i=1; i<_ledColors.size(); ++i)
|
||||
{
|
||||
_timer.stop();
|
||||
_hyperion->clear(_priority);
|
||||
_ledColors[i-1] = _ledColors[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rotate the colors left
|
||||
const RgbColor headColor = _ledColors.front();
|
||||
for (unsigned i=1; i<_ledColors.size(); ++i)
|
||||
{
|
||||
_ledColors[i-1] = _ledColors[i];
|
||||
}
|
||||
_ledColors.back() = headColor;
|
||||
_ledColors.back() = headColor;
|
||||
|
||||
// Write the colors to hyperion
|
||||
_hyperion->setColors(_priority, _ledColors, -1);
|
||||
|
||||
// Decrease the loop count
|
||||
--_iterationCounter;
|
||||
}
|
||||
return _ledColors;
|
||||
}
|
||||
|
@ -5,19 +5,14 @@
|
||||
#include <QTimer>
|
||||
|
||||
// Bootsequence include
|
||||
#include <bootsequence/BootSequence.h>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
#include "AbstractBootSequence.h"
|
||||
|
||||
///
|
||||
/// The RainborBootSequence shows a 'rainbow' (all lights have a different color). The rainbow is
|
||||
/// rotated over each led during the length of the sequence.
|
||||
///
|
||||
class RainbowBootSequence : public QObject, public BootSequence
|
||||
class RainbowBootSequence : public AbstractBootSequence
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructs the rainbow boot-sequence. Hyperion is used for writing the led colors. The given
|
||||
@ -28,27 +23,13 @@ public:
|
||||
///
|
||||
RainbowBootSequence(Hyperion * hyperion, const unsigned duration_ms);
|
||||
|
||||
///
|
||||
/// Starts the boot-sequence
|
||||
///
|
||||
virtual void start();
|
||||
|
||||
private slots:
|
||||
protected:
|
||||
///
|
||||
/// Moves the rainbow one led further
|
||||
///
|
||||
void update();
|
||||
const std::vector<RgbColor>& nextColors();
|
||||
|
||||
private:
|
||||
/// The timer used to generate an 'update' signal every interval
|
||||
QTimer _timer;
|
||||
|
||||
/// The Hyperion instance
|
||||
Hyperion * _hyperion;
|
||||
|
||||
/// The priority of the boot sequence
|
||||
int _priority;
|
||||
|
||||
/// The current color of the boot sequence (the rainbow)
|
||||
std::vector<RgbColor> _ledColors;
|
||||
/// The counter of the number of iterations left
|
||||
|
@ -60,3 +60,11 @@ void DispmanxWrapper::stop()
|
||||
// Stop the timer, effectivly stopping the process
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
void DispmanxWrapper::setGrabbingMode(GrabbingMode mode)
|
||||
{
|
||||
if (mode == GRABBINGMODE_VIDEO)
|
||||
start();
|
||||
else
|
||||
stop();
|
||||
}
|
||||
|
@ -6,32 +6,65 @@
|
||||
|
||||
namespace hyperion
|
||||
{
|
||||
///
|
||||
/// The BlackBorder processor is a wrapper around the black-border detector for keeping track of
|
||||
/// detected borders and count of the type and size of detected borders.
|
||||
///
|
||||
class BlackBorderProcessor
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructor for the BlackBorderProcessor
|
||||
/// @param unknownFrameCnt The number of frames(images) that need to contain an unknown
|
||||
/// border before the current border is set to unknown
|
||||
/// @param borderFrameCnt The number of frames(images) that need to contain a vertical or
|
||||
/// horizontal border becomes the current border
|
||||
/// @param blurRemoveCnt The size to add to a horizontal or vertical border (because the
|
||||
/// outer pixels is blurred (black and color combined))
|
||||
///
|
||||
BlackBorderProcessor(
|
||||
const unsigned unknownFrameCnt,
|
||||
const unsigned borderFrameCnt,
|
||||
const unsigned blurRemoveCnt);
|
||||
|
||||
///
|
||||
/// Return the current (detected) border
|
||||
/// @return The current border
|
||||
///
|
||||
BlackBorder getCurrentBorder() const;
|
||||
|
||||
///
|
||||
/// Processes the image. This performs detecion of black-border on the given image and
|
||||
/// updates the current border accordingly. If the current border is updated the method call
|
||||
/// will return true else false
|
||||
///
|
||||
/// @param image The image to process
|
||||
///
|
||||
/// @return True if a different border was detected than the current else false
|
||||
///
|
||||
bool process(const RgbImage& image);
|
||||
|
||||
private:
|
||||
|
||||
/// The number of unknown-borders detected before it becomes the current border
|
||||
const unsigned _unknownSwitchCnt;
|
||||
|
||||
/// The number of horizontal/vertical borders detected before it becomes the current border
|
||||
const unsigned _borderSwitchCnt;
|
||||
|
||||
/// The number of pixels to increase a detected border for removing blury pixels
|
||||
unsigned _blurRemoveCnt;
|
||||
|
||||
/// The blackborder detector
|
||||
BlackBorderDetector _detector;
|
||||
|
||||
/// The current detected border
|
||||
BlackBorder _currentBorder;
|
||||
|
||||
/// The border detected in the previous frame
|
||||
BlackBorder _previousDetectedBorder;
|
||||
|
||||
/// The number of frame the previous detected border matched the incomming border
|
||||
unsigned _consistentCnt;
|
||||
};
|
||||
} // end namespace hyperion
|
||||
|
@ -22,12 +22,10 @@ LedDevice* Hyperion::constructDevice(const Json::Value& deviceConfig)
|
||||
LedDevice* device = nullptr;
|
||||
if (deviceConfig["type"].asString() == "ws2801")
|
||||
{
|
||||
const std::string name = "WS-2801";
|
||||
const std::string output = deviceConfig["output"].asString();
|
||||
const unsigned interval = deviceConfig["interval"].asInt();
|
||||
const unsigned rate = deviceConfig["rate"].asInt();
|
||||
|
||||
LedDeviceWs2801* deviceWs2801 = new LedDeviceWs2801(name, output, interval, rate);
|
||||
LedDeviceWs2801* deviceWs2801 = new LedDeviceWs2801(output, rate);
|
||||
deviceWs2801->open();
|
||||
|
||||
device = deviceWs2801;
|
||||
@ -117,7 +115,7 @@ unsigned Hyperion::getLedCount() const
|
||||
return _ledString.leds().size();
|
||||
}
|
||||
|
||||
void Hyperion::setColor(int priority, RgbColor & color, const int timeout_ms)
|
||||
void Hyperion::setColor(int priority, const RgbColor &color, const int timeout_ms)
|
||||
{
|
||||
// create led output
|
||||
std::vector<RgbColor> ledColors(_ledString.leds().size(), color);
|
||||
@ -126,7 +124,7 @@ void Hyperion::setColor(int priority, RgbColor & color, const int timeout_ms)
|
||||
setColors(priority, ledColors, timeout_ms);
|
||||
}
|
||||
|
||||
void Hyperion::setColors(int priority, std::vector<RgbColor>& ledColors, const int timeout_ms)
|
||||
void Hyperion::setColors(int priority, const std::vector<RgbColor>& ledColors, const int timeout_ms)
|
||||
{
|
||||
if (timeout_ms > 0)
|
||||
{
|
||||
|
@ -59,6 +59,8 @@ namespace hyperion
|
||||
/// Determines the mean-color for each led using the mapping the image given
|
||||
/// at construction.
|
||||
///
|
||||
/// @param[in] image The image from which to extract the led colors
|
||||
///
|
||||
/// @return ledColors The vector containing the output
|
||||
///
|
||||
std::vector<RgbColor> getMeanLedColor(const RgbImage & image) const;
|
||||
@ -67,6 +69,7 @@ namespace hyperion
|
||||
/// Determines the mean color for each led using the mapping the image given
|
||||
/// at construction.
|
||||
///
|
||||
/// @param[in] image The image from which to extract the led colors
|
||||
/// @param[out] ledColors The vector containing the output
|
||||
///
|
||||
void getMeanLedColor(const RgbImage & image, std::vector<RgbColor> & ledColors) const;
|
||||
@ -83,6 +86,7 @@ namespace hyperion
|
||||
/// Calculates the 'mean color' of the given list. This is the mean over each color-channel
|
||||
/// (red, green, blue)
|
||||
///
|
||||
/// @param[in] image The image a section from which an average color must be computed
|
||||
/// @param[in] colors The list with colors
|
||||
///
|
||||
/// @return The mean of the given list of colors (or black when empty)
|
||||
|
@ -6,14 +6,33 @@
|
||||
// Hyperion includes
|
||||
#include <hyperion/LedDevice.h>
|
||||
|
||||
///
|
||||
/// Implementation of the LedDevice that write the led-colors to an
|
||||
/// ASCII-textfile('/home/pi/LedDevice.out')
|
||||
///
|
||||
class LedDeviceTest : public LedDevice
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructs the test-device, which opens an output stream to the file
|
||||
///
|
||||
LedDeviceTest();
|
||||
|
||||
///
|
||||
/// Destructor of this test-device
|
||||
///
|
||||
virtual ~LedDeviceTest();
|
||||
|
||||
///
|
||||
/// Writes the given led-color values to the output stream
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
///
|
||||
/// @return Zero on success else negative
|
||||
///
|
||||
virtual int write(const std::vector<RgbColor> & ledValues);
|
||||
|
||||
private:
|
||||
/// The outputstream
|
||||
std::ofstream _ofs;
|
||||
};
|
||||
|
@ -11,9 +11,7 @@
|
||||
// hyperion local includes
|
||||
#include "LedDeviceWs2801.h"
|
||||
|
||||
LedDeviceWs2801::LedDeviceWs2801(const std::string& name,
|
||||
const std::string& outputDevice,
|
||||
const unsigned interval,
|
||||
LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice,
|
||||
const unsigned baudrate) :
|
||||
mDeviceName(outputDevice),
|
||||
mBaudRate_Hz(baudrate),
|
||||
|
@ -9,25 +9,51 @@
|
||||
// hyperion incluse
|
||||
#include <hyperion/LedDevice.h>
|
||||
|
||||
///
|
||||
/// Implementation of the LedDevice interface for writing to Ws2801 led device.
|
||||
///
|
||||
class LedDeviceWs2801 : public LedDevice
|
||||
{
|
||||
public:
|
||||
LedDeviceWs2801(const std::string& name,
|
||||
const std::string& outputDevice,
|
||||
const unsigned interval,
|
||||
///
|
||||
/// Constructs the LedDevice for a string containing leds of the type Ws2801
|
||||
///
|
||||
/// @param outputDevice The name of the output device (eg '/etc/SpiDev.0.0')
|
||||
/// @param baudrate The used baudrate for writing to the output device
|
||||
///
|
||||
LedDeviceWs2801(const std::string& outputDevice,
|
||||
const unsigned baudrate);
|
||||
|
||||
///
|
||||
/// Destructor of the LedDevice; closes the output device if it is open
|
||||
///
|
||||
virtual ~LedDeviceWs2801();
|
||||
|
||||
///
|
||||
/// Opens and configures the output device
|
||||
///
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
int open();
|
||||
|
||||
///
|
||||
/// Writes the led color values to the led-device
|
||||
///
|
||||
/// @param ledValues The color-value per led
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
virtual int write(const std::vector<RgbColor> &ledValues);
|
||||
|
||||
private:
|
||||
/// The name of the output device
|
||||
const std::string mDeviceName;
|
||||
/// The used baudrate of the output device
|
||||
const int mBaudRate_Hz;
|
||||
|
||||
/// The File Identifier of the opened output device (or -1 if not opened)
|
||||
int mFid;
|
||||
/// The transfer structure for writing to the spi-device
|
||||
spi_ioc_transfer spi;
|
||||
/// The 'latch' time for latching the shifted-value into the leds
|
||||
timespec latchTime;
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ LedString::LedString()
|
||||
|
||||
LedString::~LedString()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
std::vector<Led>& LedString::leds()
|
||||
|
@ -18,44 +18,140 @@
|
||||
|
||||
class ImageProcessor;
|
||||
|
||||
///
|
||||
/// The Connection object created by \a JsonServer when a new connection is establshed
|
||||
///
|
||||
class JsonClientConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructor
|
||||
/// @param socket The Socket object for this connection
|
||||
/// @param hyperion The Hyperion server
|
||||
///
|
||||
JsonClientConnection(QTcpSocket * socket, Hyperion * hyperion);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~JsonClientConnection();
|
||||
|
||||
signals:
|
||||
///
|
||||
/// Signal which is emitted when the connection is being closed
|
||||
/// @param connection This connection object
|
||||
///
|
||||
void connectionClosed(JsonClientConnection * connection);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Slot called when new data has arrived
|
||||
///
|
||||
void readData();
|
||||
|
||||
///
|
||||
/// Slot called when this connection is being closed
|
||||
///
|
||||
void socketClosed();
|
||||
|
||||
private:
|
||||
///
|
||||
/// Handle an incoming JSON message
|
||||
///
|
||||
/// @param message the incoming message as string
|
||||
///
|
||||
void handleMessage(const std::string & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON Color message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleColorCommand(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON Image message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleImageCommand(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON Server info message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleServerInfoCommand(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON Clear message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleClearCommand(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON Clearall message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleClearallCommand(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON Transform message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleTransformCommand(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON message of unknown type
|
||||
///
|
||||
void handleNotImplemented();
|
||||
|
||||
///
|
||||
/// Send a message to the connected client
|
||||
///
|
||||
/// @param message The JSON message to send
|
||||
///
|
||||
void sendMessage(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Send a standard reply indicating success
|
||||
///
|
||||
void sendSuccessReply();
|
||||
|
||||
///
|
||||
/// Send an error message back to the client
|
||||
///
|
||||
/// @param error String describing the error
|
||||
///
|
||||
void sendErrorReply(const std::string & error);
|
||||
|
||||
private:
|
||||
///
|
||||
/// Check if a JSON messag is valid according to a given JSON schema
|
||||
///
|
||||
/// @param message JSON message which need to be checked
|
||||
/// @param schemaResource Qt esource identifier with the JSON schema
|
||||
/// @param errors Output error message
|
||||
///
|
||||
/// @return true if message conforms the given JSON schema
|
||||
///
|
||||
bool checkJson(const Json::Value & message, const QString &schemaResource, std::string & errors);
|
||||
|
||||
private:
|
||||
/// The TCP-Socket that is connected tot the Json-client
|
||||
QTcpSocket * _socket;
|
||||
|
||||
/// The processor for translating images to led-values
|
||||
ImageProcessor * _imageProcessor;
|
||||
|
||||
/// Link to Hyperion for writing led-values to a priority channel
|
||||
Hyperion * _hyperion;
|
||||
|
||||
/// The buffer used for reading data from the socket
|
||||
QByteArray _receiveBuffer;
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <iostream>
|
||||
#include <utils/HsvTransform.h>
|
||||
|
||||
HsvTransform::HsvTransform() :
|
||||
@ -44,6 +45,8 @@ void HsvTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) con
|
||||
uint8_t saturation, value;
|
||||
rgb2hsv(red, green, blue, hue, saturation, value);
|
||||
|
||||
std::cout << int(hue) << " " << int(saturation) << " " << int(value) << std::endl;
|
||||
|
||||
int s = saturation * _saturationGain;
|
||||
if (s > 255)
|
||||
saturation = 255;
|
||||
@ -83,11 +86,21 @@ void HsvTransform::rgb2hsv(uint8_t red, uint8_t green, uint8_t blue, uint16_t &
|
||||
}
|
||||
|
||||
if (rgbMax == red)
|
||||
hue = 0 + 60 * (green - blue) / (rgbMax - rgbMin);
|
||||
{
|
||||
// start from 360 to be sure that we won't assign a negative number to the unsigned hue value
|
||||
hue = 360 + 60 * (green - blue) / (rgbMax - rgbMin);
|
||||
|
||||
if (hue > 359)
|
||||
hue -= 360;
|
||||
}
|
||||
else if (rgbMax == green)
|
||||
{
|
||||
hue = 120 + 60 * (blue - red) / (rgbMax - rgbMin);
|
||||
}
|
||||
else
|
||||
{
|
||||
hue = 240 + 60 * (red - green) / (rgbMax - rgbMin);
|
||||
}
|
||||
}
|
||||
|
||||
void HsvTransform::hsv2rgb(uint16_t hue, uint8_t saturation, uint8_t value, uint8_t & red, uint8_t & green, uint8_t & blue)
|
||||
@ -103,7 +116,7 @@ void HsvTransform::hsv2rgb(uint16_t hue, uint8_t saturation, uint8_t value, uint
|
||||
}
|
||||
|
||||
region = hue / 60;
|
||||
remainder = (hue - (region * 60)) * 6;
|
||||
remainder = (hue - (region * 60)) * 256 / 60;
|
||||
|
||||
p = (value * (255 - saturation)) >> 8;
|
||||
q = (value * (255 - ((saturation * remainder) >> 8))) >> 8;
|
||||
|
@ -8,8 +8,8 @@
|
||||
|
||||
|
||||
RgbImage::RgbImage(const unsigned width, const unsigned height, const RgbColor background) :
|
||||
mWidth(width),
|
||||
mHeight(height),
|
||||
_width(width),
|
||||
_height(height),
|
||||
mColors(new RgbColor[width*height])
|
||||
{
|
||||
for (unsigned i=0; i<width*height; ++i)
|
||||
@ -32,8 +32,8 @@ void RgbImage::setPixel(const unsigned x, const unsigned y, const RgbColor color
|
||||
const RgbColor& RgbImage::operator()(const unsigned x, const unsigned y) const
|
||||
{
|
||||
// Debug-mode sanity check on given index
|
||||
assert(x < mWidth);
|
||||
assert(y < mHeight);
|
||||
assert(x < _width);
|
||||
assert(y < _height);
|
||||
|
||||
const unsigned index = toIndex(x, y);
|
||||
return mColors[index];
|
||||
@ -42,8 +42,8 @@ const RgbColor& RgbImage::operator()(const unsigned x, const unsigned y) const
|
||||
RgbColor& RgbImage::operator()(const unsigned x, const unsigned y)
|
||||
{
|
||||
// Debug-mode sanity check on given index
|
||||
assert(x < mWidth);
|
||||
assert(y < mHeight);
|
||||
assert(x < _width);
|
||||
assert(y < _height);
|
||||
|
||||
const unsigned index = toIndex(x, y);
|
||||
return mColors[index];
|
||||
|
@ -413,7 +413,7 @@ void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::
|
||||
{
|
||||
// only for arrays
|
||||
_error = true;
|
||||
setMessage("maxItems only valid for arrays");
|
||||
setMessage("uniqueItems only valid for arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,18 @@
|
||||
|
||||
#include <xbmcvideochecker/XBMCVideoChecker.h>
|
||||
|
||||
XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, uint64_t interval_ms, Hyperion * hyperion, int priority) :
|
||||
XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, uint64_t interval_ms, bool grabVideo, bool grabPhoto, bool grabAudio, bool grabMenu) :
|
||||
QObject(),
|
||||
_address(QString::fromStdString(address)),
|
||||
_port(port),
|
||||
_request("{\"jsonrpc\":\"2.0\",\"method\":\"Player.GetActivePlayers\",\"id\":1}"),
|
||||
_timer(),
|
||||
_socket(),
|
||||
_hyperion(hyperion),
|
||||
_priority(priority)
|
||||
_grabVideo(grabVideo),
|
||||
_grabPhoto(grabPhoto),
|
||||
_grabAudio(grabAudio),
|
||||
_grabMenu(grabMenu),
|
||||
_previousMode(GRABBINGMODE_INVALID)
|
||||
{
|
||||
// setup timer
|
||||
_timer.setSingleShot(false);
|
||||
@ -51,17 +54,33 @@ void XBMCVideoChecker::receiveReply()
|
||||
// expect that the reply is received as a single message. Probably oke considering the size of the expected reply
|
||||
QString reply(_socket.readAll());
|
||||
|
||||
if (reply.contains("playerid"))
|
||||
GrabbingMode newMode = GRABBINGMODE_INVALID;
|
||||
if (reply.contains("video"))
|
||||
{
|
||||
// something is playing. check for "video" to check if a video is playing
|
||||
// clear our priority channel to allow the grabbed vido colors to be shown
|
||||
_hyperion->clear(_priority);
|
||||
// video is playing
|
||||
newMode = _grabVideo ? GRABBINGMODE_VIDEO : GRABBINGMODE_OFF;
|
||||
}
|
||||
else if (reply.contains("picture"))
|
||||
{
|
||||
// photo viewer is playing
|
||||
newMode = _grabVideo ? GRABBINGMODE_PHOTO : GRABBINGMODE_OFF;
|
||||
}
|
||||
else if (reply.contains("audio"))
|
||||
{
|
||||
// photo viewer is playing
|
||||
newMode = _grabVideo ? GRABBINGMODE_AUDIO : GRABBINGMODE_OFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing is playing. set our priority channel completely to black
|
||||
// The timeout is used to have the channel cleared after 30 seconds of connection problems...
|
||||
_hyperion->setColor(_priority, RgbColor::BLACK, 30000);
|
||||
// Nothing is playing.
|
||||
newMode = _grabMenu ? GRABBINGMODE_MENU : GRABBINGMODE_OFF;
|
||||
}
|
||||
|
||||
// emit new state if applicable
|
||||
if (newMode != _previousMode)
|
||||
{
|
||||
emit grabbingMode(newMode);
|
||||
_previousMode = newMode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,10 @@
|
||||
/// Simple structure to contain the values of a color transformation
|
||||
struct ColorTransformValues
|
||||
{
|
||||
/// The value for the red color-channel
|
||||
double valueRed;
|
||||
/// The value for the green color-channel
|
||||
double valueGreen;
|
||||
/// The value for the blue color-channel
|
||||
double valueBlue;
|
||||
};
|
||||
|
@ -10,13 +10,25 @@
|
||||
// hyperion-remote includes
|
||||
#include "ColorTransformValues.h"
|
||||
|
||||
|
||||
/// Data parameter for a color
|
||||
typedef vlofgren::PODParameter<QColor> ColorParameter;
|
||||
|
||||
/// Data parameter for an image
|
||||
typedef vlofgren::PODParameter<QImage> ImageParameter;
|
||||
|
||||
/// Data parameter for color transform values (list of three values)
|
||||
typedef vlofgren::PODParameter<ColorTransformValues> TransformParameter;
|
||||
|
||||
|
||||
namespace vlofgren {
|
||||
///
|
||||
/// Translates a string (as passed on the commandline) to a color
|
||||
///
|
||||
/// @param[in] s The string (as passed on the commandline)
|
||||
///
|
||||
/// @return The translated color
|
||||
///
|
||||
/// @throws Parameter::ParameterRejected If the string did not result in a color
|
||||
///
|
||||
template<>
|
||||
QColor ColorParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
|
||||
{
|
||||
|
@ -15,30 +15,74 @@
|
||||
// hyperion-remote includes
|
||||
#include "ColorTransformValues.h"
|
||||
|
||||
///
|
||||
/// Connection class to setup an connection to the hyperion server and execute commands
|
||||
///
|
||||
class JsonConnection
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
/// @param address The address of the Hyperion server (for example "192.168.0.32:19444)
|
||||
/// @param printJson Boolean indicating if the sent and received json is written to stdout
|
||||
///
|
||||
JsonConnection(const std::string & address, bool printJson);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~JsonConnection();
|
||||
|
||||
///
|
||||
/// Set all leds to the specified color
|
||||
///
|
||||
/// @param color The color
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setColor(QColor color, int priority, int duration);
|
||||
|
||||
///
|
||||
/// Set the leds according to the given image (assume the image is stretched to the display size)
|
||||
///
|
||||
/// @param image The image
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setImage(QImage image, int priority, int duration);
|
||||
|
||||
///
|
||||
/// Retrieve a list of all occupied priority channels
|
||||
///
|
||||
/// @return String with the server info
|
||||
///
|
||||
QString getServerInfo();
|
||||
|
||||
///
|
||||
/// Clear the given priority channel
|
||||
///
|
||||
/// @param priority The priority
|
||||
///
|
||||
void clear(int priority);
|
||||
|
||||
///
|
||||
/// Clear all priority channels
|
||||
///
|
||||
void clearAll();
|
||||
|
||||
///
|
||||
/// Set the color transform of the leds
|
||||
/// Note that providing a NULL will leave the settings on the server unchanged
|
||||
///
|
||||
/// @note Note that providing a NULL will leave the settings on the server unchanged
|
||||
///
|
||||
/// @param saturation The HSV saturation gain
|
||||
/// @param value The HSV value gain
|
||||
/// @param threshold The threshold
|
||||
/// @param gamma The gamma value
|
||||
/// @param blacklevel The blacklevel
|
||||
/// @param whitelevel The whitelevel
|
||||
///
|
||||
void setTransform(
|
||||
double * saturation,
|
||||
double * value,
|
||||
@ -48,13 +92,28 @@ public:
|
||||
ColorTransformValues * whitelevel);
|
||||
|
||||
private:
|
||||
///
|
||||
/// Send a json command message and receive its reply
|
||||
///
|
||||
/// @param message The message to send
|
||||
///
|
||||
/// @return The returned reply
|
||||
///
|
||||
Json::Value sendMessage(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Parse a reply message
|
||||
///
|
||||
/// @param reply The received reply
|
||||
///
|
||||
/// @return true if the reply indicates success
|
||||
///
|
||||
bool parseReply(const Json::Value & reply);
|
||||
|
||||
private:
|
||||
/// Flag for printing all send and received json-messages to the standard out
|
||||
bool _printJson;
|
||||
|
||||
/// The TCP-Socket with the connection to the server
|
||||
QTcpSocket _socket;
|
||||
};
|
||||
|
@ -83,7 +83,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
const Json::Value & videoCheckerConfig = config["xbmcVideoChecker"];
|
||||
XBMCVideoChecker xbmcVideoChecker(videoCheckerConfig["xbmcAddress"].asString(), videoCheckerConfig["xbmcTcpPort"].asUInt(), 1000, &hyperion, 999);
|
||||
XBMCVideoChecker xbmcVideoChecker(videoCheckerConfig["xbmcAddress"].asString(), videoCheckerConfig["xbmcTcpPort"].asUInt(), 1000, true, true, true, true);
|
||||
if (videoCheckerConfig["enable"].asBool())
|
||||
{
|
||||
xbmcVideoChecker.start();
|
||||
@ -97,6 +97,7 @@ int main(int argc, char** argv)
|
||||
frameGrabberConfig["height"].asUInt(),
|
||||
frameGrabberConfig["frequency_Hz"].asUInt(),
|
||||
&hyperion);
|
||||
QObject::connect(&xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), &dispmanx, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
dispmanx.start();
|
||||
std::cout << "Frame grabber created and started" << std::endl;
|
||||
|
||||
|
@ -6,6 +6,7 @@ if(PNG_FOUND)
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
|
||||
add_executable(viewpng
|
||||
FbWriter.h
|
||||
ViewPng.cpp)
|
||||
|
||||
target_link_libraries(viewpng
|
||||
|
@ -12,14 +12,27 @@
|
||||
|
||||
#include <utils/RgbImage.h>
|
||||
|
||||
///
|
||||
/// FbWriter allows direct access tot the FrameBuffer. It writes and image to the framebuffer,
|
||||
/// adjusting the resolution as required. When destructed the FrameBuffer is switch to original
|
||||
/// configuration.
|
||||
///
|
||||
class FbWriter
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructs the FrameBuffer writer opening the FrameBuffer device and storing the current
|
||||
/// configuration.
|
||||
///
|
||||
FbWriter()
|
||||
{
|
||||
initialise();
|
||||
}
|
||||
|
||||
///
|
||||
/// Destructor of the write. Switches the FrameBuffer to its origianl configuration and closes
|
||||
/// the FrameBuffer
|
||||
///
|
||||
~FbWriter()
|
||||
{
|
||||
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo))
|
||||
@ -30,26 +43,33 @@ public:
|
||||
close(fbfd);
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialises the write, opening the FrameBuffer
|
||||
///
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
int initialise()
|
||||
{
|
||||
// Open the file for reading and writing
|
||||
fbfd = open("/dev/fb0", O_RDWR);
|
||||
if (!fbfd)
|
||||
{
|
||||
printf("Error: cannot open framebuffer device.\n");
|
||||
return(-1);
|
||||
std::cerr << "Error: cannot open framebuffer device." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
printf("The framebuffer device was opened successfully.\n");
|
||||
|
||||
// Get fixed screen information
|
||||
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
|
||||
{
|
||||
printf("Error reading fixed information.\n");
|
||||
std::cerr << "Error reading fixed information.\n" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
// Get variable screen information
|
||||
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &orig_vinfo))
|
||||
{
|
||||
printf("Error reading variable information.\n");
|
||||
std::cerr << "Error reading variable information.\n" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
printf("Original %dx%d, %dbpp\n", orig_vinfo.xres, orig_vinfo.yres, orig_vinfo.bits_per_pixel );
|
||||
|
||||
@ -57,6 +77,12 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// Writes the given RGB Image to the FrameBuffer. When required the resolution of the
|
||||
/// FrameBuffer is asjusted to match the given image
|
||||
///
|
||||
/// @param image The RGB Image
|
||||
///
|
||||
void writeImage(const RgbImage& image)
|
||||
{
|
||||
std::cout << "Writing image [" << image.width() << "x" << image.height() << "]" << std::endl;
|
||||
@ -93,23 +119,16 @@ public:
|
||||
for (unsigned iY=0; iY<image.height(); ++iY)
|
||||
{
|
||||
memcpy(fbp + iY*finfo.line_length, &(image(0, iY)), image.width()*3);
|
||||
// for (unsigned iX=0; iX<image.width(); ++iX)
|
||||
// {
|
||||
// const unsigned pixOffset = iX*3 + iY*finfo.line_length;
|
||||
// fbp[pixOffset ] = image(iX, iY).red;
|
||||
// fbp[pixOffset+1] = image(iX, iY).green;
|
||||
// fbp[pixOffset+2] = image(iX, iY).blue;
|
||||
// }
|
||||
}
|
||||
std::cout << "FINISHED COPYING IMAGE TO FRAMEBUFFER" << std::endl;
|
||||
// cleanup
|
||||
munmap(fbp, screensize);
|
||||
}
|
||||
|
||||
// The identifier of the FrameBuffer File-Device
|
||||
/// The identifier of the FrameBuffer File-Device
|
||||
int fbfd;
|
||||
// The 'Fixed' screen information
|
||||
/// The 'Fixed' screen information
|
||||
fb_fix_screeninfo finfo;
|
||||
// The original 'Variable' screen information
|
||||
/// The original 'Variable' screen information
|
||||
fb_var_screeninfo orig_vinfo;
|
||||
};
|
||||
|
@ -54,7 +54,7 @@ void setColor(char* colorStr)
|
||||
unsigned ledCnt = 50;
|
||||
std::vector<RgbColor> buff(ledCnt, color);
|
||||
|
||||
LedDeviceWs2801 ledDevice("SpiPi", "/dev/spidev0.0", 20000, 40000);
|
||||
LedDeviceWs2801 ledDevice("/dev/spidev0.0", 40000);
|
||||
ledDevice.open();
|
||||
ledDevice.write(buff);
|
||||
}
|
||||
@ -68,7 +68,7 @@ void doCircle()
|
||||
unsigned ledCnt = 50;
|
||||
std::vector<RgbColor> data(ledCnt, RgbColor::BLACK);
|
||||
|
||||
LedDeviceWs2801 ledDevice("SpiPi", "/dev/spidev0.0", 20000, 40000);
|
||||
LedDeviceWs2801 ledDevice("/dev/spidev0.0", 40000);
|
||||
ledDevice.open();
|
||||
|
||||
timespec loopTime;
|
||||
|
Loading…
Reference in New Issue
Block a user