<commit_before>// $Id: Line3_test.C,v 1.8 2000/07/26 16:49:47 amoll Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#	include <BALL/MATHS/vector3.h>
#	include <BALL/MATHS/line3.h>
///////////////////////////

START_TEST(class_name, "$Id: Line3_test.C,v 1.8 2000/07/26 16:49:47 amoll Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;
using namespace std;

Vector3 v1, v2, v3, v4;

String filename;
using std::ofstream;
using std::ios;

CHECK(TLine3::BALL_CREATE(TLine3<T>))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	Line3 v(v1, v2);
	Line3* v_ptr = (Line3*)v.create(false, true);
	TEST_EQUAL(v_ptr->p, v3)
	TEST_EQUAL(v_ptr->d, v3)
	delete v_ptr;
	v_ptr = (Line3*)v.create();
	TEST_EQUAL(v_ptr->p, v1)
	TEST_EQUAL(v_ptr->d, v2)
	delete v_ptr;
RESULT

CHECK(TLine3::TLine3())
  Line3* line;
	line = new Line3();
	TEST_NOT_EQUAL(line, 0)
RESULT

CHECK(TLine3::~TLine3())
  Line3* line;
	line = new Line3();
	delete line;
RESULT

Line3 line, line1, line2, line3;

CHECK(TLine3(const TVector3<T>& point, const TVector3<T>& vector,
					 Form form = FORM__PARAMETER))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line.get(v3, v4, Line3::FORM__PARAMETER);
	TEST_EQUAL(v1, v3)
	TEST_EQUAL(v2, v4)

	line = Line3(v1, v2, Line3::FORM__TWO_POINTS);
	line.get(v1, v2);
	v3.set(0, 1, 2);
	v4.set(3, 3, 3);
	TEST_EQUAL(v1, v3)
	TEST_EQUAL(v2, v4)
RESULT

CHECK(bool operator ==(const TLine3& line) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(0, 4, 2);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	line  = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line == line2, true)
	v2 = Vector3(0, 1, 2);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line == line2, false)
RESULT

CHECK(TLine3::swap(TLine3& line))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	v3 = Vector3(6, 7, 8);
	v4 = Vector3(9, 10, 11);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line1 = Line3(v1, v2, Line3::FORM__PARAMETER);

	line2 = Line3(v3, v4, Line3::FORM__PARAMETER);
	line3 = Line3(v3, v4, Line3::FORM__PARAMETER);

	line.swap(line2);
	TEST_EQUAL(line1, line2)
	TEST_EQUAL(line, line3)
RESULT

CHECK(TLine3::set(const TVector3<T>& point, const TVector3<T>& vector, Form form = FORM__PARAMETER))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line2.set(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line, line2)
	line = Line3(v1, v2, Line3::FORM__TWO_POINTS);
	line2.set(v1, v2, Line3::FORM__TWO_POINTS);
	TEST_EQUAL(line, line2)
RESULT

CHECK(TLine3::get(TLine3& line, bool /* deep */ = true) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line2.get(line);
	TEST_EQUAL(line, line2)
RESULT

CHECK(normalize())
	v1 = Vector3(0, 0, 0);
	v2 = Vector3(4, 9, 16);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line.normalize();
	v2.normalize();
	line.get(v3, v4, Line3::FORM__PARAMETER);
	TEST_EQUAL(v2, v4)
RESULT

CHECK(bool operator != (const TLine3& line) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(0, 3, 2);
	line  = Line3(v1, v2, Line3::FORM__PARAMETER);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line != line2, false)
	v2 = Vector3(9, 1, 2);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line != line2, true)
RESULT

CHECK(has(const TVector3<T>& point) const )
	v1 = Vector3(0, 0, 0);
	v2 = Vector3(4, 4, 4);
	line = Line3(v1, v2, Line3::FORM__TWO_POINTS);
	v1 = Vector3(2, 2, 2);
	TEST_EQUAL(line.has(v1), true)
	v1 = Vector3(2, 2, 3);
	TEST_EQUAL(line.has(v1), false)
RESULT

CHECK(isValid() const)
	TEST_EQUAL(line.isValid(), true)
RESULT

CHECK(std::istream& operator >> (std::istream& s, TLine3<T>& line))
	std::ifstream instr("data/Line_test2.txt");
	line = Line3();
	instr >> line;
	instr.close();
	v3 = Vector3(0, 1, 2);
	v4 = Vector3(3, 4, 5);
	line2 = Line3(v3, v4, Line3::FORM__PARAMETER);
	TEST_EQUAL(line, line2)
RESULT

NEW_TMP_FILE(filename)
CHECK(std::ostream& operator << (std::ostream& s, const TLine3<T>& line))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	std::ofstream outstr(filename.c_str(), File::OUT);
	outstr << line;
	outstr.close();
	TEST_FILE(filename.c_str(), "data/Line_test2.txt", false)
RESULT

