From db5dfa1746e15bd5ca290f8626dbd6685f0a10ba Mon Sep 17 00:00:00 2001 From: Thad House Date: Thu, 19 Jan 2017 00:02:37 -0800 Subject: [PATCH] Adds sliders for all settable properties to the default webpage (#48) When the page is loaded, if properties can be found they will automatically be created on screen. They are currently not auto updating. Raw values are currently disabled because of this. --- src/MjpegServerImpl.cpp | 111 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 3 deletions(-) diff --git a/src/MjpegServerImpl.cpp b/src/MjpegServerImpl.cpp index 164411f813..628ce87f80 100644 --- a/src/MjpegServerImpl.cpp +++ b/src/MjpegServerImpl.cpp @@ -31,12 +31,35 @@ using namespace cs; #define BOUNDARY "boundarydonotcross" // A bare-bones HTML webpage for user friendliness. -static const char* rootPage = - "CameraServer" +static const char* emptyRootPage = + "CameraServer" "

" "Settings JSON" ""; +// An HTML page to be sent when a source exists +static const char* startRootPage = "\n" + "\n" + "CameraServer\n" + "

\n" + "Settings JSON\n"; +static const char* endRootPage =""; + class MjpegServerImpl::ConnThread : public wpi::SafeThread { public: ConnThread(llvm::StringRef name) : m_name(name) {} @@ -46,6 +69,7 @@ class MjpegServerImpl::ConnThread : public wpi::SafeThread { bool ProcessCommand(llvm::raw_ostream& os, SourceImpl& source, llvm::StringRef parameters, bool respond); void SendJSON(llvm::raw_ostream& os, SourceImpl& source, bool header); + void SendHTML(llvm::raw_ostream& os, SourceImpl& source, bool header); void SendStream(wpi::raw_socket_ostream& os); void ProcessRequest(); @@ -289,6 +313,83 @@ bool MjpegServerImpl::ConnThread::ProcessCommand(llvm::raw_ostream& os, return true; } +// Send the root html file with controls for all the settable properties. +void MjpegServerImpl::ConnThread::SendHTML(llvm::raw_ostream& os, + SourceImpl& source, bool header) { + if (header) SendHeader(os, 200, "OK", "application/x-javascript"); + + os << startRootPage; + llvm::SmallVector properties_vec; + CS_Status status = 0; + for (auto prop : source.EnumerateProperties(properties_vec, &status)) { + llvm::SmallString<128> name_buf; + auto name = source.GetPropertyName(prop, name_buf, &status); + if (name.startswith("raw_")) continue; + auto kind = source.GetPropertyKind(prop); + os << "

" + << "\n"; + switch (kind) { + case CS_PROP_BOOLEAN: + os << "\n"; + else + os << " />\n"; + break; + case CS_PROP_INTEGER: { + auto valI = source.GetProperty(prop, &status); + auto min = source.GetPropertyMin(prop, &status); + auto max = source.GetPropertyMax(prop, &status); + auto step = source.GetPropertyStep(prop, &status); + os << "\n"; + os << "" << valI + << "\n"; + break; + } + case CS_PROP_ENUM: { + auto valE = source.GetProperty(prop, &status); + auto choices = source.GetEnumPropertyChoices(prop, &status); + int j = 0; + for (auto choice = choices.begin(), end = choices.end(); choice != end; + ++j, ++choice) { + if (choice->empty()) continue; // skip empty choices + // replace any non-printable characters in name with spaces + llvm::SmallString<128> ch_name; + for (char ch : *choice) ch_name.push_back(isprint(ch) ? ch : ' '); + os << "\n"; + } + break; + } + case CS_PROP_STRING: { + llvm::SmallString<128> strval_buf; + os << "\n"; + os << "\n"; + break; + } + default: + break; + } + } + + os << endRootPage << "\r\n"; + os.flush(); +} + // Send a JSON file which is contains information about the source parameters. void MjpegServerImpl::ConnThread::SendJSON(llvm::raw_ostream& os, SourceImpl& source, bool header) { @@ -587,7 +688,11 @@ void MjpegServerImpl::ConnThread::ProcessRequest() { case kRootPage: SDEBUG("request for root page"); SendHeader(os, 200, "OK", "text/html"); - os << rootPage << "\r\n"; + if (auto source = GetSource()) { + SendHTML(os, *source, false); + } else { + os << emptyRootPage << "\r\n"; + } break; }