CHECK(TAngle::dump(std::ostream& s = std::cout, Size depth = 0) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	String filename;
	NEW_TMP_FILE(filename)
	std::ofstream outfile(filename.c_str(), File::OUT);
	line.dump(outfile);
	outfile.close();
	TEST_FILE(filename.c_str(), "data/Line_test.txt", true)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>removed: redundant using directives for some members of namespace std<commit_after>// $Id: Line3_test.C,v 1.9 2000/08/29 15:53:39 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#	include <BALL/MATHS/vector3.h>
#	include <BALL/MATHS/line3.h>
///////////////////////////

START_TEST(class_name, "$Id: Line3_test.C,v 1.9 2000/08/29 15:53:39 oliver Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;
using namespace std;

Vector3 v1, v2, v3, v4;

String filename;

CHECK(TLine3::BALL_CREATE(TLine3<T>))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	Line3 v(v1, v2);
	Line3* v_ptr = (Line3*)v.create(false, true);
	TEST_EQUAL(v_ptr->p, v3)
	TEST_EQUAL(v_ptr->d, v3)
	delete v_ptr;
	v_ptr = (Line3*)v.create();
	TEST_EQUAL(v_ptr->p, v1)
	TEST_EQUAL(v_ptr->d, v2)
	delete v_ptr;
RESULT

CHECK(TLine3::TLine3())
  Line3* line;
	line = new Line3();
	TEST_NOT_EQUAL(line, 0)
RESULT

CHECK(TLine3::~TLine3())
  Line3* line;
	line = new Line3();
	delete line;
RESULT

Line3 line, line1, line2, line3;

CHECK(TLine3(const TVector3<T>& point, const TVector3<T>& vector,
					 Form form = FORM__PARAMETER))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line.get(v3, v4, Line3::FORM__PARAMETER);
	TEST_EQUAL(v1, v3)
	TEST_EQUAL(v2, v4)

	line = Line3(v1, v2, Line3::FORM__TWO_POINTS);
	line.get(v1, v2);
	v3.set(0, 1, 2);
	v4.set(3, 3, 3);
	TEST_EQUAL(v1, v3)
	TEST_EQUAL(v2, v4)
RESULT

CHECK(bool operator ==(const TLine3& line) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(0, 4, 2);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	line  = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line == line2, true)
	v2 = Vector3(0, 1, 2);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line == line2, false)
RESULT

CHECK(TLine3::swap(TLine3& line))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	v3 = Vector3(6, 7, 8);
	v4 = Vector3(9, 10, 11);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line1 = Line3(v1, v2, Line3::FORM__PARAMETER);

	line2 = Line3(v3, v4, Line3::FORM__PARAMETER);
	line3 = Line3(v3, v4, Line3::FORM__PARAMETER);

	line.swap(line2);
	TEST_EQUAL(line1, line2)
	TEST_EQUAL(line, line3)
RESULT

CHECK(TLine3::set(const TVector3<T>& point, const TVector3<T>& vector, Form form = FORM__PARAMETER))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line2.set(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line, line2)
	line = Line3(v1, v2, Line3::FORM__TWO_POINTS);
	line2.set(v1, v2, Line3::FORM__TWO_POINTS);
	TEST_EQUAL(line, line2)
RESULT

CHECK(TLine3::get(TLine3& line, bool /* deep */ = true) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line2.get(line);
	TEST_EQUAL(line, line2)
RESULT

CHECK(normalize())
	v1 = Vector3(0, 0, 0);
	v2 = Vector3(4, 9, 16);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	line.normalize();
	v2.normalize();
	line.get(v3, v4, Line3::FORM__PARAMETER);
	TEST_EQUAL(v2, v4)
RESULT

CHECK(bool operator != (const TLine3& line) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(0, 3, 2);
	line  = Line3(v1, v2, Line3::FORM__PARAMETER);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line != line2, false)
	v2 = Vector3(9, 1, 2);
	line2 = Line3(v1, v2, Line3::FORM__PARAMETER);
	TEST_EQUAL(line != line2, true)
RESULT

CHECK(has(const TVector3<T>& point) const )
	v1 = Vector3(0, 0, 0);
	v2 = Vector3(4, 4, 4);
	line = Line3(v1, v2, Line3::FORM__TWO_POINTS);
	v1 = Vector3(2, 2, 2);
	TEST_EQUAL(line.has(v1), true)
	v1 = Vector3(2, 2, 3);
	TEST_EQUAL(line.has(v1), false)
RESULT

CHECK(isValid() const)
	TEST_EQUAL(line.isValid(), true)
RESULT

CHECK(std::istream& operator >> (std::istream& s, TLine3<T>& line))
	std::ifstream instr("data/Line_test2.txt");
	line = Line3();
	instr >> line;
	instr.close();
	v3 = Vector3(0, 1, 2);
	v4 = Vector3(3, 4, 5);
	line2 = Line3(v3, v4, Line3::FORM__PARAMETER);
	TEST_EQUAL(line, line2)
RESULT

NEW_TMP_FILE(filename)
CHECK(std::ostream& operator << (std::ostream& s, const TLine3<T>& line))
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	std::ofstream outstr(filename.c_str(), File::OUT);
	outstr << line;
	outstr.close();
	TEST_FILE(filename.c_str(), "data/Line_test2.txt", false)
RESULT

CHECK(TAngle::dump(std::ostream& s = std::cout, Size depth = 0) const )
	v1 = Vector3(0, 1, 2);
	v2 = Vector3(3, 4, 5);
	line = Line3(v1, v2, Line3::FORM__PARAMETER);
	String filename;
	NEW_TMP_FILE(filename)
	std::ofstream outfile(filename.c_str(), File::OUT);
	line.dump(outfile);
	outfile.close();
	TEST_FILE(filename.c_str(), "data/Line_test.txt", true)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2021 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include <stdafx.h>

#include <cursespp/Screen.h>
#include <cursespp/Colors.h>
#include <cursespp/ToastOverlay.h>

#include <musikcore/runtime/Message.h>
#include <musikcore/support/Auddio.h>
#include <musikcore/library/RemoteLibrary.h>
#include <musikcore/version.h>

#include <app/util/Messages.h>
#include <app/util/PreferenceKeys.h>
#include <app/layout/ConsoleLayout.h>
#include <app/layout/LyricsLayout.h>
#include <app/layout/LibraryLayout.h>
#include <app/layout/LibraryNotConnectedLayout.h>
#include <app/layout/SettingsLayout.h>
#include <app/layout/HotkeysLayout.h>
#include <app/util/Hotkeys.h>

#include <map>

#include "SettingsLayout.h"
#include "MainLayout.h"

using namespace musik;
using namespace musik::cube;
using namespace musik::core;
using namespace musik::core::library;
using namespace musik::core::runtime;
using namespace cursespp;

using MasterLibraryPtr = MainLayout::MasterLibraryPtr;

static inline void updateSyncingText(TextLabel* label, int updates) {
    try {
        if (updates <= 0) {
            label->SetText(
                _TSTR("main_syncing_banner_start"),
                cursespp::text::AlignCenter);
        }
        else {
            label->SetText(u8fmt(
                _TSTR("main_syncing_banner"), updates),
                cursespp::text::AlignCenter);
        }
    }
    catch (...) {
        /* swallow. incomplete locale. don't crash. */
    }
}

static inline void updateRemoteLibraryConnectedText(TextLabel* label, MasterLibraryPtr library) {
    RemoteLibrary* remoteLibrary = dynamic_cast<RemoteLibrary*>(library->Wrapped().get());
    if (remoteLibrary) {
        std::string host = remoteLibrary->WebSocketClient().Uri();
        if (host.find("ws://") == 0) { host = host.substr(5); }
        auto value = u8fmt(_TSTR("library_remote_connected_banner"), host.c_str());
        label->SetText(value, cursespp::text::AlignCenter);
    }
}

MainLayout::MainLayout(
    cursespp::App& app,
    musik::cube::ConsoleLogger* logger,
    musik::core::audio::PlaybackService& playback,
    MasterLibraryPtr library)
: shortcutsFocused(false)
, syncUpdateCount(0)
, library(library)
, playback(playback)
, AppLayout(app) {
    this->prefs = Preferences::ForComponent("settings");

    library->ConnectionStateChanged.connect(this, &MainLayout::OnLibraryConnectionStateChanged);
    library->LibraryChanged.connect(this, &MainLayout::OnLibraryChanged);
    playback.TrackChanged.connect(this, &MainLayout::OnTrackChanged);

    this->RebindIndexerEventHandlers(ILibraryPtr(), this->library);

    /* note we don't create `libraryLayout` here; instead we do it lazily once we're sure
    it has been connected. see SwitchToLibraryLayout() */
    this->libraryNotConnectedLayout = std::make_shared<LibraryNotConnectedLayout>(library);
    this->lyricsLayout = std::make_shared<LyricsLayout>(playback, library);
    this->consoleLayout = std::make_shared<ConsoleLayout>(logger);
    this->settingsLayout = std::make_shared<SettingsLayout>(app, library, playback);
    this->hotkeysLayout = std::make_shared<HotkeysLayout>();

    this->topBanner = std::make_shared<TextLabel>();
    this->topBanner->SetContentColor(Color::Header);
    this->topBanner->Hide();
    this->AddWindow(this->topBanner);

    /* take user to settings if they don't have a valid configuration. otherwise,
    switch to the library view immediately */
    this->SetInitialLayout();
    this->SetAutoHideCommandBar(this->prefs->GetBool(prefs::keys::AutoHideCommandBar, false));

    this->RunUpdateCheck();
}

MainLayout::~MainLayout() {
    updateCheck.Cancel();
}

bool MainLayout::ShowTopBanner() {
    const auto libraryType = this->library->GetType();
    if (libraryType == ILibrary::Type::Local) {
        return this->library->Indexer()->GetState() == IIndexer::StateIndexing;
    }
    else if (libraryType == ILibrary::Type::Remote) {
        return this->library->GetConnectionState() == ILibrary::ConnectionState::Connected;
    }
    return false;
}

void MainLayout::UpdateTopBannerText() {
    const auto libraryType = this->library->GetType();
    if (libraryType == ILibrary::Type::Local) {
        updateSyncingText(this->topBanner.get(), this->syncUpdateCount);
    }
    else if (libraryType == ILibrary::Type::Remote) {
        updateRemoteLibraryConnectedText(this->topBanner.get(), this->library);
    }
}

void MainLayout::OnLayout() {
    if (this->ShowTopBanner()) {
        const int cx = this->GetContentWidth();
        this->SetPadding(1, 0, 0, 0);
        this->topBanner->MoveAndResize(0, 0, cx, 1);
        this->topBanner->Show();
        this->UpdateTopBannerText();
    }
    else {
        this->SetPadding(0, 0, 0, 0);
        this->topBanner->Hide();
    }

    AppLayout::OnLayout();
}

bool MainLayout::KeyPress(const std::string& key) {
    /* deal with top-level view switching first. */
    if (Hotkeys::Is(Hotkeys::NavigateConsole, key)) {
        this->SetLayout(consoleLayout);
        return true;
    }
    else if (auddio::Available() && Hotkeys::Is(Hotkeys::NavigateLyrics, key)) {
        this->Broadcast(message::JumpToLyrics);
        return true;
    }
    else if (Hotkeys::Is(Hotkeys::NavigateHotkeys, key)) {
        this->SetLayout(hotkeysLayout);
        return true;
    }
    else if (Hotkeys::Is(Hotkeys::NavigateLibrary, key)) {
        this->SwitchToLibraryLayout();
        return true;
    }
    else if (Hotkeys::Is(Hotkeys::NavigateSettings, key)) {
        this->SetLayout(settingsLayout);
        return true;
    }
    else if (key == "M-`") {
        std::string version = u8fmt("%s %s", VERSION, VERSION_COMMIT_HASH);
        ToastOverlay::Show(u8fmt(_TSTR("console_version"), version.c_str()), -1);
        return true;
    }
    else if (this->GetLayout()->KeyPress(key)) {
        return true;
    }
    return AppLayout::KeyPress(key);
}

void MainLayout::Start() {
    MessageQueue().RegisterForBroadcasts(this->shared_from_this());
}

void MainLayout::Stop() {
    MessageQueue().UnregisterForBroadcasts(this);
}

void MainLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
    const int type = message.Type();

    if (type == message::JumpToConsole) {
        this->SetLayout(consoleLayout);
    }
    else if (type == message::JumpToSettings) {
        this->SetLayout(settingsLayout);
    }
    else if (type == message::JumpToLyrics) {
        this->SetLayout(lyricsLayout);
    }
    else if (type == message::JumpToHotkeys) {
        this->SetLayout(hotkeysLayout);
    }
    else if (type == message::JumpToLibrary) {
        this->SwitchToLibraryLayout();
    }
    else if (type == message::JumpToPlayQueue) {
        this->SwitchToPlayQueue();
    }
    else if (type == message::IndexerStarted) {
        this->syncUpdateCount = 0;
        this->Layout();
    }
    else if (type == message::IndexerFinished) {
        this->Layout();
    }
    else if (type == message::IndexerProgress) {
        this->syncUpdateCount = narrow_cast<int>(message.UserData1());
        this->UpdateTopBannerText();
        if (!topBanner->IsVisible()) {
            this->Layout();
        }
    }
    else {
        LayoutBase::ProcessMessage(message);
    }
}

bool MainLayout::IsLibraryConnected() {
    using State = ILibrary::ConnectionState;
    return library->GetConnectionState()  == State::Connected;
}

void MainLayout::SetInitialLayout() {
    if (library->IsConfigured()) {
        this->SwitchToLibraryLayout();
    }
    else {
        this->SetLayout(settingsLayout);
    }
}

void MainLayout::SwitchToPlayQueue() {
    if (IsLibraryConnected()) {
        this->SetLayout(libraryLayout);
        libraryLayout->KeyPress(Hotkeys::Get(Hotkeys::NavigateLibraryPlayQueue));
    }
}

void MainLayout::SwitchToLibraryLayout() {
    if (IsLibraryConnected()) {
        if (!this->libraryLayout) {
            this->libraryLayout = std::make_shared<LibraryLayout>(playback, library);
        }
        this->SetLayout(libraryLayout);
    }
    else {
        this->libraryLayout.reset();
        this->SetLayout(this->libraryNotConnectedLayout);
    }
}

void MainLayout::OnLibraryConnectionStateChanged(ILibrary::ConnectionState state) {
    auto currentLayout = this->GetLayout();
    if (currentLayout == this->libraryLayout ||
        currentLayout == this->libraryNotConnectedLayout)
    {
        this->SwitchToLibraryLayout();
    }
}

void MainLayout::OnLibraryChanged(musik::core::ILibraryPtr prev, musik::core::ILibraryPtr curr) {
    this->playback.Stop();
    this->libraryLayout = std::make_shared<LibraryLayout>(playback, library);
    this->RebindIndexerEventHandlers(prev, curr);
    this->Layout();
}

void MainLayout::RebindIndexerEventHandlers(musik::core::ILibraryPtr prev, musik::core::ILibraryPtr curr) {
    if (prev) {
        prev->Indexer()->Started.disconnect(this);
        prev->Indexer()->Finished.disconnect(this);
        prev->Indexer()->Progress.disconnect(this);
    }
    if (curr) {
        curr->Indexer()->Started.connect(this, &MainLayout::OnIndexerStarted);
        curr->Indexer()->Finished.connect(this, &MainLayout::OnIndexerFinished);
        curr->Indexer()->Progress.connect(this, &MainLayout::OnIndexerProgress);
    }
}

void MainLayout::OnIndexerStarted() {
    this->Post(message::IndexerStarted);
}

void MainLayout::OnIndexerProgress(int count) {
    this->Post(message::IndexerProgress, count);
}

void MainLayout::OnIndexerFinished(int count) {
    this->Post(message::IndexerFinished);
}

void MainLayout::OnTrackChanged(size_t index, musik::core::TrackPtr track) {
    if (prefs->GetBool(
            cube::prefs::keys::DisableWindowTitleUpdates,
            cube::prefs::defaults::DisableWindowTitleUpdates))
    {
        return;
    }

    if (!track) {
        App::Instance().SetTitle("musikcube");
    }
    else {
        App::Instance().SetTitle(u8fmt(
            "musikcube [%s - %s]",
            track->GetString("artist").c_str(),
            track->GetString("title").c_str()));
    }
}

void MainLayout::RunUpdateCheck() {
    if (!prefs->GetBool(cube::prefs::keys::AutoUpdateCheck, true)) {
        return;
    }

    updateCheck.Run([this](bool updateRequired, std::string version, std::string url) {
        if (updateRequired) {
            UpdateCheck::ShowUpgradeAvailableOverlay(version, url);
        }
    });
}
<commit_msg>Fix bug where user may not be able to navigate to lyrics layout.<commit_after>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2021 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include <stdafx.h>

#include <cursespp/Screen.h>
#include <cursespp/Colors.h>
#include <cursespp/ToastOverlay.h>

#include <musikcore/runtime/Message.h>
#include <musikcore/support/Auddio.h>
#include <musikcore/library/RemoteLibrary.h>
#include <musikcore/version.h>

#include <app/util/Messages.h>
#include <app/util/PreferenceKeys.h>
#include <app/layout/ConsoleLayout.h>
#include <app/layout/LyricsLayout.h>
#include <app/layout/LibraryLayout.h>
#include <app/layout/LibraryNotConnectedLayout.h>
#include <app/layout/SettingsLayout.h>
#include <app/layout/HotkeysLayout.h>
#include <app/util/Hotkeys.h>

#include <map>

#include "SettingsLayout.h"
#include "MainLayout.h"

using namespace musik;
using namespace musik::cube;
using namespace musik::core;
using namespace musik::core::library;
using namespace musik::core::runtime;
using namespace cursespp;

using MasterLibraryPtr = MainLayout::MasterLibraryPtr;

static inline void updateSyncingText(TextLabel* label, int updates) {
    try {
        if (updates <= 0) {
            label->SetText(
                _TSTR("main_syncing_banner_start"),
                cursespp::text::AlignCenter);
        }
        else {
            label->SetText(u8fmt(
                _TSTR("main_syncing_banner"), updates),
                cursespp::text::AlignCenter);
        }
    }
    catch (...) {
        /* swallow. incomplete locale. don't crash. */
    }
}

static inline void updateRemoteLibraryConnectedText(TextLabel* label, MasterLibraryPtr library) {
    RemoteLibrary* remoteLibrary = dynamic_cast<RemoteLibrary*>(library->Wrapped().get());
    if (remoteLibrary) {
        std::string host = remoteLibrary->WebSocketClient().Uri();
        if (host.find("ws://") == 0) { host = host.substr(5); }
        auto value = u8fmt(_TSTR("library_remote_connected_banner"), host.c_str());
        label->SetText(value, cursespp::text::AlignCenter);
    }
}

MainLayout::MainLayout(
    cursespp::App& app,
    musik::cube::ConsoleLogger* logger,
    musik::core::audio::PlaybackService& playback,
    MasterLibraryPtr library)
: shortcutsFocused(false)
, syncUpdateCount(0)
, library(library)
, playback(playback)
, AppLayout(app) {
    this->prefs = Preferences::ForComponent("settings");

    library->ConnectionStateChanged.connect(this, &MainLayout::OnLibraryConnectionStateChanged);
    library->LibraryChanged.connect(this, &MainLayout::OnLibraryChanged);
    playback.TrackChanged.connect(this, &MainLayout::OnTrackChanged);

    this->RebindIndexerEventHandlers(ILibraryPtr(), this->library);

    /* note we don't create `libraryLayout` here; instead we do it lazily once we're sure
    it has been connected. see SwitchToLibraryLayout() */
    this->libraryNotConnectedLayout = std::make_shared<LibraryNotConnectedLayout>(library);
    this->lyricsLayout = std::make_shared<LyricsLayout>(playback, library);
    this->consoleLayout = std::make_shared<ConsoleLayout>(logger);
    this->settingsLayout = std::make_shared<SettingsLayout>(app, library, playback);
    this->hotkeysLayout = std::make_shared<HotkeysLayout>();

    this->topBanner = std::make_shared<TextLabel>();
    this->topBanner->SetContentColor(Color::Header);
    this->topBanner->Hide();
    this->AddWindow(this->topBanner);

    /* take user to settings if they don't have a valid configuration. otherwise,
    switch to the library view immediately */
    this->SetInitialLayout();
    this->SetAutoHideCommandBar(this->prefs->GetBool(prefs::keys::AutoHideCommandBar, false));

    this->RunUpdateCheck();
}

MainLayout::~MainLayout() {
    updateCheck.Cancel();
}

bool MainLayout::ShowTopBanner() {
    const auto libraryType = this->library->GetType();
    if (libraryType == ILibrary::Type::Local) {
        return this->library->Indexer()->GetState() == IIndexer::StateIndexing;
    }
    else if (libraryType == ILibrary::Type::Remote) {
        return this->library->GetConnectionState() == ILibrary::ConnectionState::Connected;
    }
    return false;
}

void MainLayout::UpdateTopBannerText() {
    const auto libraryType = this->library->GetType();
    if (libraryType == ILibrary::Type::Local) {
        updateSyncingText(this->topBanner.get(), this->syncUpdateCount);
    }
    else if (libraryType == ILibrary::Type::Remote) {
        updateRemoteLibraryConnectedText(this->topBanner.get(), this->library);
    }
}

void MainLayout::OnLayout() {
    if (this->ShowTopBanner()) {
        const int cx = this->GetContentWidth();
        this->SetPadding(1, 0, 0, 0);
        this->topBanner->MoveAndResize(0, 0, cx, 1);
        this->topBanner->Show();
        this->UpdateTopBannerText();
    }
    else {
        this->SetPadding(0, 0, 0, 0);
        this->topBanner->Hide();
    }

    AppLayout::OnLayout();
}

bool MainLayout::KeyPress(const std::string& key) {
    /* deal with top-level view switching first. */
    if (Hotkeys::Is(Hotkeys::NavigateConsole, key)) {
        this->SetLayout(consoleLayout);
        return true;
    }
    else if (Hotkeys::Is(Hotkeys::NavigateLyrics, key)) {
        this->Broadcast(message::JumpToLyrics);
        return true;
    }
    else if (Hotkeys::Is(Hotkeys::NavigateHotkeys, key)) {
        this->SetLayout(hotkeysLayout);
        return true;
    }
    else if (Hotkeys::Is(Hotkeys::NavigateLibrary, key)) {
        this->SwitchToLibraryLayout();
        return true;
    }
    else if (Hotkeys::Is(Hotkeys::NavigateSettings, key)) {
        this->SetLayout(settingsLayout);
        return true;
    }
    else if (key == "M-`") {
        std::string version = u8fmt("%s %s", VERSION, VERSION_COMMIT_HASH);
        ToastOverlay::Show(u8fmt(_TSTR("console_version"), version.c_str()), -1);
        return true;
    }
    else if (this->GetLayout()->KeyPress(key)) {
        return true;
    }
    return AppLayout::KeyPress(key);
}

void MainLayout::Start() {
    MessageQueue().RegisterForBroadcasts(this->shared_from_this());
}

void MainLayout::Stop() {
    MessageQueue().UnregisterForBroadcasts(this);
}

void MainLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
    const int type = message.Type();

    if (type == message::JumpToConsole) {
        this->SetLayout(consoleLayout);
    }
    else if (type == message::JumpToSettings) {
        this->SetLayout(settingsLayout);
    }
    else if (type == message::JumpToLyrics) {
        this->SetLayout(lyricsLayout);
    }
    else if (type == message::JumpToHotkeys) {
        this->SetLayout(hotkeysLayout);
    }
    else if (type == message::JumpToLibrary) {
        this->SwitchToLibraryLayout();
    }
    else if (type == message::JumpToPlayQueue) {
        this->SwitchToPlayQueue();
    }
    else if (type == message::IndexerStarted) {
        this->syncUpdateCount = 0;
        this->Layout();
    }
    else if (type == message::IndexerFinished) {
        this->Layout();
    }
    else if (type == message::IndexerProgress) {
        this->syncUpdateCount = narrow_cast<int>(message.UserData1());
        this->UpdateTopBannerText();
        if (!topBanner->IsVisible()) {
            this->Layout();
        }
    }
    else {
        LayoutBase::ProcessMessage(message);
    }
}

bool MainLayout::IsLibraryConnected() {
    using State = ILibrary::ConnectionState;
    return library->GetConnectionState()  == State::Connected;
}

void MainLayout::SetInitialLayout() {
    if (library->IsConfigured()) {
        this->SwitchToLibraryLayout();
    }
    else {
        this->SetLayout(settingsLayout);
    }
}

void MainLayout::SwitchToPlayQueue() {
    if (IsLibraryConnected()) {
        this->SetLayout(libraryLayout);
        libraryLayout->KeyPress(Hotkeys::Get(Hotkeys::NavigateLibraryPlayQueue));
    }
}

void MainLayout::SwitchToLibraryLayout() {
    if (IsLibraryConnected()) {
        if (!this->libraryLayout) {
            this->libraryLayout = std::make_shared<LibraryLayout>(playback, library);
        }
        this->SetLayout(libraryLayout);
    }
    else {
        this->libraryLayout.reset();
        this->SetLayout(this->libraryNotConnectedLayout);
    }
}

void MainLayout::OnLibraryConnectionStateChanged(ILibrary::ConnectionState state) {
    auto currentLayout = this->GetLayout();
    if (currentLayout == this->libraryLayout ||
        currentLayout == this->libraryNotConnectedLayout)
    {
        this->SwitchToLibraryLayout();
    }
}

void MainLayout::OnLibraryChanged(musik::core::ILibraryPtr prev, musik::core::ILibraryPtr curr) {
    this->playback.Stop();
    this->libraryLayout = std::make_shared<LibraryLayout>(playback, library);
    this->RebindIndexerEventHandlers(prev, curr);
    this->Layout();
}

void MainLayout::RebindIndexerEventHandlers(musik::core::ILibraryPtr prev, musik::core::ILibraryPtr curr) {
    if (prev) {
        prev->Indexer()->Started.disconnect(this);
        prev->Indexer()->Finished.disconnect(this);
        prev->Indexer()->Progress.disconnect(this);
    }
    if (curr) {
        curr->Indexer()->Started.connect(this, &MainLayout::OnIndexerStarted);
        curr->Indexer()->Finished.connect(this, &MainLayout::OnIndexerFinished);
        curr->Indexer()->Progress.connect(this, &MainLayout::OnIndexerProgress);
    }
}

void MainLayout::OnIndexerStarted() {
    this->Post(message::IndexerStarted);
}

void MainLayout::OnIndexerProgress(int count) {
    this->Post(message::IndexerProgress, count);
}

void MainLayout::OnIndexerFinished(int count) {
    this->Post(message::IndexerFinished);
}

void MainLayout::OnTrackChanged(size_t index, musik::core::TrackPtr track) {
    if (prefs->GetBool(
            cube::prefs::keys::DisableWindowTitleUpdates,
            cube::prefs::defaults::DisableWindowTitleUpdates))
    {
        return;
    }

    if (!track) {
        App::Instance().SetTitle("musikcube");
    }
    else {
        App::Instance().SetTitle(u8fmt(
            "musikcube [%s - %s]",
            track->GetString("artist").c_str(),
            track->GetString("title").c_str()));
    }
}

void MainLayout::RunUpdateCheck() {
    if (!prefs->GetBool(cube::prefs::keys::AutoUpdateCheck, true)) {
        return;
    }

    updateCheck.Run([this](bool updateRequired, std::string version, std::string url) {
        if (updateRequired) {
            UpdateCheck::ShowUpgradeAvailableOverlay(version, url);
        }
    });
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/security_filter_peer.h"

#include "app/gfx/codec/png_codec.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/gfx/size.h"
#include "base/string_util.h"
#include "grit/generated_resources.h"
#include "grit/renderer_resources.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkDevice.h"
#include "webkit/glue/webkit_glue.h"

SecurityFilterPeer::SecurityFilterPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer)
    : original_peer_(peer),
      resource_loader_bridge_(resource_loader_bridge) {
}

SecurityFilterPeer::~SecurityFilterPeer() {
}

// static
SecurityFilterPeer* SecurityFilterPeer::CreateSecurityFilterPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    ResourceType::Type resource_type,
    const std::string& mime_type,
    FilterPolicy::Type filter_policy,
    int os_error) {
  if (filter_policy == FilterPolicy::DONT_FILTER) {
    NOTREACHED();
    return NULL;
  }

  if (StartsWithASCII(mime_type, "image/", false)) {
    // What we do with images depends on details of the |filter_policy|.
    if (filter_policy == FilterPolicy::FILTER_ALL_EXCEPT_IMAGES)
      return new ImageFilterPeer(resource_loader_bridge, peer);
    // Otherwise, fall through to blocking images hard.
  }

  // Regardless of what a frame contents replace it with our error message,
  // so it is visible it's been filtered-out.
  if (ResourceType::IsFrame(resource_type))
    return CreateSecurityFilterPeerForFrame(peer, os_error);

  // Any other content is entirely filtered-out.
  return new ReplaceContentPeer(resource_loader_bridge, peer,
                                std::string(), std::string());
}

// static
SecurityFilterPeer*
    SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
    ResourceType::Type resource_type,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    int os_error) {
  // Create a filter for SSL and CERT errors.
  switch (os_error) {
    case net::ERR_SSL_PROTOCOL_ERROR:
    case net::ERR_CERT_COMMON_NAME_INVALID:
    case net::ERR_CERT_DATE_INVALID:
    case net::ERR_CERT_AUTHORITY_INVALID:
    case net::ERR_CERT_CONTAINS_ERRORS:
    case net::ERR_CERT_NO_REVOCATION_MECHANISM:
    case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
    case net::ERR_CERT_REVOKED:
    case net::ERR_CERT_INVALID:
    case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
    case net::ERR_INSECURE_RESPONSE:
      if (ResourceType::IsFrame(resource_type))
        return CreateSecurityFilterPeerForFrame(peer, os_error);
      // Any other content is entirely filtered-out.
      return new ReplaceContentPeer(NULL, peer, std::string(), std::string());
    default:
      // For other errors, we use our normal error handling.
      return NULL;
  }
}

// static
SecurityFilterPeer* SecurityFilterPeer::CreateSecurityFilterPeerForFrame(
    webkit_glue::ResourceLoaderBridge::Peer* peer, int os_error) {
  // TODO(jcampan): use a different message when getting a phishing/malware
  // error.
  std::wstring error_msg = l10n_util::GetString(IDS_UNSAFE_FRAME_MESSAGE);
  std::string html = StringPrintf(
      ""
      "%s",
      WideToUTF8(error_msg).c_str());
  return new ReplaceContentPeer(NULL, peer, "text/html", html);
}

void SecurityFilterPeer::OnUploadProgress(uint64 position, uint64 size) {
  original_peer_->OnUploadProgress(position, size);
}

bool SecurityFilterPeer::OnReceivedRedirect(
    const GURL& new_url,
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
  NOTREACHED();
  return false;
}

void SecurityFilterPeer::OnReceivedResponse(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
    bool content_filtered) {
  NOTREACHED();
}

void SecurityFilterPeer::OnReceivedData(const char* data, int len) {
  NOTREACHED();
}

void SecurityFilterPeer::OnCompletedRequest(const URLRequestStatus& status,
                                            const std::string& security_info) {
  NOTREACHED();
}

GURL SecurityFilterPeer::GetURLForDebugging() const {
  return original_peer_->GetURLForDebugging();
}

// static
void ProcessResponseInfo(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info_in,
    webkit_glue::ResourceLoaderBridge::ResponseInfo* info_out,
    const std::string& mime_type) {
  DCHECK(info_out);
  *info_out = info_in;
  info_out->mime_type = mime_type;
  // Let's create our own HTTP headers.
  std::string raw_headers;
  raw_headers.append("HTTP/1.1 200 OK");
  raw_headers.push_back('\0');
  // Don't cache the data we are serving, it is not the real data for that URL
  // (if the filtered resource were to make it into the WebCore cache, then the
  // same URL loaded in a safe scenario would still return the filtered
  // resource).
  raw_headers.append("cache-control: no-cache");
  raw_headers.push_back('\0');
  if (!mime_type.empty()) {
    raw_headers.append("content-type: ");
    raw_headers.append(mime_type);
    raw_headers.push_back('\0');
  }
  raw_headers.push_back('\0');
  net::HttpResponseHeaders* new_headers =
      new net::HttpResponseHeaders(raw_headers);
  info_out->headers = new_headers;
}

////////////////////////////////////////////////////////////////////////////////
// BufferedPeer

BufferedPeer::BufferedPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    const std::string& mime_type)
    : SecurityFilterPeer(resource_loader_bridge, peer),
      mime_type_(mime_type) {
}

BufferedPeer::~BufferedPeer() {
}

void BufferedPeer::OnReceivedResponse(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
    bool response_filtered) {
  ProcessResponseInfo(info, &response_info_, mime_type_);
}

void BufferedPeer::OnReceivedData(const char* data, int len) {
  data_.append(data, len);
}

void BufferedPeer::OnCompletedRequest(const URLRequestStatus& status,
                                      const std::string& security_info) {
  // Make sure we delete ourselves at the end of this call.
  scoped_ptr<BufferedPeer> this_deleter(this);

  // Give sub-classes a chance at altering the data.
  if (status.status() != URLRequestStatus::SUCCESS || !DataReady()) {
    // Pretend we failed to load the resource.
    original_peer_->OnReceivedResponse(response_info_, true);
    URLRequestStatus status(URLRequestStatus::CANCELED, net::ERR_ABORTED);
    original_peer_->OnCompletedRequest(status, security_info);
    return;
  }

  original_peer_->OnReceivedResponse(response_info_, true);
  if (!data_.empty())
    original_peer_->OnReceivedData(data_.data(),
                                   static_cast<int>(data_.size()));
  original_peer_->OnCompletedRequest(status, security_info);
}

////////////////////////////////////////////////////////////////////////////////
// ReplaceContentPeer

ReplaceContentPeer::ReplaceContentPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    const std::string& mime_type,
    const std::string& data)
    : SecurityFilterPeer(resource_loader_bridge, peer),
      mime_type_(mime_type),
      data_(data) {
}

ReplaceContentPeer::~ReplaceContentPeer() {
}

void ReplaceContentPeer::OnReceivedResponse(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
    bool content_filtered) {
  // Ignore this, we'll serve some alternate content in OnCompletedRequest.
}

void ReplaceContentPeer::OnReceivedData(const char* data, int len) {
  // Ignore this, we'll serve some alternate content in OnCompletedRequest.
}

void ReplaceContentPeer::OnCompletedRequest(const URLRequestStatus& status,
                                            const std::string& security_info) {
  webkit_glue::ResourceLoaderBridge::ResponseInfo info;
  ProcessResponseInfo(info, &info, mime_type_);
  info.security_info = security_info;
  info.content_length = static_cast<int>(data_.size());
  original_peer_->OnReceivedResponse(info, true);
  if (!data_.empty())
    original_peer_->OnReceivedData(data_.data(),
                                   static_cast<int>(data_.size()));
  original_peer_->OnCompletedRequest(URLRequestStatus(), security_info);

  // The request processing is complete, we must delete ourselves.
  delete this;
}

////////////////////////////////////////////////////////////////////////////////
// ImageFilterPeer

ImageFilterPeer::ImageFilterPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer)
    : BufferedPeer(resource_loader_bridge, peer, "image/png") {
}

ImageFilterPeer::~ImageFilterPeer() {
}

bool ImageFilterPeer::DataReady() {
  static SkBitmap* stamp_bitmap = NULL;
  if (!stamp_bitmap) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    stamp_bitmap = rb.GetBitmapNamed(IDR_INSECURE_CONTENT_STAMP);
    if (!stamp_bitmap) {
      NOTREACHED();
      return false;
    }
  }

  // Let's decode the image we have been given.
  SkBitmap image;
  if (!webkit_glue::DecodeImage(data_, &image))
    return false;  // We could not decode that image.

  // Let's create a new canvas to modify the image.
  SkBitmap canvas_bitmap;
  canvas_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
                          image.width(), image.height());
  canvas_bitmap.allocPixels();
  SkCanvas canvas(canvas_bitmap);

  // Let's paint the actual image with an alpha.
  SkRect rect;
  rect.fLeft = 0;
  rect.fTop = 0;
  rect.fRight = SkIntToScalar(image.width());
  rect.fBottom = SkIntToScalar(image.height());

  SkPaint paint;
  paint.setAlpha(80);
  canvas.drawBitmapRect(image, NULL, rect, &paint);

  // Then stamp-it.
  paint.setAlpha(150);
  int visible_row_count = image.height() / stamp_bitmap->height();
  if (image.height() % stamp_bitmap->height() != 0)
    visible_row_count++;

  for (int row = 0; row < visible_row_count; row++) {
    for (int x = (row % 2 == 0) ? 0 : stamp_bitmap->width(); x < image.width();
         x += stamp_bitmap->width() * 2) {
      canvas.drawBitmap(*stamp_bitmap,
                        SkIntToScalar(x),
                        SkIntToScalar(row * stamp_bitmap->height()),
                        &paint);
    }
  }

  // Now encode it to a PNG.
  std::vector<unsigned char> output;
  if (!gfx::PNGCodec::EncodeBGRASkBitmap(
          canvas.getDevice()->accessBitmap(false), false, &output)) {
    return false;
  }

  // Copy the vector content to data_ which is a string.
  data_.clear();
  data_.resize(output.size());
  std::copy(output.begin(), output.end(), data_.begin());

  return true;
}
<commit_msg>Add 'meta charset=UTF-8' to the html of an iframe interstitial  to prevent non-ASCII characters from being garbled. <commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/security_filter_peer.h"

#include "app/gfx/codec/png_codec.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/gfx/size.h"
#include "base/string_util.h"
#include "grit/generated_resources.h"
#include "grit/renderer_resources.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkDevice.h"
#include "webkit/glue/webkit_glue.h"

SecurityFilterPeer::SecurityFilterPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer)
    : original_peer_(peer),
      resource_loader_bridge_(resource_loader_bridge) {
}

SecurityFilterPeer::~SecurityFilterPeer() {
}

// static
SecurityFilterPeer* SecurityFilterPeer::CreateSecurityFilterPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    ResourceType::Type resource_type,
    const std::string& mime_type,
    FilterPolicy::Type filter_policy,
    int os_error) {
  if (filter_policy == FilterPolicy::DONT_FILTER) {
    NOTREACHED();
    return NULL;
  }

  if (StartsWithASCII(mime_type, "image/", false)) {
    // What we do with images depends on details of the |filter_policy|.
    if (filter_policy == FilterPolicy::FILTER_ALL_EXCEPT_IMAGES)
      return new ImageFilterPeer(resource_loader_bridge, peer);
    // Otherwise, fall through to blocking images hard.
  }

  // Regardless of what a frame contents replace it with our error message,
  // so it is visible it's been filtered-out.
  if (ResourceType::IsFrame(resource_type))
    return CreateSecurityFilterPeerForFrame(peer, os_error);

  // Any other content is entirely filtered-out.
  return new ReplaceContentPeer(resource_loader_bridge, peer,
                                std::string(), std::string());
}

// static
SecurityFilterPeer*
    SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
    ResourceType::Type resource_type,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    int os_error) {
  // Create a filter for SSL and CERT errors.
  switch (os_error) {
    case net::ERR_SSL_PROTOCOL_ERROR:
    case net::ERR_CERT_COMMON_NAME_INVALID:
    case net::ERR_CERT_DATE_INVALID:
    case net::ERR_CERT_AUTHORITY_INVALID:
    case net::ERR_CERT_CONTAINS_ERRORS:
    case net::ERR_CERT_NO_REVOCATION_MECHANISM:
    case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
    case net::ERR_CERT_REVOKED:
    case net::ERR_CERT_INVALID:
    case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
    case net::ERR_INSECURE_RESPONSE:
      if (ResourceType::IsFrame(resource_type))
        return CreateSecurityFilterPeerForFrame(peer, os_error);
      // Any other content is entirely filtered-out.
      return new ReplaceContentPeer(NULL, peer, std::string(), std::string());
    default:
      // For other errors, we use our normal error handling.
      return NULL;
  }
}

// static
SecurityFilterPeer* SecurityFilterPeer::CreateSecurityFilterPeerForFrame(
    webkit_glue::ResourceLoaderBridge::Peer* peer, int os_error) {
  // TODO(jcampan): use a different message when getting a phishing/malware
  // error.
  std::string html = StringPrintf(
      "<meta charset='UTF-8'>"
      ""
      "%s",
      l10n_util::GetStringUTF8(IDS_UNSAFE_FRAME_MESSAGE).c_str());
  return new ReplaceContentPeer(NULL, peer, "text/html", html);
}

void SecurityFilterPeer::OnUploadProgress(uint64 position, uint64 size) {
  original_peer_->OnUploadProgress(position, size);
}

bool SecurityFilterPeer::OnReceivedRedirect(
    const GURL& new_url,
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
  NOTREACHED();
  return false;
}

void SecurityFilterPeer::OnReceivedResponse(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
    bool content_filtered) {
  NOTREACHED();
}

void SecurityFilterPeer::OnReceivedData(const char* data, int len) {
  NOTREACHED();
}

void SecurityFilterPeer::OnCompletedRequest(const URLRequestStatus& status,
                                            const std::string& security_info) {
  NOTREACHED();
}

GURL SecurityFilterPeer::GetURLForDebugging() const {
  return original_peer_->GetURLForDebugging();
}

// static
void ProcessResponseInfo(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info_in,
    webkit_glue::ResourceLoaderBridge::ResponseInfo* info_out,
    const std::string& mime_type) {
  DCHECK(info_out);
  *info_out = info_in;
  info_out->mime_type = mime_type;
  // Let's create our own HTTP headers.
  std::string raw_headers;
  raw_headers.append("HTTP/1.1 200 OK");
  raw_headers.push_back('\0');
  // Don't cache the data we are serving, it is not the real data for that URL
  // (if the filtered resource were to make it into the WebCore cache, then the
  // same URL loaded in a safe scenario would still return the filtered
  // resource).
  raw_headers.append("cache-control: no-cache");
  raw_headers.push_back('\0');
  if (!mime_type.empty()) {
    raw_headers.append("content-type: ");
    raw_headers.append(mime_type);
    raw_headers.push_back('\0');
  }
  raw_headers.push_back('\0');
  net::HttpResponseHeaders* new_headers =
      new net::HttpResponseHeaders(raw_headers);
  info_out->headers = new_headers;
}

////////////////////////////////////////////////////////////////////////////////
// BufferedPeer

BufferedPeer::BufferedPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    const std::string& mime_type)
    : SecurityFilterPeer(resource_loader_bridge, peer),
      mime_type_(mime_type) {
}

BufferedPeer::~BufferedPeer() {
}

void BufferedPeer::OnReceivedResponse(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
    bool response_filtered) {
  ProcessResponseInfo(info, &response_info_, mime_type_);
}

void BufferedPeer::OnReceivedData(const char* data, int len) {
  data_.append(data, len);
}

void BufferedPeer::OnCompletedRequest(const URLRequestStatus& status,
                                      const std::string& security_info) {
  // Make sure we delete ourselves at the end of this call.
  scoped_ptr<BufferedPeer> this_deleter(this);

  // Give sub-classes a chance at altering the data.
  if (status.status() != URLRequestStatus::SUCCESS || !DataReady()) {
    // Pretend we failed to load the resource.
    original_peer_->OnReceivedResponse(response_info_, true);
    URLRequestStatus status(URLRequestStatus::CANCELED, net::ERR_ABORTED);
    original_peer_->OnCompletedRequest(status, security_info);
    return;
  }

  original_peer_->OnReceivedResponse(response_info_, true);
  if (!data_.empty())
    original_peer_->OnReceivedData(data_.data(),
                                   static_cast<int>(data_.size()));
  original_peer_->OnCompletedRequest(status, security_info);
}

////////////////////////////////////////////////////////////////////////////////
// ReplaceContentPeer

ReplaceContentPeer::ReplaceContentPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer,
    const std::string& mime_type,
    const std::string& data)
    : SecurityFilterPeer(resource_loader_bridge, peer),
      mime_type_(mime_type),
      data_(data) {
}

ReplaceContentPeer::~ReplaceContentPeer() {
}

void ReplaceContentPeer::OnReceivedResponse(
    const webkit_glue::ResourceLoaderBridge::ResponseInfo& info,
    bool content_filtered) {
  // Ignore this, we'll serve some alternate content in OnCompletedRequest.
}

void ReplaceContentPeer::OnReceivedData(const char* data, int len) {
  // Ignore this, we'll serve some alternate content in OnCompletedRequest.
}

void ReplaceContentPeer::OnCompletedRequest(const URLRequestStatus& status,
                                            const std::string& security_info) {
  webkit_glue::ResourceLoaderBridge::ResponseInfo info;
  ProcessResponseInfo(info, &info, mime_type_);
  info.security_info = security_info;
  info.content_length = static_cast<int>(data_.size());
  original_peer_->OnReceivedResponse(info, true);
  if (!data_.empty())
    original_peer_->OnReceivedData(data_.data(),
                                   static_cast<int>(data_.size()));
  original_peer_->OnCompletedRequest(URLRequestStatus(), security_info);

  // The request processing is complete, we must delete ourselves.
  delete this;
}

////////////////////////////////////////////////////////////////////////////////
// ImageFilterPeer

ImageFilterPeer::ImageFilterPeer(
    webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
    webkit_glue::ResourceLoaderBridge::Peer* peer)
    : BufferedPeer(resource_loader_bridge, peer, "image/png") {
}

ImageFilterPeer::~ImageFilterPeer() {
}

bool ImageFilterPeer::DataReady() {
  static SkBitmap* stamp_bitmap = NULL;
  if (!stamp_bitmap) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    stamp_bitmap = rb.GetBitmapNamed(IDR_INSECURE_CONTENT_STAMP);
    if (!stamp_bitmap) {
      NOTREACHED();
      return false;
    }
  }

  // Let's decode the image we have been given.
  SkBitmap image;
  if (!webkit_glue::DecodeImage(data_, &image))
    return false;  // We could not decode that image.

  // Let's create a new canvas to modify the image.
  SkBitmap canvas_bitmap;
  canvas_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
                          image.width(), image.height());
  canvas_bitmap.allocPixels();
  SkCanvas canvas(canvas_bitmap);

  // Let's paint the actual image with an alpha.
  SkRect rect;
  rect.fLeft = 0;
  rect.fTop = 0;
  rect.fRight = SkIntToScalar(image.width());
  rect.fBottom = SkIntToScalar(image.height());

  SkPaint paint;
  paint.setAlpha(80);
  canvas.drawBitmapRect(image, NULL, rect, &paint);

  // Then stamp-it.
  paint.setAlpha(150);
  int visible_row_count = image.height() / stamp_bitmap->height();
  if (image.height() % stamp_bitmap->height() != 0)
    visible_row_count++;

  for (int row = 0; row < visible_row_count; row++) {
    for (int x = (row % 2 == 0) ? 0 : stamp_bitmap->width(); x < image.width();
         x += stamp_bitmap->width() * 2) {
      canvas.drawBitmap(*stamp_bitmap,
                        SkIntToScalar(x),
                        SkIntToScalar(row * stamp_bitmap->height()),
                        &paint);
    }
  }

  // Now encode it to a PNG.
  std::vector<unsigned char> output;
  if (!gfx::PNGCodec::EncodeBGRASkBitmap(
          canvas.getDevice()->accessBitmap(false), false, &output)) {
    return false;
  }

  // Copy the vector content to data_ which is a string.
  data_.clear();
  data_.resize(output.size());
  std::copy(output.begin(), output.end(), data_.begin());

  return true;
}
<|endoftext|>


<commit_before>//
// THIS CONTAINS THE IMPLEMENTATION FOR PUBLISHING ON-BOARD CAMERA IMAGES
// ON CRAZYFLIE USING THE CAMERA PUBLISHER CLASS
//
// COPYRIGHT BELONGS TO THE AUTHOR OF THIS CODE
//
// AUTHOR : LAKSHMAN KUMAR
// AFFILIATION : UNIVERSITY OF MARYLAND, MARYLAND ROBOTICS CENTER
// EMAIL : LKUMAR93@UMD.EDU
// LINKEDIN : WWW.LINKEDIN.COM/IN/LAKSHMANKUMAR1993
//
// THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THE MIT LICENSE
// THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF
// THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
//
// BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO
// BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS
// CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
// CONDITIONS.
//

///////////////////////////////////////////
//
//	LIBRARIES
//
///////////////////////////////////////////

#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <string>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <sensor_msgs/image_encodings.h>
#include <image_transport/image_transport.h>
#include <camera_info_manager/camera_info_manager.h>
#include <deep_learning_crazyflie/camera_parameters.h>

using namespace cv;
using namespace std;

///////////////////////////////////////////
//
//	CLASSES
//
///////////////////////////////////////////
class CameraPublisher
{

  //Declare all the necessary variables
  string camera_position;
  int camera_input_id ;
  VideoCapture cap;
  Mat InputImage;
  image_transport::CameraPublisher camera_pub;
  string prefix = "crazyflie/cameras/";
  string postfix = "/image" ;
  string camera_topic_name ;
  sensor_msgs::CameraInfo* camera_info;
  sensor_msgs::CameraInfoPtr camera_info_ptr;

  public:

  //Use the constructor to initialize variables
  CameraPublisher(string position, int id, image_transport::ImageTransport ImageTransporter, double FL_X ,double PP_X ,double FL_Y, double PP_Y, double* DistArray)
  {
	camera_position = position ;
	camera_input_id = id ;
	camera_topic_name = prefix + camera_position + postfix ;
	camera_pub = ImageTransporter.advertiseCamera(camera_topic_name, 1);
	camera_info = new sensor_msgs::CameraInfo ();
	camera_info_ptr = sensor_msgs::CameraInfoPtr (camera_info);

	camera_info_ptr->header.frame_id = camera_position+"_camera";
	camera_info->header.frame_id = camera_position+"_camera";
	camera_info->width = 640;
	camera_info->height = 480;

	camera_info->K.at(0) = FL_X;
	camera_info->K.at(2) = PP_X;
	camera_info->K.at(4) = FL_Y;
	camera_info->K.at(5) = PP_Y;
	camera_info->K.at(8) = 1;
	camera_info->P.at(0) = camera_info->K.at(0);
	camera_info->P.at(1) = 0;
	camera_info->P.at(2) = camera_info->K.at(2);
	camera_info->P.at(3) = 0;
	camera_info->P.at(4) = 0;
	camera_info->P.at(5) = camera_info->K.at(4);
	camera_info->P.at(6) = camera_info->K.at(5);
	camera_info->P.at(7) = 0;
	camera_info->P.at(8) = 0;
	camera_info->P.at(9) = 0;
	camera_info->P.at(10) = 1;
	camera_info->P.at(11) = 0;
	camera_info->distortion_model = "plumb_bob";

	// Make Rotation Matrix an identity matrix
	camera_info->R.at(0) = (double) 1;
	camera_info->R.at(1) = (double) 0;
	camera_info->R.at(2) = (double) 0;
	camera_info->R.at(3) = (double) 0;
	camera_info->R.at(4) = (double) 1;
	camera_info->R.at(5) = (double) 0;
	camera_info->R.at(6) = (double) 0;
	camera_info->R.at(7) = (double) 0;
	camera_info->R.at(8) = (double) 1;

	for (int i = 0; i < 5; i++)
	    camera_info->D.push_back (DistArray[i]);

  }

  // Initialize the camera
  bool Initialize()
  {
  	cap.open(camera_input_id);

    	if( !cap.isOpened() )
	    {
		ROS_ERROR("Could not initialize camera with id : %d ",camera_input_id);
		return false;
	    }

	return true;

  }

  // Publish the image from the camera to the corresponding topic
  void Publish()
  {
        cap >> InputImage;

        if( InputImage.empty() )
	{
		ROS_INFO("Empty image from camera with id : %d ",camera_input_id);
	}
	else
	{
	    sensor_msgs::ImagePtr msg;

	    msg  = cv_bridge::CvImage(std_msgs::Header(), "bgr8", InputImage).toImageMsg();
	    msg->header.stamp = ros::Time::now() ;
	    msg->header.frame_id = camera_position+"_camera";

	    camera_info->header.stamp = ros::Time::now();

	    camera_pub.publish(msg, camera_info_ptr) ;
	}
  }

};

///////////////////////////////////////////
//
//	MAIN FUNCTION
//
///////////////////////////////////////////

int main( int argc, char** argv )
{
    //Initialize the Crazyflie Camera Publisher Node
    ros::init(argc, argv, "crazyflie_camera_node");
    ros::NodeHandle nh;
    image_transport::ImageTransport it(nh);

    int camera_id;
    nh.param<int>("/crazyflie/crazyflie_camera_node/cameras/bottom/id", camera_id, 0);

    //Create a publisher for the bottom facing camera
    CameraPublisher bottom_camera_pub("bottom", camera_id, it, FocalLength_X, FocalLength_Y, PrincipalPoint_X, PrincipalPoint_Y, Distortion);

    //Initialize the camera and check for errors
    bool Initialized = bottom_camera_pub.Initialize();

    //If the camera has been initialized and everything is ok , publish the images from the camera
    while(nh.ok() && Initialized)
    {
	bottom_camera_pub.Publish() ;
    }

    return 0;
}
<commit_msg>Change param id argument<commit_after>//
// THIS CONTAINS THE IMPLEMENTATION FOR PUBLISHING ON-BOARD CAMERA IMAGES
// ON CRAZYFLIE USING THE CAMERA PUBLISHER CLASS
//
// COPYRIGHT BELONGS TO THE AUTHOR OF THIS CODE
//
// AUTHOR : LAKSHMAN KUMAR
// AFFILIATION : UNIVERSITY OF MARYLAND, MARYLAND ROBOTICS CENTER
// EMAIL : LKUMAR93@UMD.EDU
// LINKEDIN : WWW.LINKEDIN.COM/IN/LAKSHMANKUMAR1993
//
// THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THE MIT LICENSE
// THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF
// THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
//
// BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO
// BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS
// CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
// CONDITIONS.
//

///////////////////////////////////////////
//
//	LIBRARIES
//
///////////////////////////////////////////

#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <string>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <sensor_msgs/image_encodings.h>
#include <image_transport/image_transport.h>
#include <camera_info_manager/camera_info_manager.h>
#include <deep_learning_crazyflie/camera_parameters.h>

using namespace cv;
using namespace std;

///////////////////////////////////////////
//
//	CLASSES
//
///////////////////////////////////////////
class CameraPublisher
{

  //Declare all the necessary variables
  string camera_position;
  int camera_input_id ;
  VideoCapture cap;
  Mat InputImage;
  image_transport::CameraPublisher camera_pub;
  string prefix = "crazyflie/cameras/";
  string postfix = "/image" ;
  string camera_topic_name ;
  sensor_msgs::CameraInfo* camera_info;
  sensor_msgs::CameraInfoPtr camera_info_ptr;

  public:

  //Use the constructor to initialize variables
  CameraPublisher(string position, int id, image_transport::ImageTransport ImageTransporter, double FL_X ,double PP_X ,double FL_Y, double PP_Y, double* DistArray)
  {
	camera_position = position ;
	camera_input_id = id ;
	camera_topic_name = prefix + camera_position + postfix ;
	camera_pub = ImageTransporter.advertiseCamera(camera_topic_name, 1);
	camera_info = new sensor_msgs::CameraInfo ();
	camera_info_ptr = sensor_msgs::CameraInfoPtr (camera_info);

	camera_info_ptr->header.frame_id = camera_position+"_camera";
	camera_info->header.frame_id = camera_position+"_camera";
	camera_info->width = 640;
	camera_info->height = 480;

	camera_info->K.at(0) = FL_X;
	camera_info->K.at(2) = PP_X;
	camera_info->K.at(4) = FL_Y;
	camera_info->K.at(5) = PP_Y;
	camera_info->K.at(8) = 1;
	camera_info->P.at(0) = camera_info->K.at(0);
	camera_info->P.at(1) = 0;
	camera_info->P.at(2) = camera_info->K.at(2);
	camera_info->P.at(3) = 0;
	camera_info->P.at(4) = 0;
	camera_info->P.at(5) = camera_info->K.at(4);
	camera_info->P.at(6) = camera_info->K.at(5);
	camera_info->P.at(7) = 0;
	camera_info->P.at(8) = 0;
	camera_info->P.at(9) = 0;
	camera_info->P.at(10) = 1;
	camera_info->P.at(11) = 0;
	camera_info->distortion_model = "plumb_bob";

	// Make Rotation Matrix an identity matrix
	camera_info->R.at(0) = (double) 1;
	camera_info->R.at(1) = (double) 0;
	camera_info->R.at(2) = (double) 0;
	camera_info->R.at(3) = (double) 0;
	camera_info->R.at(4) = (double) 1;
	camera_info->R.at(5) = (double) 0;
	camera_info->R.at(6) = (double) 0;
	camera_info->R.at(7) = (double) 0;
	camera_info->R.at(8) = (double) 1;

	for (int i = 0; i < 5; i++)
	    camera_info->D.push_back (DistArray[i]);

  }

  // Initialize the camera
  bool Initialize()
  {
  	cap.open(camera_input_id);

    	if( !cap.isOpened() )
	    {
		ROS_ERROR("Could not initialize camera with id : %d ",camera_input_id);
		return false;
	    }

	return true;

  }

  // Publish the image from the camera to the corresponding topic
  void Publish()
  {
        cap >> InputImage;

        if( InputImage.empty() )
	{
		ROS_INFO("Empty image from camera with id : %d ",camera_input_id);
	}
	else
	{
	    sensor_msgs::ImagePtr msg;

	    msg  = cv_bridge::CvImage(std_msgs::Header(), "bgr8", InputImage).toImageMsg();
	    msg->header.stamp = ros::Time::now() ;
	    msg->header.frame_id = camera_position+"_camera";

	    camera_info->header.stamp = ros::Time::now();

	    camera_pub.publish(msg, camera_info_ptr) ;
	}
  }

};

///////////////////////////////////////////
//
//	MAIN FUNCTION
//
///////////////////////////////////////////

int main( int argc, char** argv )
{
    //Initialize the Crazyflie Camera Publisher Node
    ros::init(argc, argv, "crazyflie_camera_node");
    ros::NodeHandle nh;
    image_transport::ImageTransport it(nh);

    int camera_id;
    nh.param<int>("crazyflie_camera_node/cameras/bottom/id", camera_id, 0);

    //Create a publisher for the bottom facing camera
    CameraPublisher bottom_camera_pub("bottom", camera_id, it, FocalLength_X, FocalLength_Y, PrincipalPoint_X, PrincipalPoint_Y, Distortion);

    //Initialize the camera and check for errors
    bool Initialized = bottom_camera_pub.Initialize();

    //If the camera has been initialized and everything is ok , publish the images from the camera
    while(nh.ok() && Initialized)
    {
	bottom_camera_pub.Publish() ;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "trikQtsGeneratorPlugin.h"

#include <QtWidgets/QApplication>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>

#include <trikGeneratorBase/trikGeneratorPluginBase.h>
#include <utils/tcpRobotCommunicator.h>

#include "trikQtsMasterGenerator.h"

using namespace trik::qts;
using namespace qReal;

TrikQtsGeneratorPlugin::TrikQtsGeneratorPlugin()
	: mGenerateCodeAction(new QAction(nullptr))
	, mUploadProgramAction(new QAction(nullptr))
	, mRunProgramAction(new QAction(nullptr))
	, mStopRobotAction(new QAction(nullptr))
	, mCommunicator(nullptr)
{
}

TrikQtsGeneratorPlugin::~TrikQtsGeneratorPlugin()
{
	delete mCommunicator;
}

void TrikQtsGeneratorPlugin::init(qReal::PluginConfigurator const &configurator
		, interpreterBase::robotModel::RobotModelManagerInterface const &robotModelManager
		, qrtext::LanguageToolboxInterface &textLanguage)
{
	RobotsGeneratorPluginBase::init(configurator, robotModelManager, textLanguage);
	mCommunicator = new utils::TcpRobotCommunicator("TrikTcpServer");
	mCommunicator->setErrorReporter(configurator.mainWindowInterpretersInterface().errorReporter());
}

QList<ActionInfo> TrikQtsGeneratorPlugin::actions()
{
	QAction *separator = new QAction(this);
	separator->setSeparator(true);
	qReal::ActionInfo separatorInfo(separator, "generators", "tools");

	mGenerateCodeAction->setText(tr("Generate TRIK code"));
	mGenerateCodeAction->setIcon(QIcon(":/images/generateQtsCode.svg"));
	ActionInfo generateCodeActionInfo(mGenerateCodeAction, "generators", "tools");
	connect(mGenerateCodeAction, SIGNAL(triggered()), this, SLOT(generateCode()), Qt::UniqueConnection);

	mUploadProgramAction->setText(tr("Upload program"));
	mUploadProgramAction->setIcon(QIcon(":/images/uploadProgram.svg"));
	ActionInfo uploadProgramActionInfo(mUploadProgramAction, "generators", "tools");
	connect(mUploadProgramAction, SIGNAL(triggered()), this, SLOT(uploadProgram()), Qt::UniqueConnection);

	mRunProgramAction->setText(tr("Run program"));
	mRunProgramAction->setIcon(QIcon(":/images/uploadAndExecuteProgram.svg"));
	ActionInfo runProgramActionInfo(mRunProgramAction, "generators", "tools");
	connect(mRunProgramAction, SIGNAL(triggered()), this, SLOT(runProgram()), Qt::UniqueConnection);

	mStopRobotAction->setText(tr("Stop robot"));
	mStopRobotAction->setIcon(QIcon(":/images/stopRobot.svg"));
	ActionInfo stopRobotActionInfo(mStopRobotAction, "generators", "tools");
	connect(mStopRobotAction, SIGNAL(triggered()), this, SLOT(stopRobot()), Qt::UniqueConnection);

	return {generateCodeActionInfo, uploadProgramActionInfo, runProgramActionInfo, stopRobotActionInfo, separatorInfo};
}

QList<HotKeyActionInfo> TrikQtsGeneratorPlugin::hotKeyActions()
{
	mGenerateCodeAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_G));
	mUploadProgramAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
	mRunProgramAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F5));
	mStopRobotAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_F5));

	HotKeyActionInfo generateCodeInfo("Generator.GenerateTrik", tr("Generate TRIK Code"), mGenerateCodeAction);
	HotKeyActionInfo uploadProgramInfo("Generator.UploadTrik", tr("Upload TRIK Program"), mUploadProgramAction);
	HotKeyActionInfo runProgramInfo("Generator.RunTrik", tr("Run TRIK Program"), mRunProgramAction);
	HotKeyActionInfo stopRobotInfo("Generator.StopTrik", tr("Stop TRIK Robot"), mStopRobotAction);

	return { generateCodeInfo, uploadProgramInfo, runProgramInfo, stopRobotInfo };
}

generatorBase::MasterGeneratorBase *TrikQtsGeneratorPlugin::masterGenerator()
{
	return new TrikQtsMasterGenerator(*mRepo
			, *mMainWindowInterface->errorReporter()
			, *mRobotModelManager
			, *mTextLanguage
			, mMainWindowInterface->activeDiagram()
			, generatorName());
}

QString TrikQtsGeneratorPlugin::defaultFilePath(QString const &projectName) const
{
	return QString("trik/%1/%1.qts").arg(projectName);
}

text::LanguageInfo TrikQtsGeneratorPlugin::language() const
{
	return qReal::text::Languages::qtScript({ "brick" });
}

QString TrikQtsGeneratorPlugin::generatorName() const
{
	return "trikQts";
}

bool TrikQtsGeneratorPlugin::uploadProgram()
{
	QFileInfo const fileInfo = generateCodeForProcessing();

	if (fileInfo != QFileInfo() && !fileInfo.absoluteFilePath().isEmpty()) {
		bool const result = mCommunicator->uploadProgram(fileInfo.absoluteFilePath());
		if (!result) {
			mMainWindowInterface->errorReporter()->addError(tr("No connection to robot"));
		}

		return result;
	} else {
		qDebug() << "Code generation failed, aborting";
		return false;
	}
}

void TrikQtsGeneratorPlugin::runProgram()
{
	if (uploadProgram()) {
		QFileInfo const fileInfo = generateCodeForProcessing();
		mCommunicator->runProgram(fileInfo.fileName());
	} else {
		qDebug() << "Program upload failed, aborting";
	}
}

void TrikQtsGeneratorPlugin::stopRobot()
{
	if (!mCommunicator->stopRobot()) {
		mMainWindowInterface->errorReporter()->addError(tr("No connection to robot"));
	}

	mCommunicator->runDirectCommand(
			"brick.system(\"killall aplay\"); \n"
			"brick.system(\"killall vlc\"); \n"
			"brick.system(\"killall rover-cv\");"
			, true
			);
}
<commit_msg>rover-cv removed<commit_after>#include "trikQtsGeneratorPlugin.h"

#include <QtWidgets/QApplication>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>

#include <trikGeneratorBase/trikGeneratorPluginBase.h>
#include <utils/tcpRobotCommunicator.h>

#include "trikQtsMasterGenerator.h"

using namespace trik::qts;
using namespace qReal;

TrikQtsGeneratorPlugin::TrikQtsGeneratorPlugin()
	: mGenerateCodeAction(new QAction(nullptr))
	, mUploadProgramAction(new QAction(nullptr))
	, mRunProgramAction(new QAction(nullptr))
	, mStopRobotAction(new QAction(nullptr))
	, mCommunicator(nullptr)
{
}

TrikQtsGeneratorPlugin::~TrikQtsGeneratorPlugin()
{
	delete mCommunicator;
}

void TrikQtsGeneratorPlugin::init(qReal::PluginConfigurator const &configurator
		, interpreterBase::robotModel::RobotModelManagerInterface const &robotModelManager
		, qrtext::LanguageToolboxInterface &textLanguage)
{
	RobotsGeneratorPluginBase::init(configurator, robotModelManager, textLanguage);
	mCommunicator = new utils::TcpRobotCommunicator("TrikTcpServer");
	mCommunicator->setErrorReporter(configurator.mainWindowInterpretersInterface().errorReporter());
}

QList<ActionInfo> TrikQtsGeneratorPlugin::actions()
{
	QAction *separator = new QAction(this);
	separator->setSeparator(true);
	qReal::ActionInfo separatorInfo(separator, "generators", "tools");

	mGenerateCodeAction->setText(tr("Generate TRIK code"));
	mGenerateCodeAction->setIcon(QIcon(":/images/generateQtsCode.svg"));
	ActionInfo generateCodeActionInfo(mGenerateCodeAction, "generators", "tools");
	connect(mGenerateCodeAction, SIGNAL(triggered()), this, SLOT(generateCode()), Qt::UniqueConnection);

	mUploadProgramAction->setText(tr("Upload program"));
	mUploadProgramAction->setIcon(QIcon(":/images/uploadProgram.svg"));
	ActionInfo uploadProgramActionInfo(mUploadProgramAction, "generators", "tools");
	connect(mUploadProgramAction, SIGNAL(triggered()), this, SLOT(uploadProgram()), Qt::UniqueConnection);

	mRunProgramAction->setText(tr("Run program"));
	mRunProgramAction->setIcon(QIcon(":/images/uploadAndExecuteProgram.svg"));
	ActionInfo runProgramActionInfo(mRunProgramAction, "generators", "tools");
	connect(mRunProgramAction, SIGNAL(triggered()), this, SLOT(runProgram()), Qt::UniqueConnection);

	mStopRobotAction->setText(tr("Stop robot"));
	mStopRobotAction->setIcon(QIcon(":/images/stopRobot.svg"));
	ActionInfo stopRobotActionInfo(mStopRobotAction, "generators", "tools");
	connect(mStopRobotAction, SIGNAL(triggered()), this, SLOT(stopRobot()), Qt::UniqueConnection);

	return {generateCodeActionInfo, uploadProgramActionInfo, runProgramActionInfo, stopRobotActionInfo, separatorInfo};
}

QList<HotKeyActionInfo> TrikQtsGeneratorPlugin::hotKeyActions()
{
	mGenerateCodeAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_G));
	mUploadProgramAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
	mRunProgramAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F5));
	mStopRobotAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_F5));

	HotKeyActionInfo generateCodeInfo("Generator.GenerateTrik", tr("Generate TRIK Code"), mGenerateCodeAction);
	HotKeyActionInfo uploadProgramInfo("Generator.UploadTrik", tr("Upload TRIK Program"), mUploadProgramAction);
	HotKeyActionInfo runProgramInfo("Generator.RunTrik", tr("Run TRIK Program"), mRunProgramAction);
	HotKeyActionInfo stopRobotInfo("Generator.StopTrik", tr("Stop TRIK Robot"), mStopRobotAction);

	return { generateCodeInfo, uploadProgramInfo, runProgramInfo, stopRobotInfo };
}

generatorBase::MasterGeneratorBase *TrikQtsGeneratorPlugin::masterGenerator()
{
	return new TrikQtsMasterGenerator(*mRepo
			, *mMainWindowInterface->errorReporter()
			, *mRobotModelManager
			, *mTextLanguage
			, mMainWindowInterface->activeDiagram()
			, generatorName());
}

QString TrikQtsGeneratorPlugin::defaultFilePath(QString const &projectName) const
{
	return QString("trik/%1/%1.qts").arg(projectName);
}

text::LanguageInfo TrikQtsGeneratorPlugin::language() const
{
	return qReal::text::Languages::qtScript({ "brick" });
}

QString TrikQtsGeneratorPlugin::generatorName() const
{
	return "trikQts";
}

bool TrikQtsGeneratorPlugin::uploadProgram()
{
	QFileInfo const fileInfo = generateCodeForProcessing();

	if (fileInfo != QFileInfo() && !fileInfo.absoluteFilePath().isEmpty()) {
		bool const result = mCommunicator->uploadProgram(fileInfo.absoluteFilePath());
		if (!result) {
			mMainWindowInterface->errorReporter()->addError(tr("No connection to robot"));
		}

		return result;
	} else {
		qDebug() << "Code generation failed, aborting";
		return false;
	}
}

void TrikQtsGeneratorPlugin::runProgram()
{
	if (uploadProgram()) {
		QFileInfo const fileInfo = generateCodeForProcessing();
		mCommunicator->runProgram(fileInfo.fileName());
	} else {
		qDebug() << "Program upload failed, aborting";
	}
}

void TrikQtsGeneratorPlugin::stopRobot()
{
	if (!mCommunicator->stopRobot()) {
		mMainWindowInterface->errorReporter()->addError(tr("No connection to robot"));
	}

	mCommunicator->runDirectCommand(
			"brick.system(\"killall aplay\"); \n"
			"brick.system(\"killall vlc\");"
			, true
			);
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#ifndef PCL_PCA_IMPL_HPP
#define PCL_PCA_IMPL_HPP

#include <Eigen/Eigenvalues>
#include "pcl/point_types.h"
#include "pcl/common/centroid.h"
#include "pcl/common/transforms.h"
#include "pcl/exceptions.h"

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT>
pcl::PCA<PointT>::PCA (const pcl::PointCloud<PointT>& X, bool basis_only)
{
  Base ();
  basis_only_ = basis_only;
  setInputCloud (X.makeShared ());
  compute_done_ = initCompute ();
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> bool
pcl::PCA<PointT>::initCompute ()
{
  if(!Base::initCompute ())
  {
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::initCompute] failed");
    return (false);
  }
  if(indices_->size () < 3)
  {
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::initCompute] number of points < 3");
    return (false);
  }

  // Compute mean
  mean_ = Eigen::Vector4f::Zero ();
  compute3DCentroid (*input_, *indices_, mean_);
  // Compute demeanished cloud
  Eigen::MatrixXf cloud_demean;
  demeanPointCloud (*input_, *indices_, mean_, cloud_demean);
  assert (cloud_demean.cols () == int (indices_->size ()));
  // Compute the product cloud_demean * cloud_demean^T
  Eigen::Matrix3f alpha = cloud_demean.topRows<3> () * cloud_demean.topRows<3> ().transpose ();

  // Compute eigen vectors and values
  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> evd (alpha);
  // Organize eigenvectors and eigenvalues in ascendent order
  for (int i = 0; i < 3; ++i)
  {
    eigenvalues_[i] = evd.eigenvalues () [2-i];
    eigenvectors_.col (i) = evd.eigenvectors ().col (2-i);
  }
  // If not basis only then compute the coefficients

  if (!basis_only_)
    // 3x3 = 3x3 * 3x3
    coefficients_ = eigenvectors_.transpose() * (cloud_demean.topRows<3>()).leftCols<3> ();
  compute_done_ = true;
  return (true);
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::update (const PointT& input_point, FLAG flag)
{
  if (!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::update] PCA initCompute failed");

  Eigen::Vector3f input (input_point.x, input_point.y, input_point.z);
  const size_t n = eigenvectors_.cols ();// number of eigen vectors
  Eigen::VectorXf meanp = (float(n) * (mean_.head<3>() + input)) / float(n + 1);
  Eigen::VectorXf a = eigenvectors_.transpose() * (input - mean_.head<3>());
  Eigen::VectorXf y = (eigenvectors_ * a) + mean_.head<3>();
  Eigen::VectorXf h = y - input;
  if (h.norm() > 0)
    h.normalize ();
  else
    h.setZero ();
  float gamma = h.dot(input - mean_.head<3>());
  Eigen::MatrixXf D = Eigen::MatrixXf::Zero (a.size() + 1, a.size() + 1);
  D.block(0,0,n,n) = a * a.transpose();
  D /=  float(n)/float((n+1) * (n+1));
  for(std::size_t i=0; i < a.size(); i++) {
    D(i,i)+= float(n)/float(n+1)*eigenvalues_(i);
    D(D.rows()-1,i) = float(n) / float((n+1) * (n+1)) * gamma * a(i);
    D(i,D.cols()-1) = D(D.rows()-1,i);
    D(D.rows()-1,D.cols()-1) = float(n)/float((n+1) * (n+1)) * gamma * gamma;
  }

  Eigen::MatrixXf R(D.rows(), D.cols());
  Eigen::EigenSolver<Eigen::MatrixXf> D_evd (D, false);
  Eigen::VectorXf alphap = D_evd.eigenvalues().real();
  eigenvalues_.resize(eigenvalues_.size() +1);
  for(std::size_t i=0;i<eigenvalues_.size();i++) {
    eigenvalues_(i) = alphap(eigenvalues_.size()-i-1);
    R.col(i) = D.col(D.cols()-i-1);
  }
  Eigen::MatrixXf Up = Eigen::MatrixXf::Zero(eigenvectors_.rows(), eigenvectors_.cols()+1);
  Up.topLeftCorner(eigenvectors_.rows(),eigenvectors_.cols()) = eigenvectors_;
  Up.rightCols<1>() = h;
  eigenvectors_ = Up*R;
  if (!basis_only_) {
    Eigen::Vector3f etha = Up.transpose() * (mean_.head<3>() - meanp);
    coefficients_.resize(coefficients_.rows()+1,coefficients_.cols()+1);
    for(std::size_t i=0; i < (coefficients_.cols() - 1); i++) {
      coefficients_(coefficients_.rows()-1,i) = 0;
      coefficients_.col(i) = (R.transpose() * coefficients_.col(i)) + etha;
    }
    a.resize(a.size()+1);
    a(a.size()-1) = 0;
    coefficients_.col(coefficients_.cols()-1) = (R.transpose() * a) + etha;
  }
  mean_.head<3>() = meanp;
  switch (flag)
  {
    case increase:
      if (eigenvectors_.rows() >= eigenvectors_.cols())
        break;
    case preserve:
      if (!basis_only_)
        coefficients_ = coefficients_.topRows(coefficients_.rows() - 1);
      eigenvectors_ = eigenvectors_.leftCols(eigenvectors_.cols() - 1);
      eigenvalues_.resize(eigenvalues_.size()-1);
      break;
    default:
      PCL_ERROR("[pcl::PCA] unknown flag\n");
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::project (const PointT& input, PointT& projection)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::project] PCA initCompute failed");

  Eigen::Vector3f demean_input = input.getVector3fMap () - mean_.head<3> ();
  projection.getVector3fMap () = eigenvectors_.transpose() * demean_input;
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::project (const PointCloud& input, PointCloud& projection)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::project] PCA initCompute failed");
  if (input.is_dense)
  {
    projection.resize (input.size ());
    for (size_t i = 0; i < input.size (); ++i)
      project (input[i], projection[i]);
  }
  else
  {
    PointT p;
    for (size_t i = 0; i < input.size (); ++i)
    {
      if (!pcl_isfinite (input[i].x) ||
          !pcl_isfinite (input[i].y) ||
          !pcl_isfinite (input[i].z))
        continue;
      project (input[i], p);
      projection.push_back (p);
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::reconstruct (const PointT& projection, PointT& input)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::reconstruct] PCA initCompute failed");

  input.getVector3fMap ()= eigenvectors_ * projection.getVector3fMap ();
  input.getVector3fMap ()+= mean_.head<3> ();
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::reconstruct (const PointCloud& projection, PointCloud& input)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::reconstruct] PCA initCompute failed");
  if (input.is_dense)
  {
    input.resize (projection.size ());
    for (size_t i = 0; i < projection.size (); ++i)
      reconstruct (projection[i], input[i]);
  }
  else
  {
    PointT p;
    for (size_t i = 0; i < input.size (); ++i)
    {
      if (!pcl_isfinite (input[i].x) ||
          !pcl_isfinite (input[i].y) ||
          !pcl_isfinite (input[i].z))
        continue;
      reconstruct (projection[i], p);
      input.push_back (p);
    }
  }
}

#endif
<commit_msg>Correct coeffcients formula<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#ifndef PCL_PCA_IMPL_HPP
#define PCL_PCA_IMPL_HPP

#include <Eigen/Eigenvalues>
#include "pcl/point_types.h"
#include "pcl/common/centroid.h"
#include "pcl/common/transforms.h"
#include "pcl/exceptions.h"

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT>
pcl::PCA<PointT>::PCA (const pcl::PointCloud<PointT>& X, bool basis_only)
{
  Base ();
  basis_only_ = basis_only;
  setInputCloud (X.makeShared ());
  compute_done_ = initCompute ();
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> bool
pcl::PCA<PointT>::initCompute ()
{
  if(!Base::initCompute ())
  {
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::initCompute] failed");
    return (false);
  }
  if(indices_->size () < 3)
  {
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::initCompute] number of points < 3");
    return (false);
  }

  // Compute mean
  mean_ = Eigen::Vector4f::Zero ();
  compute3DCentroid (*input_, *indices_, mean_);
  // Compute demeanished cloud
  Eigen::MatrixXf cloud_demean;
  demeanPointCloud (*input_, *indices_, mean_, cloud_demean);
  assert (cloud_demean.cols () == int (indices_->size ()));
  // Compute the product cloud_demean * cloud_demean^T
  Eigen::Matrix3f alpha = cloud_demean.topRows<3> () * cloud_demean.topRows<3> ().transpose ();

  // Compute eigen vectors and values
  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> evd (alpha);
  // Organize eigenvectors and eigenvalues in ascendent order
  for (int i = 0; i < 3; ++i)
  {
    eigenvalues_[i] = evd.eigenvalues () [2-i];
    eigenvectors_.col (i) = evd.eigenvectors ().col (2-i);
  }
  // If not basis only then compute the coefficients

  if (!basis_only_)
    coefficients_ = eigenvectors_.transpose() * cloud_demean.topRows<3> ();
  compute_done_ = true;
  return (true);
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::update (const PointT& input_point, FLAG flag)
{
  if (!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::update] PCA initCompute failed");

  Eigen::Vector3f input (input_point.x, input_point.y, input_point.z);
  const size_t n = eigenvectors_.cols ();// number of eigen vectors
  Eigen::VectorXf meanp = (float(n) * (mean_.head<3>() + input)) / float(n + 1);
  Eigen::VectorXf a = eigenvectors_.transpose() * (input - mean_.head<3>());
  Eigen::VectorXf y = (eigenvectors_ * a) + mean_.head<3>();
  Eigen::VectorXf h = y - input;
  if (h.norm() > 0)
    h.normalize ();
  else
    h.setZero ();
  float gamma = h.dot(input - mean_.head<3>());
  Eigen::MatrixXf D = Eigen::MatrixXf::Zero (a.size() + 1, a.size() + 1);
  D.block(0,0,n,n) = a * a.transpose();
  D /=  float(n)/float((n+1) * (n+1));
  for(std::size_t i=0; i < a.size(); i++) {
    D(i,i)+= float(n)/float(n+1)*eigenvalues_(i);
    D(D.rows()-1,i) = float(n) / float((n+1) * (n+1)) * gamma * a(i);
    D(i,D.cols()-1) = D(D.rows()-1,i);
    D(D.rows()-1,D.cols()-1) = float(n)/float((n+1) * (n+1)) * gamma * gamma;
  }

  Eigen::MatrixXf R(D.rows(), D.cols());
  Eigen::EigenSolver<Eigen::MatrixXf> D_evd (D, false);
  Eigen::VectorXf alphap = D_evd.eigenvalues().real();
  eigenvalues_.resize(eigenvalues_.size() +1);
  for(std::size_t i=0;i<eigenvalues_.size();i++) {
    eigenvalues_(i) = alphap(eigenvalues_.size()-i-1);
    R.col(i) = D.col(D.cols()-i-1);
  }
  Eigen::MatrixXf Up = Eigen::MatrixXf::Zero(eigenvectors_.rows(), eigenvectors_.cols()+1);
  Up.topLeftCorner(eigenvectors_.rows(),eigenvectors_.cols()) = eigenvectors_;
  Up.rightCols<1>() = h;
  eigenvectors_ = Up*R;
  if (!basis_only_) {
    Eigen::Vector3f etha = Up.transpose() * (mean_.head<3>() - meanp);
    coefficients_.resize(coefficients_.rows()+1,coefficients_.cols()+1);
    for(std::size_t i=0; i < (coefficients_.cols() - 1); i++) {
      coefficients_(coefficients_.rows()-1,i) = 0;
      coefficients_.col(i) = (R.transpose() * coefficients_.col(i)) + etha;
    }
    a.resize(a.size()+1);
    a(a.size()-1) = 0;
    coefficients_.col(coefficients_.cols()-1) = (R.transpose() * a) + etha;
  }
  mean_.head<3>() = meanp;
  switch (flag)
  {
    case increase:
      if (eigenvectors_.rows() >= eigenvectors_.cols())
        break;
    case preserve:
      if (!basis_only_)
        coefficients_ = coefficients_.topRows(coefficients_.rows() - 1);
      eigenvectors_ = eigenvectors_.leftCols(eigenvectors_.cols() - 1);
      eigenvalues_.resize(eigenvalues_.size()-1);
      break;
    default:
      PCL_ERROR("[pcl::PCA] unknown flag\n");
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::project (const PointT& input, PointT& projection)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::project] PCA initCompute failed");

  Eigen::Vector3f demean_input = input.getVector3fMap () - mean_.head<3> ();
  projection.getVector3fMap () = eigenvectors_.transpose() * demean_input;
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::project (const PointCloud& input, PointCloud& projection)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::project] PCA initCompute failed");
  if (input.is_dense)
  {
    projection.resize (input.size ());
    for (size_t i = 0; i < input.size (); ++i)
      project (input[i], projection[i]);
  }
  else
  {
    PointT p;
    for (size_t i = 0; i < input.size (); ++i)
    {
      if (!pcl_isfinite (input[i].x) ||
          !pcl_isfinite (input[i].y) ||
          !pcl_isfinite (input[i].z))
        continue;
      project (input[i], p);
      projection.push_back (p);
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::reconstruct (const PointT& projection, PointT& input)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::reconstruct] PCA initCompute failed");

  input.getVector3fMap ()= eigenvectors_ * projection.getVector3fMap ();
  input.getVector3fMap ()+= mean_.head<3> ();
}

/////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> inline void
pcl::PCA<PointT>::reconstruct (const PointCloud& projection, PointCloud& input)
{
  if(!compute_done_)
    initCompute ();
  if (!compute_done_)
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::reconstruct] PCA initCompute failed");
  if (input.is_dense)
  {
    input.resize (projection.size ());
    for (size_t i = 0; i < projection.size (); ++i)
      reconstruct (projection[i], input[i]);
  }
  else
  {
    PointT p;
    for (size_t i = 0; i < input.size (); ++i)
    {
      if (!pcl_isfinite (input[i].x) ||
          !pcl_isfinite (input[i].y) ||
          !pcl_isfinite (input[i].z))
        continue;
      reconstruct (projection[i], p);
      input.push_back (p);
    }
  }
}

#endif
<|endoftext|>