<commit_before>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, Intel Corporation
 *
 * 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 Intel Corporation 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 LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FrequencyGovernorImp.hpp"

#include <cmath>
#include <unistd.h>

#include <vector>

#include "Exception.hpp"
#include "Helper.hpp"
#include "PlatformIO.hpp"
#include "PlatformTopo.hpp"
#include "config.h"

namespace geopm
{
    std::unique_ptr<FrequencyGovernor> FrequencyGovernor::make_unique(void)
    {
        return geopm::make_unique<FrequencyGovernorImp>();
    }

    std::shared_ptr<FrequencyGovernor> FrequencyGovernor::make_shared(void)
    {
        return std::make_shared<FrequencyGovernorImp>();
    }

    FrequencyGovernorImp::FrequencyGovernorImp()
        : FrequencyGovernorImp(platform_io(), platform_topo())
    {

    }

    FrequencyGovernorImp::FrequencyGovernorImp(PlatformIO &platform_io, const PlatformTopo &platform_topo)
        : m_platform_io(platform_io)
        , m_platform_topo(platform_topo)
        , M_FREQ_STEP(get_limit("CPUINFO::FREQ_STEP"))
        , M_PLAT_FREQ_MIN(get_limit("CPUINFO::FREQ_MIN"))
        , M_PLAT_FREQ_MAX(get_limit("FREQUENCY_MAX"))
        , m_freq_min(M_PLAT_FREQ_MIN)
        , m_freq_max(M_PLAT_FREQ_MAX)
        , m_do_write_batch(false)
        , m_freq_ctl_domain_type(m_platform_io.control_domain_type("FREQUENCY"))
    {

    }

    FrequencyGovernorImp::~FrequencyGovernorImp()
    {

    }

    double FrequencyGovernorImp::get_limit(const std::string &sig_name) const
    {
        const int domain_type = m_platform_io.signal_domain_type(sig_name);
        double result = NAN;
        if (sig_name == "CPUINFO::FREQ_MIN") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "CPUINFO::FREQ_STICKER") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "CPUINFO::FREQ_STEP") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "FREQUENCY_MAX") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
#ifdef GEOPM_DEBUG
        else {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): requested invalid signal name.",
                            GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
        }
#endif
        return result;
    }

    void FrequencyGovernorImp::init_platform_io(void)
    {
        m_last_freq = std::vector<double>(m_freq_ctl_domain_type, NAN);
        const int num_freq_ctl_domain = m_platform_topo.num_domain(m_freq_ctl_domain_type);
        for (int ctl_dom_idx = 0; ctl_dom_idx != num_freq_ctl_domain; ++ctl_dom_idx) {
            m_control_idx.push_back(m_platform_io.push_control("FREQUENCY",
                                                               m_freq_ctl_domain_type,
                                                               ctl_dom_idx));
        }
    }

    int FrequencyGovernorImp::frequency_domain_type(void) const
    {
        return m_freq_ctl_domain_type;
    }

    void FrequencyGovernorImp::adjust_platform(const std::vector<double> &frequency_request)
    {
        if (frequency_request.size() != m_control_idx.size()) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) +
                            "(): size of request vector does not match size of control domain.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);
        }

        m_do_write_batch = !std::equal(m_last_freq.begin(), m_last_freq.end(), frequency_request.begin());
        std::vector<double> frequency_actual;
        for (size_t idx = 0; idx < m_control_idx.size(); ++idx) {
            double clamp_freq = NAN;
            if (frequency_request[idx] > m_freq_max) {
                clamp_freq = m_freq_max;
            }
            else if (frequency_request[idx] < m_freq_min) {
                clamp_freq = m_freq_min;
            }
            else {
                clamp_freq = frequency_request[idx];
            }
            frequency_actual.push_back(clamp_freq);
            m_platform_io.adjust(m_control_idx[idx], frequency_actual[idx]);
        }
        m_last_freq = frequency_actual;
    }

    bool FrequencyGovernorImp::do_write_batch(void) const
    {
        return m_do_write_batch;
    }

    bool FrequencyGovernorImp::set_frequency_bounds(double freq_min, double freq_max)
    {
        if (freq_min < M_PLAT_FREQ_MIN || freq_max > M_PLAT_FREQ_MAX ||
            freq_min > freq_max) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): invalid frequency bounds.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);

        }
        bool result = false;
        if (m_freq_min != freq_min ||
            m_freq_max != freq_max) {
            m_freq_min = freq_min;
            m_freq_max = freq_max;
            result = true;
        }
        return result;
    }

    double FrequencyGovernorImp::get_frequency_min()  const
    {
        return m_freq_min;
    }

    double FrequencyGovernorImp::get_frequency_max()  const
    {
        return m_freq_max;
    }

    double FrequencyGovernorImp::get_frequency_step()  const
    {
        return M_FREQ_STEP;
    }

    void FrequencyGovernorImp::validate_policy(double &freq_min, double &freq_max) const
    {
        double target_freq_min = std::isnan(freq_min) ? get_limit("CPUINFO::FREQ_MIN") : freq_min;
        double target_freq_max = std::isnan(freq_max) ? get_limit("CPUINFO::FREQ_STICKER") : freq_max;
        freq_min = target_freq_min;
        freq_max = target_freq_max;
    }
}
<commit_msg>Fix m_last_freq size init in FrequencyGovernor<commit_after>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, Intel Corporation
 *
 * 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 Intel Corporation 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 LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FrequencyGovernorImp.hpp"

#include <cmath>
#include <unistd.h>

#include <vector>

#include "Exception.hpp"
#include "Helper.hpp"
#include "PlatformIO.hpp"
#include "PlatformTopo.hpp"
#include "config.h"

namespace geopm
{
    std::unique_ptr<FrequencyGovernor> FrequencyGovernor::make_unique(void)
    {
        return geopm::make_unique<FrequencyGovernorImp>();
    }

    std::shared_ptr<FrequencyGovernor> FrequencyGovernor::make_shared(void)
    {
        return std::make_shared<FrequencyGovernorImp>();
    }

    FrequencyGovernorImp::FrequencyGovernorImp()
        : FrequencyGovernorImp(platform_io(), platform_topo())
    {

    }

    FrequencyGovernorImp::FrequencyGovernorImp(PlatformIO &platform_io, const PlatformTopo &platform_topo)
        : m_platform_io(platform_io)
        , m_platform_topo(platform_topo)
        , M_FREQ_STEP(get_limit("CPUINFO::FREQ_STEP"))
        , M_PLAT_FREQ_MIN(get_limit("CPUINFO::FREQ_MIN"))
        , M_PLAT_FREQ_MAX(get_limit("FREQUENCY_MAX"))
        , m_freq_min(M_PLAT_FREQ_MIN)
        , m_freq_max(M_PLAT_FREQ_MAX)
        , m_do_write_batch(false)
        , m_freq_ctl_domain_type(m_platform_io.control_domain_type("FREQUENCY"))
    {

    }

    FrequencyGovernorImp::~FrequencyGovernorImp()
    {

    }

    double FrequencyGovernorImp::get_limit(const std::string &sig_name) const
    {
        const int domain_type = m_platform_io.signal_domain_type(sig_name);
        double result = NAN;
        if (sig_name == "CPUINFO::FREQ_MIN") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "CPUINFO::FREQ_STICKER") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "CPUINFO::FREQ_STEP") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "FREQUENCY_MAX") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
#ifdef GEOPM_DEBUG
        else {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): requested invalid signal name.",
                            GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
        }
#endif
        return result;
    }

    void FrequencyGovernorImp::init_platform_io(void)
    {
        const int num_freq_ctl_domain = m_platform_topo.num_domain(m_freq_ctl_domain_type);
        m_last_freq = std::vector<double>(num_freq_ctl_domain, NAN);
        for (int ctl_dom_idx = 0; ctl_dom_idx != num_freq_ctl_domain; ++ctl_dom_idx) {
            m_control_idx.push_back(m_platform_io.push_control("FREQUENCY",
                                                               m_freq_ctl_domain_type,
                                                               ctl_dom_idx));
        }
    }

    int FrequencyGovernorImp::frequency_domain_type(void) const
    {
        return m_freq_ctl_domain_type;
    }

    void FrequencyGovernorImp::adjust_platform(const std::vector<double> &frequency_request)
    {
        if (frequency_request.size() != m_control_idx.size()) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) +
                            "(): size of request vector does not match size of control domain.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);
        }

        m_do_write_batch = !std::equal(m_last_freq.begin(), m_last_freq.end(), frequency_request.begin());
        std::vector<double> frequency_actual;
        for (size_t idx = 0; idx < m_control_idx.size(); ++idx) {
            double clamp_freq = NAN;
            if (frequency_request[idx] > m_freq_max) {
                clamp_freq = m_freq_max;
            }
            else if (frequency_request[idx] < m_freq_min) {
                clamp_freq = m_freq_min;
            }
            else {
                clamp_freq = frequency_request[idx];
            }
            frequency_actual.push_back(clamp_freq);
            m_platform_io.adjust(m_control_idx[idx], frequency_actual[idx]);
        }
        m_last_freq = frequency_actual;
    }

    bool FrequencyGovernorImp::do_write_batch(void) const
    {
        return m_do_write_batch;
    }

    bool FrequencyGovernorImp::set_frequency_bounds(double freq_min, double freq_max)
    {
        if (freq_min < M_PLAT_FREQ_MIN || freq_max > M_PLAT_FREQ_MAX ||
            freq_min > freq_max) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): invalid frequency bounds.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);

        }
        bool result = false;
        if (m_freq_min != freq_min ||
            m_freq_max != freq_max) {
            m_freq_min = freq_min;
            m_freq_max = freq_max;
            result = true;
        }
        return result;
    }

    double FrequencyGovernorImp::get_frequency_min()  const
    {
        return m_freq_min;
    }

    double FrequencyGovernorImp::get_frequency_max()  const
    {
        return m_freq_max;
    }

    double FrequencyGovernorImp::get_frequency_step()  const
    {
        return M_FREQ_STEP;
    }

    void FrequencyGovernorImp::validate_policy(double &freq_min, double &freq_max) const
    {
        double target_freq_min = std::isnan(freq_min) ? get_limit("CPUINFO::FREQ_MIN") : freq_min;
        double target_freq_max = std::isnan(freq_max) ? get_limit("CPUINFO::FREQ_STICKER") : freq_max;
        freq_min = target_freq_min;
        freq_max = target_freq_max;
    }
}
<|endoftext|>


<commit_before>
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <sstream>

int main()
{
  std::string sentence;
  getline(std::cin, sentence); //"sentence" will be user input command
  std::stringstream command(sentence); //"command" is the broken down version of "sentence"
  std::istream_iterator<std::string> begin(command); //set begining of iterator for words in "command"
  std::istream_iterator<std::string> end; //set end of iterator for words in "command"
  std::vector<std::string> parseCommand(begin, end); //sets parsed words from "command" into vector labled "parseCommand"
  std::copy(parseCommand.begin(), parseCommand.end(), std::ostream_iterator<std::string>(std::cout, "\n")); //test line to op "parseCommand"

  return 0;
}
<commit_msg>Update tokenizer.hpp<commit_after>#ifndef TOKENIZER_HPP
#define TOKENIZER_HPP

#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <sstream>

std::string sentence;
getline(std::cin, sentence); //"sentence" will be user input command
std::stringstream command(sentence); //"command" is the broken down version of "sentence"
std::istream_iterator<std::string> begin(command); //set begining of iterator for words in "command"
std::istream_iterator<std::string> end; //set end of iterator for words in "command"
std::vector<std::string> parseCommand(begin, end); //sets parsed words from "command" into vector labled "parseCommand"

/*
* test line to o/p "parseCommand"
* std::copy(parseCommand.begin(), parseCommand.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
*/

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 * spatializer.cpp: sound reverberation
 *****************************************************************************
 * Copyright (C) 2004, 2006, 2007 the VideoLAN team
 *
 * Google Summer of Code 2007
 *
 * Authors: Biodun Osunkunle <biodun@videolan.org>
 *
 * Mentor : Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <math.h>

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>
#include <vlc_plugin.h>
#include "vlc_aout.h"
#include "revmodel.hpp"
#define SPAT_AMP 0.3
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );

#define ROOMSIZE_TEXT N_("Room size")
#define ROOMSIZE_LONGTEXT N_("Defines the virtual surface of the room" \
                                "emulated by the filter." )

#define WIDTH_TEXT N_("Room width")
#define WIDTH_LONGTEXT N_("Width of the virtual room")

#define WET_TEXT N_("")
#define WET_LONGTEXT N_("")

#define DRY_TEXT N_("")
#define DRY_LONGTEXT N_("")

#define DAMP_TEXT N_("")
#define DAMP_LONGTEXT N_("")

vlc_module_begin();
    set_description( N_("spatializer") );
    set_shortname( N_("spatializer" ) );
    set_capability( "audio filter", 0 );
    set_category( CAT_AUDIO );
    set_subcategory( SUBCAT_AUDIO_AFILTER );

    set_callbacks( Open, Close );
    add_shortcut( "spatializer" );
    add_float( "Roomsize", 1.05, NULL, ROOMSIZE_TEXT,ROOMSIZE_LONGTEXT, true);
    add_float( "Width", 10.0, NULL, WIDTH_TEXT,WIDTH_LONGTEXT, true);
    add_float( "Wet", 3.0, NULL, WET_TEXT,WET_LONGTEXT, true);
    add_float( "Dry", 2.0, NULL, DRY_TEXT,DRY_LONGTEXT, true);
    add_float( "Damp", 1.0, NULL, DAMP_TEXT,DAMP_LONGTEXT, true);
vlc_module_end();

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
typedef struct aout_filter_sys_t
{
    vlc_mutex_t lock;
    revmodel *p_reverbm;

} aout_filter_sys_t;

class CLocker
{
public:
    CLocker( vlc_mutex_t *p_lock ) : p_lock(p_lock) {
        vlc_mutex_lock( p_lock );
    }
    virtual ~CLocker() {
        vlc_mutex_unlock( p_lock );
    }
private:
    vlc_mutex_t *p_lock;
};

static const char *psz_control_names[] =
{
    "Roomsize", "Width" , "Wet", "Dry", "Damp"
};
static void DoWork( aout_instance_t *, aout_filter_t *,
                    aout_buffer_t *, aout_buffer_t * );

static int  SpatInit( aout_filter_t *);
static void SpatFilter( aout_instance_t *,aout_filter_t *, float *, float *,
                        int, int );
static void SpatClean( aout_filter_t * );
static int RoomCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int WetCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int DryCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int DampCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int WidthCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );

/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    aout_filter_t     *p_filter = (aout_filter_t *)p_this;
    aout_filter_sys_t *p_sys;
    bool         b_fit = true;
    msg_Dbg(p_this, "Opening filter spatializer %s %s %d\n", __FILE__,__func__,__LINE__);

    if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) ||
        p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
    {
        b_fit = false;
        p_filter->input.i_format = VLC_FOURCC('f','l','3','2');
        p_filter->output.i_format = VLC_FOURCC('f','l','3','2');
        msg_Warn( p_filter, "bad input or output format" );
    }
    if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
    {
        b_fit = false;
        memcpy( &p_filter->output, &p_filter->input,
                sizeof(audio_sample_format_t) );
        msg_Warn( p_filter, "input and output formats are not similar" );
    }

    if ( ! b_fit )
    {
        return VLC_EGENERIC;
    }

    p_filter->pf_do_work = DoWork;
    p_filter->b_in_place = true;

     /* Allocate structure */
    p_sys = p_filter->p_sys = (aout_filter_sys_t*)malloc( sizeof( aout_filter_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;

    vlc_mutex_init( &p_sys->lock );
    p_sys->p_reverbm = new revmodel();
    p_sys->p_reverbm->setroomsize(1.05);
    p_sys->p_reverbm->setwet(10.0f);
    p_sys->p_reverbm->setdry(1.0f);
    p_sys->p_reverbm->setdamp(0.3);
    p_sys->p_reverbm->setwidth(0.9);
    SpatInit( p_filter);

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Close: close the plugin
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
    aout_filter_t     *p_filter = (aout_filter_t *)p_this;
    aout_filter_sys_t *p_sys = p_filter->p_sys;
    SpatClean( p_filter );
    delete p_sys->p_reverbm;
    vlc_mutex_destroy( &p_sys->lock );
    free( p_sys );
    msg_Dbg(p_this, "Closing filter spatializer %s %s %d\n", __FILE__,__func__,__LINE__);
}

/*****************************************************************************
 * DoWork: process samples buffer
 *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;

    SpatFilter( p_aout, p_filter, (float*)p_out_buf->p_buffer,
               (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples,
               aout_FormatNbChannels( &p_filter->input ) );
}

static int SpatInit( aout_filter_t *p_filter )
{
    aout_filter_sys_t *p_sys = p_filter->p_sys;
    int i, ch;
    vlc_value_t val1, val2, val3, val4, val5;
    aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;

    for( i = 0; i < 5 ; i ++ )
    {
        var_CreateGetFloatCommand( p_aout, psz_control_names[i] );
    }

    /* Get initial values */
    var_Get( p_aout, psz_control_names[0], &val1 );
    var_Get( p_aout, psz_control_names[1], &val2 );
    var_Get( p_aout, psz_control_names[2], &val3 );
    var_Get( p_aout, psz_control_names[3], &val4 );
    var_Get( p_aout, psz_control_names[4], &val5);

    RoomCallback( VLC_OBJECT( p_aout ), NULL, val1, val1, p_sys );
    WidthCallback( VLC_OBJECT( p_aout ), NULL, val2, val2, p_sys );
    WetCallback( VLC_OBJECT( p_aout ), NULL, val3, val3, p_sys );
    DryCallback( VLC_OBJECT( p_aout ), NULL, val4, val4, p_sys );
    DampCallback( VLC_OBJECT( p_aout ), NULL, val5, val5, p_sys );

    msg_Dbg( p_filter, "%f", val1.f_float );
    /* Add our own callbacks */
    var_AddCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[4], DampCallback, p_sys );

    return VLC_SUCCESS;
}

static void SpatFilter( aout_instance_t *p_aout,
                       aout_filter_t *p_filter, float *out, float *in,
                       int i_samples, int i_channels )
{
    aout_filter_sys_t *p_sys = p_filter->p_sys;
    CLocker locker( &p_sys->lock );

    int i, ch, j;
    for( i = 0; i < i_samples; i++ )
    {
        for( ch = 0 ; ch < 2; ch++)
        {
            in[ch] = in[ch] * SPAT_AMP;
        }
        p_sys->p_reverbm->processreplace( in, out , 1, i_channels);
        in  += i_channels;
        out += i_channels;
    }
}

static void SpatClean( aout_filter_t *p_filter )
{
    aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;
    aout_filter_sys_t *p_sys = p_filter->p_sys;

    var_DelCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[4], DampCallback, p_sys );
}

/*****************************************************************************
 * Variables callbacks
 *****************************************************************************/

static int RoomCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setroomsize(newval.f_float);
    msg_Dbg (p_this,"room callback %3.1f %s %s %d\n", newval.f_float, __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}

static int WidthCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setwidth(newval.f_float);
    msg_Dbg (p_this,"width callback %3.1f %s %s %d\n", newval.f_float,  __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}
static int WetCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setwet(newval.f_float);
    msg_Dbg (p_this,"wet callback %3.1f %s %s %d\n", newval.f_float,  __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}
static int DryCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setdry(newval.f_float);
    msg_Dbg (p_this,"dry callback %3.1f %s %s %d\n", newval.f_float, __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}
static int DampCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setdamp(newval.f_float);
    msg_Dbg (p_this, "damp callback %3.1f %s %s %d\n", newval.f_float, __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}

<commit_msg>spatializer: don't translate empty strings. Someone please add descriptions though.<commit_after>/*****************************************************************************
 * spatializer.cpp: sound reverberation
 *****************************************************************************
 * Copyright (C) 2004, 2006, 2007 the VideoLAN team
 *
 * Google Summer of Code 2007
 *
 * Authors: Biodun Osunkunle <biodun@videolan.org>
 *
 * Mentor : Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <math.h>

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>
#include <vlc_plugin.h>
#include "vlc_aout.h"
#include "revmodel.hpp"
#define SPAT_AMP 0.3
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );

#define ROOMSIZE_TEXT N_("Room size")
#define ROOMSIZE_LONGTEXT N_("Defines the virtual surface of the room" \
                                "emulated by the filter." )

#define WIDTH_TEXT N_("Room width")
#define WIDTH_LONGTEXT N_("Width of the virtual room")

#define WET_TEXT ""
#define WET_LONGTEXT ""

#define DRY_TEXT ""
#define DRY_LONGTEXT ""

#define DAMP_TEXT ""
#define DAMP_LONGTEXT ""

vlc_module_begin();
    set_description( N_("spatializer") );
    set_shortname( N_("spatializer" ) );
    set_capability( "audio filter", 0 );
    set_category( CAT_AUDIO );
    set_subcategory( SUBCAT_AUDIO_AFILTER );

    set_callbacks( Open, Close );
    add_shortcut( "spatializer" );
    add_float( "Roomsize", 1.05, NULL, ROOMSIZE_TEXT,ROOMSIZE_LONGTEXT, true);
    add_float( "Width", 10.0, NULL, WIDTH_TEXT,WIDTH_LONGTEXT, true);
    add_float( "Wet", 3.0, NULL, WET_TEXT,WET_LONGTEXT, true);
    add_float( "Dry", 2.0, NULL, DRY_TEXT,DRY_LONGTEXT, true);
    add_float( "Damp", 1.0, NULL, DAMP_TEXT,DAMP_LONGTEXT, true);
vlc_module_end();

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
typedef struct aout_filter_sys_t
{
    vlc_mutex_t lock;
    revmodel *p_reverbm;

} aout_filter_sys_t;

class CLocker
{
public:
    CLocker( vlc_mutex_t *p_lock ) : p_lock(p_lock) {
        vlc_mutex_lock( p_lock );
    }
    virtual ~CLocker() {
        vlc_mutex_unlock( p_lock );
    }
private:
    vlc_mutex_t *p_lock;
};

static const char *psz_control_names[] =
{
    "Roomsize", "Width" , "Wet", "Dry", "Damp"
};
static void DoWork( aout_instance_t *, aout_filter_t *,
                    aout_buffer_t *, aout_buffer_t * );

static int  SpatInit( aout_filter_t *);
static void SpatFilter( aout_instance_t *,aout_filter_t *, float *, float *,
                        int, int );
static void SpatClean( aout_filter_t * );
static int RoomCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int WetCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int DryCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int DampCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );
static int WidthCallback ( vlc_object_t *, char const *,
                                           vlc_value_t, vlc_value_t, void * );

/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    aout_filter_t     *p_filter = (aout_filter_t *)p_this;
    aout_filter_sys_t *p_sys;
    bool         b_fit = true;
    msg_Dbg(p_this, "Opening filter spatializer %s %s %d\n", __FILE__,__func__,__LINE__);

    if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) ||
        p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
    {
        b_fit = false;
        p_filter->input.i_format = VLC_FOURCC('f','l','3','2');
        p_filter->output.i_format = VLC_FOURCC('f','l','3','2');
        msg_Warn( p_filter, "bad input or output format" );
    }
    if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
    {
        b_fit = false;
        memcpy( &p_filter->output, &p_filter->input,
                sizeof(audio_sample_format_t) );
        msg_Warn( p_filter, "input and output formats are not similar" );
    }

    if ( ! b_fit )
    {
        return VLC_EGENERIC;
    }

    p_filter->pf_do_work = DoWork;
    p_filter->b_in_place = true;

     /* Allocate structure */
    p_sys = p_filter->p_sys = (aout_filter_sys_t*)malloc( sizeof( aout_filter_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;

    vlc_mutex_init( &p_sys->lock );
    p_sys->p_reverbm = new revmodel();
    p_sys->p_reverbm->setroomsize(1.05);
    p_sys->p_reverbm->setwet(10.0f);
    p_sys->p_reverbm->setdry(1.0f);
    p_sys->p_reverbm->setdamp(0.3);
    p_sys->p_reverbm->setwidth(0.9);
    SpatInit( p_filter);

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Close: close the plugin
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
    aout_filter_t     *p_filter = (aout_filter_t *)p_this;
    aout_filter_sys_t *p_sys = p_filter->p_sys;
    SpatClean( p_filter );
    delete p_sys->p_reverbm;
    vlc_mutex_destroy( &p_sys->lock );
    free( p_sys );
    msg_Dbg(p_this, "Closing filter spatializer %s %s %d\n", __FILE__,__func__,__LINE__);
}

/*****************************************************************************
 * DoWork: process samples buffer
 *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;

    SpatFilter( p_aout, p_filter, (float*)p_out_buf->p_buffer,
               (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples,
               aout_FormatNbChannels( &p_filter->input ) );
}

static int SpatInit( aout_filter_t *p_filter )
{
    aout_filter_sys_t *p_sys = p_filter->p_sys;
    int i, ch;
    vlc_value_t val1, val2, val3, val4, val5;
    aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;

    for( i = 0; i < 5 ; i ++ )
    {
        var_CreateGetFloatCommand( p_aout, psz_control_names[i] );
    }

    /* Get initial values */
    var_Get( p_aout, psz_control_names[0], &val1 );
    var_Get( p_aout, psz_control_names[1], &val2 );
    var_Get( p_aout, psz_control_names[2], &val3 );
    var_Get( p_aout, psz_control_names[3], &val4 );
    var_Get( p_aout, psz_control_names[4], &val5);

    RoomCallback( VLC_OBJECT( p_aout ), NULL, val1, val1, p_sys );
    WidthCallback( VLC_OBJECT( p_aout ), NULL, val2, val2, p_sys );
    WetCallback( VLC_OBJECT( p_aout ), NULL, val3, val3, p_sys );
    DryCallback( VLC_OBJECT( p_aout ), NULL, val4, val4, p_sys );
    DampCallback( VLC_OBJECT( p_aout ), NULL, val5, val5, p_sys );

    msg_Dbg( p_filter, "%f", val1.f_float );
    /* Add our own callbacks */
    var_AddCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
    var_AddCallback( p_aout, psz_control_names[4], DampCallback, p_sys );

    return VLC_SUCCESS;
}

static void SpatFilter( aout_instance_t *p_aout,
                       aout_filter_t *p_filter, float *out, float *in,
                       int i_samples, int i_channels )
{
    aout_filter_sys_t *p_sys = p_filter->p_sys;
    CLocker locker( &p_sys->lock );

    int i, ch, j;
    for( i = 0; i < i_samples; i++ )
    {
        for( ch = 0 ; ch < 2; ch++)
        {
            in[ch] = in[ch] * SPAT_AMP;
        }
        p_sys->p_reverbm->processreplace( in, out , 1, i_channels);
        in  += i_channels;
        out += i_channels;
    }
}

static void SpatClean( aout_filter_t *p_filter )
{
    aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;
    aout_filter_sys_t *p_sys = p_filter->p_sys;

    var_DelCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
    var_DelCallback( p_aout, psz_control_names[4], DampCallback, p_sys );
}

/*****************************************************************************
 * Variables callbacks
 *****************************************************************************/

static int RoomCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setroomsize(newval.f_float);
    msg_Dbg (p_this,"room callback %3.1f %s %s %d\n", newval.f_float, __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}

static int WidthCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setwidth(newval.f_float);
    msg_Dbg (p_this,"width callback %3.1f %s %s %d\n", newval.f_float,  __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}
static int WetCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setwet(newval.f_float);
    msg_Dbg (p_this,"wet callback %3.1f %s %s %d\n", newval.f_float,  __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}
static int DryCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setdry(newval.f_float);
    msg_Dbg (p_this,"dry callback %3.1f %s %s %d\n", newval.f_float, __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}
static int DampCallback( vlc_object_t *p_this, char const *psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
    CLocker locker( &p_sys->lock );

    p_sys->p_reverbm->setdamp(newval.f_float);
    msg_Dbg (p_this, "damp callback %3.1f %s %s %d\n", newval.f_float, __FILE__,__func__,__LINE__);
    return VLC_SUCCESS;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) [2016-2017] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "config.h"
#include "storage/Utils/AppUtil.h"
#include "storage/Utils/Mockup.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/StorageImpl.h"
#include "storage/DevicegraphImpl.h"
#include "storage/Devices/DiskImpl.h"
#include "storage/Devices/MdImpl.h"
#include "storage/Devices/LvmPvImpl.h"
#include "storage/Devices/LvmVgImpl.h"
#include "storage/Devices/LvmLvImpl.h"
#include "storage/Devices/LuksImpl.h"
#include "storage/Devices/BcacheImpl.h"
#include "storage/Devices/BcacheCsetImpl.h"
#include "storage/Filesystems/BlkFilesystemImpl.h"
#include "storage/Filesystems/NfsImpl.h"
#include "storage/SystemInfo/SystemInfo.h"
#include "storage/Actiongraph.h"
#include "storage/EtcFstab.h"

namespace storage
{

    Storage::Impl::Impl(const Storage& storage, const Environment& environment)
	: storage(storage), environment(environment), arch(false), tmp_dir("libstorage-XXXXXX")
    {
	y2mil("constructed Storage with " << environment);
	y2mil("libstorage-ng version " VERSION);
    }

    void
    Storage::Impl::initialize_standard_devicegraphs()
    {
	// This function is not called from the constructor Storage::Impl::Impl() since
	// code below uses get_storage()->get_impl().xyz(). But Storage::impl, which is
	// used in Storage::get_impl(), is only initialized in Storage::Storage() after
	// Storage::Impl::Impl() has finished.

	Devicegraph* probed = create_devicegraph("probed");

	switch (environment.get_probe_mode())
	{
	    case ProbeMode::STANDARD: {
	    LvmVg::Impl::activate();
		probe(probed);
	    } break;

	    case ProbeMode::STANDARD_WRITE_DEVICEGRAPH: {
	    LvmVg::Impl::activate();
		probe(probed);
		probed->save(environment.get_devicegraph_filename());
	    } break;

	    case ProbeMode::STANDARD_WRITE_MOCKUP: {
	    LvmVg::Impl::activate();
		Mockup::set_mode(Mockup::Mode::RECORD);
		probe(probed);
		Mockup::save(environment.get_mockup_filename());
	    } break;

	    case ProbeMode::NONE: {
	    } break;

	    case ProbeMode::READ_DEVICEGRAPH: {
		probed->load(environment.get_devicegraph_filename());
	    } break;

	    case ProbeMode::READ_MOCKUP: {
		Mockup::set_mode(Mockup::Mode::PLAYBACK);
		Mockup::load(environment.get_mockup_filename());
		probe(probed);
	    } break;
	}

	y2mil("probed devicegraph begin");
	y2mil(*probed);
	y2mil("probed devicegraph end");

	copy_devicegraph("probed", "staging");
    }

    Storage::Impl::~Impl()
    {
	// TODO: Make sure logger is destroyed after this object
    }

    void
    Storage::Impl::probe(Devicegraph* probed)
    {
	SystemInfo systeminfo;

	arch = systeminfo.getArch();

	EtcFstab fstab;

        if ( environment.get_probe_mode() ==  ProbeMode::READ_MOCKUP )
            fstab.parse( Mockup::get_file( ETC_FSTAB ).content );
        else
            fstab.read( ETC_FSTAB );

	// TODO

	// Pass 1: Detect all Devices except Filesystems and some Holders,
	// e.g. between Partitionable, PartitionTable and Partitions.

	Disk::Impl::probe_disks(probed, systeminfo);

	if (systeminfo.getBlkid().any_md())
	{
	    // TODO check whether md tools are installed

	    Md::Impl::probe_mds(probed, systeminfo);
	}

	if (systeminfo.getBlkid().any_lvm())
	{
	    // TODO check whether lvm tools are installed

	    LvmVg::Impl::probe_lvm_vgs(probed, systeminfo);
	    LvmPv::Impl::probe_lvm_pvs(probed, systeminfo);
	    LvmLv::Impl::probe_lvm_lvs(probed, systeminfo);
	}

	if (systeminfo.getBlkid().any_luks())
	{
	    // TODO check whether cryptsetup tools are installed

	    Luks::Impl::probe_lukses(probed, systeminfo);
	}

	if (systeminfo.getBlkid().any_bcache())
	{
	    // TODO check whether bcache-tools are installed

	    Bcache::Impl::probe_bcaches(probed, systeminfo);
	    BcacheCset::Impl::probe_bcache_csets(probed, systeminfo);
	}

	// Pass 2: Detect remaining Holders, e.g. MdUsers. This is not
	// possible in pass 1 since a Md can use other Mds (e.g. md0 using md1
	// and md2).

	for (Devicegraph::Impl::vertex_descriptor vertex : probed->get_impl().vertices())
	{
	    Device* device = probed->get_impl()[vertex];
	    device->get_impl().probe_pass_2(probed, systeminfo);
	}

	// Pass 3: Detect filesystems.

	for (BlkDevice* blk_device : BlkDevice::get_all(probed))
	{
	    if (blk_device->num_children() != 0)
		continue;

	    Blkid::Entry entry;
	    if (systeminfo.getBlkid().find_by_name(blk_device->get_name(), entry, systeminfo))
	    {
		if (entry.is_fs)
		{
		    if (entry.fs_type != FsType::EXT2 && entry.fs_type != FsType::EXT3 &&
			entry.fs_type != FsType::EXT4 && entry.fs_type != FsType::BTRFS &&
			entry.fs_type != FsType::REISERFS && entry.fs_type != FsType::XFS &&
			entry.fs_type != FsType::SWAP && entry.fs_type != FsType::NTFS &&
			entry.fs_type != FsType::VFAT && entry.fs_type != FsType::ISO9660 &&
			entry.fs_type != FsType::UDF)
		    {
			y2war("detected unsupported filesystem " << toString(entry.fs_type) << " on " <<
			      blk_device->get_name());
			continue;
		    }

		    BlkFilesystem* blk_filesystem = blk_device->create_blk_filesystem(entry.fs_type);
		    blk_filesystem->get_impl().probe_pass_3(probed, systeminfo, fstab);
		}
	    }
	}

	Nfs::Impl::probe_nfses(probed, systeminfo);
    }

    Devicegraph*
    Storage::Impl::get_devicegraph(const string& name)
    {
	if (name == "probed")
	    ST_THROW(Exception("invalid name"));

	map<string, Devicegraph>::iterator it = devicegraphs.find(name);
	if (it == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	return &it->second;
    }

    const Devicegraph*
    Storage::Impl::get_devicegraph(const string& name) const
    {
	map<string, Devicegraph>::const_iterator it = devicegraphs.find(name);
	if (it == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	return &it->second;
    }

    Devicegraph*
    Storage::Impl::get_staging()
    {
	return get_devicegraph("staging");
    }

    const Devicegraph*
    Storage::Impl::get_staging() const
    {
	return get_devicegraph("staging");
    }

    const Devicegraph*
    Storage::Impl::get_probed() const
    {
	return get_devicegraph("probed");
    }

    vector<string>
    Storage::Impl::get_devicegraph_names() const
    {
	vector<string> ret;

	for (const map<string, Devicegraph>::value_type& it : devicegraphs)
	    ret.push_back(it.first);

	return ret;
    }

    Devicegraph*
    Storage::Impl::create_devicegraph(const string& name)
    {
	pair<map<string, Devicegraph>::iterator, bool> tmp =
	    devicegraphs.emplace(piecewise_construct, forward_as_tuple(name),
				 forward_as_tuple(&storage));
	if (!tmp.second)
	    ST_THROW(Exception("device graph already exists"));

	map<string, Devicegraph>::iterator it = tmp.first;

	return &it->second;
    }

    Devicegraph*
    Storage::Impl::copy_devicegraph(const string& source_name, const string& dest_name)
    {
	const Devicegraph* tmp1 = static_cast<const Impl*>(this)->get_devicegraph(source_name);

	Devicegraph* tmp2 = create_devicegraph(dest_name);

	tmp1->copy(*tmp2);

	return tmp2;
    }

    void
    Storage::Impl::remove_devicegraph(const string& name)
    {
	map<string, Devicegraph>::const_iterator it1 = devicegraphs.find(name);
	if (it1 == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	devicegraphs.erase(it1);
    }

    void
    Storage::Impl::restore_devicegraph(const string& name)
    {
	map<string, Devicegraph>::iterator it1 = devicegraphs.find(name);
	if (it1 == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	map<string, Devicegraph>::iterator it2 = devicegraphs.find("staging");
	if (it2 == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	it1->second.get_impl().swap(it2->second.get_impl());
	devicegraphs.erase(it1);
    }

    bool
    Storage::Impl::exist_devicegraph(const string& name) const
    {
	return devicegraphs.find(name) != devicegraphs.end();
    }

    bool
    Storage::Impl::equal_devicegraph(const string& lhs, const string& rhs) const
    {
	return *get_devicegraph(lhs) == *get_devicegraph(rhs);
    }

    void
    Storage::Impl::check() const
    {
	for (const map<string, Devicegraph>::value_type& key_value : devicegraphs)
	{
	    key_value.second.check();
	}

	// TODO check that a object has the same type in every devicegraph
    }

    string
    Storage::Impl::prepend_rootprefix(const string& mountpoint) const
    {
	if (mountpoint == "swap" || rootprefix.empty())
	    return mountpoint;

	if (mountpoint == "/")
	    return rootprefix;
	else
	    return rootprefix + mountpoint;
    }

    const Actiongraph*
    Storage::Impl::calculate_actiongraph()
    {
	actiongraph.reset(new Actiongraph(storage, get_probed(), get_staging()));

	return actiongraph.get();
    }

    void
    Storage::Impl::commit(const CommitCallbacks* commit_callbacks)
    {
	ST_CHECK_PTR(actiongraph.get());

	actiongraph->get_impl().commit(commit_callbacks);

	// TODO somehow update probed
    }

}
<commit_msg>Add comment<commit_after>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) [2016-2017] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "config.h"
#include "storage/Utils/AppUtil.h"
#include "storage/Utils/Mockup.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/StorageImpl.h"
#include "storage/DevicegraphImpl.h"
#include "storage/Devices/DiskImpl.h"
#include "storage/Devices/MdImpl.h"
#include "storage/Devices/LvmPvImpl.h"
#include "storage/Devices/LvmVgImpl.h"
#include "storage/Devices/LvmLvImpl.h"
#include "storage/Devices/LuksImpl.h"
#include "storage/Devices/BcacheImpl.h"
#include "storage/Devices/BcacheCsetImpl.h"
#include "storage/Filesystems/BlkFilesystemImpl.h"
#include "storage/Filesystems/NfsImpl.h"
#include "storage/SystemInfo/SystemInfo.h"
#include "storage/Actiongraph.h"
#include "storage/EtcFstab.h"

namespace storage
{

    Storage::Impl::Impl(const Storage& storage, const Environment& environment)
	: storage(storage), environment(environment), arch(false), tmp_dir("libstorage-XXXXXX")
    {
	y2mil("constructed Storage with " << environment);
	y2mil("libstorage-ng version " VERSION);
    }

    void
    Storage::Impl::initialize_standard_devicegraphs()
    {
	// This function is not called from the constructor Storage::Impl::Impl() since
	// code below uses get_storage()->get_impl().xyz(). But Storage::impl, which is
	// used in Storage::get_impl(), is only initialized in Storage::Storage() after
	// Storage::Impl::Impl() has finished.

	Devicegraph* probed = create_devicegraph("probed");

    // FIXME
    // This approach for vgs activation does not work in combination with activating
    // LUKS. Managing lvm with LUKS, raid, etc is pending to implement.
	switch (environment.get_probe_mode())
	{
	    case ProbeMode::STANDARD: {
	    LvmVg::Impl::activate();
		probe(probed);
	    } break;

	    case ProbeMode::STANDARD_WRITE_DEVICEGRAPH: {
	    LvmVg::Impl::activate();
		probe(probed);
		probed->save(environment.get_devicegraph_filename());
	    } break;

	    case ProbeMode::STANDARD_WRITE_MOCKUP: {
	    LvmVg::Impl::activate();
		Mockup::set_mode(Mockup::Mode::RECORD);
		probe(probed);
		Mockup::save(environment.get_mockup_filename());
	    } break;

	    case ProbeMode::NONE: {
	    } break;

	    case ProbeMode::READ_DEVICEGRAPH: {
		probed->load(environment.get_devicegraph_filename());
	    } break;

	    case ProbeMode::READ_MOCKUP: {
		Mockup::set_mode(Mockup::Mode::PLAYBACK);
		Mockup::load(environment.get_mockup_filename());
		probe(probed);
	    } break;
	}

	y2mil("probed devicegraph begin");
	y2mil(*probed);
	y2mil("probed devicegraph end");

	copy_devicegraph("probed", "staging");
    }

    Storage::Impl::~Impl()
    {
	// TODO: Make sure logger is destroyed after this object
    }

    void
    Storage::Impl::probe(Devicegraph* probed)
    {
	SystemInfo systeminfo;

	arch = systeminfo.getArch();

	EtcFstab fstab;

        if ( environment.get_probe_mode() ==  ProbeMode::READ_MOCKUP )
            fstab.parse( Mockup::get_file( ETC_FSTAB ).content );
        else
            fstab.read( ETC_FSTAB );

	// TODO

	// Pass 1: Detect all Devices except Filesystems and some Holders,
	// e.g. between Partitionable, PartitionTable and Partitions.

	Disk::Impl::probe_disks(probed, systeminfo);

	if (systeminfo.getBlkid().any_md())
	{
	    // TODO check whether md tools are installed

	    Md::Impl::probe_mds(probed, systeminfo);
	}

	if (systeminfo.getBlkid().any_lvm())
	{
	    // TODO check whether lvm tools are installed

	    LvmVg::Impl::probe_lvm_vgs(probed, systeminfo);
	    LvmPv::Impl::probe_lvm_pvs(probed, systeminfo);
	    LvmLv::Impl::probe_lvm_lvs(probed, systeminfo);
	}

	if (systeminfo.getBlkid().any_luks())
	{
	    // TODO check whether cryptsetup tools are installed

	    Luks::Impl::probe_lukses(probed, systeminfo);
	}

	if (systeminfo.getBlkid().any_bcache())
	{
	    // TODO check whether bcache-tools are installed

	    Bcache::Impl::probe_bcaches(probed, systeminfo);
	    BcacheCset::Impl::probe_bcache_csets(probed, systeminfo);
	}

	// Pass 2: Detect remaining Holders, e.g. MdUsers. This is not
	// possible in pass 1 since a Md can use other Mds (e.g. md0 using md1
	// and md2).

	for (Devicegraph::Impl::vertex_descriptor vertex : probed->get_impl().vertices())
	{
	    Device* device = probed->get_impl()[vertex];
	    device->get_impl().probe_pass_2(probed, systeminfo);
	}

	// Pass 3: Detect filesystems.

	for (BlkDevice* blk_device : BlkDevice::get_all(probed))
	{
	    if (blk_device->num_children() != 0)
		continue;

	    Blkid::Entry entry;
	    if (systeminfo.getBlkid().find_by_name(blk_device->get_name(), entry, systeminfo))
	    {
		if (entry.is_fs)
		{
		    if (entry.fs_type != FsType::EXT2 && entry.fs_type != FsType::EXT3 &&
			entry.fs_type != FsType::EXT4 && entry.fs_type != FsType::BTRFS &&
			entry.fs_type != FsType::REISERFS && entry.fs_type != FsType::XFS &&
			entry.fs_type != FsType::SWAP && entry.fs_type != FsType::NTFS &&
			entry.fs_type != FsType::VFAT && entry.fs_type != FsType::ISO9660 &&
			entry.fs_type != FsType::UDF)
		    {
			y2war("detected unsupported filesystem " << toString(entry.fs_type) << " on " <<
			      blk_device->get_name());
			continue;
		    }

		    BlkFilesystem* blk_filesystem = blk_device->create_blk_filesystem(entry.fs_type);
		    blk_filesystem->get_impl().probe_pass_3(probed, systeminfo, fstab);
		}
	    }
	}

	Nfs::Impl::probe_nfses(probed, systeminfo);
    }

    Devicegraph*
    Storage::Impl::get_devicegraph(const string& name)
    {
	if (name == "probed")
	    ST_THROW(Exception("invalid name"));

	map<string, Devicegraph>::iterator it = devicegraphs.find(name);
	if (it == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	return &it->second;
    }

    const Devicegraph*
    Storage::Impl::get_devicegraph(const string& name) const
    {
	map<string, Devicegraph>::const_iterator it = devicegraphs.find(name);
	if (it == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	return &it->second;
    }

    Devicegraph*
    Storage::Impl::get_staging()
    {
	return get_devicegraph("staging");
    }

    const Devicegraph*
    Storage::Impl::get_staging() const
    {
	return get_devicegraph("staging");
    }

    const Devicegraph*
    Storage::Impl::get_probed() const
    {
	return get_devicegraph("probed");
    }

    vector<string>
    Storage::Impl::get_devicegraph_names() const
    {
	vector<string> ret;

	for (const map<string, Devicegraph>::value_type& it : devicegraphs)
	    ret.push_back(it.first);

	return ret;
    }

    Devicegraph*
    Storage::Impl::create_devicegraph(const string& name)
    {
	pair<map<string, Devicegraph>::iterator, bool> tmp =
	    devicegraphs.emplace(piecewise_construct, forward_as_tuple(name),
				 forward_as_tuple(&storage));
	if (!tmp.second)
	    ST_THROW(Exception("device graph already exists"));

	map<string, Devicegraph>::iterator it = tmp.first;

	return &it->second;
    }

    Devicegraph*
    Storage::Impl::copy_devicegraph(const string& source_name, const string& dest_name)
    {
	const Devicegraph* tmp1 = static_cast<const Impl*>(this)->get_devicegraph(source_name);

	Devicegraph* tmp2 = create_devicegraph(dest_name);

	tmp1->copy(*tmp2);

	return tmp2;
    }

    void
    Storage::Impl::remove_devicegraph(const string& name)
    {
	map<string, Devicegraph>::const_iterator it1 = devicegraphs.find(name);
	if (it1 == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	devicegraphs.erase(it1);
    }

    void
    Storage::Impl::restore_devicegraph(const string& name)
    {
	map<string, Devicegraph>::iterator it1 = devicegraphs.find(name);
	if (it1 == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	map<string, Devicegraph>::iterator it2 = devicegraphs.find("staging");
	if (it2 == devicegraphs.end())
	    ST_THROW(Exception("device graph not found"));

	it1->second.get_impl().swap(it2->second.get_impl());
	devicegraphs.erase(it1);
    }

    bool
    Storage::Impl::exist_devicegraph(const string& name) const
    {
	return devicegraphs.find(name) != devicegraphs.end();
    }

    bool
    Storage::Impl::equal_devicegraph(const string& lhs, const string& rhs) const
    {
	return *get_devicegraph(lhs) == *get_devicegraph(rhs);
    }

    void
    Storage::Impl::check() const
    {
	for (const map<string, Devicegraph>::value_type& key_value : devicegraphs)
	{
	    key_value.second.check();
	}

	// TODO check that a object has the same type in every devicegraph
    }

    string
    Storage::Impl::prepend_rootprefix(const string& mountpoint) const
    {
	if (mountpoint == "swap" || rootprefix.empty())
	    return mountpoint;

	if (mountpoint == "/")
	    return rootprefix;
	else
	    return rootprefix + mountpoint;
    }

    const Actiongraph*
    Storage::Impl::calculate_actiongraph()
    {
	actiongraph.reset(new Actiongraph(storage, get_probed(), get_staging()));

	return actiongraph.get();
    }

    void
    Storage::Impl::commit(const CommitCallbacks* commit_callbacks)
    {
	ST_CHECK_PTR(actiongraph.get());

	actiongraph->get_impl().commit(commit_callbacks);

	// TODO somehow update probed
    }

}
<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2021                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include <modules/autonavigation/autonavigationhandler.h>

#include <modules/autonavigation/helperfunctions.h>
#include <modules/autonavigation/pathinstruction.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <openspace/util/timemanager.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/quaternion.hpp>
#include <vector>

namespace {
    constexpr const char* _loggerCat = "AutoNavigationHandler";

    constexpr openspace::properties::Property::PropertyInfo DefaultCurveOptionInfo = {
        "DefaultCurveOption",
        "Default Curve Option",
        "The defualt curve type chosen when generating a path, if none is specified"
        // TODO: right now there is no way to specify a type for a single path
    };

    constexpr openspace::properties::Property::PropertyInfo IncludeRollInfo = {
        "IncludeRoll",
        "Include Roll",
        "If disabled, roll is removed from the interpolation of camera orientation"
    };

    constexpr openspace::properties::Property::PropertyInfo StopBehaviorInfo = {
        "StopBehavior",
        "Stop Behavior",
        "A camera motion behavior that is applied when no path is being played"
    };

    constexpr openspace::properties::Property::PropertyInfo
        ApplyStopBehaviorWhenIdleInfo =
    {
        "ApplyStopBehaviorWhenIdle",
        "Apply Stop Behavior When Idle",
        "If enabled, the camera is controlled using the set stop behavior when "
        "no path is playing"
    };

    constexpr openspace::properties::Property::PropertyInfo SpeedScaleInfo = {
        "SpeedScale",
        "Speed Scale",
        "Scale factor that affects the default speed for a camera path."
    };

    constexpr openspace::properties::Property::PropertyInfo OrbitSpeedFactorInfo = {
        "OrbitSpeedFactor",
        "Orbit Speed Factor",
        "Controls the speed of the orbiting around an anchor."
    };
} // namespace

namespace openspace::autonavigation {

AutoNavigationHandler::AutoNavigationHandler()
    : properties::PropertyOwner({ "AutoNavigationHandler" })
    , _defaultCurveOption(
        DefaultCurveOptionInfo,
        properties::OptionProperty::DisplayType::Dropdown
    )
    , _includeRoll(IncludeRollInfo, false)
    , _stopBehavior(
        StopBehaviorInfo,
        properties::OptionProperty::DisplayType::Dropdown
    )
    , _applyStopBehaviorWhenIdle(ApplyStopBehaviorWhenIdleInfo, false)
    , _speedScale(SpeedScaleInfo, 1.f, 0.01f, 2.f)
    , _orbitSpeedFactor(OrbitSpeedFactorInfo, 0.5, 0.0, 20.0)
{
    _defaultCurveOption.addOptions({
        { Path::CurveType::AvoidCollision, "AvoidCollision" },
        { Path::CurveType::Linear, "Linear" },
        { Path::CurveType::ZoomOutOverview, "ZoomOutOverview"}
    });
    addProperty(_defaultCurveOption);

    addProperty(_includeRoll);
    addProperty(_speedScale);

    addProperty(_applyStopBehaviorWhenIdle);

    // Must be listed in the same order as in enum definition
    _stopBehavior.addOptions({
        { StopBehavior::None, "None" },
        { StopBehavior::Orbit, "Orbit" }
    });
    _stopBehavior = StopBehavior::None;
    addProperty(_stopBehavior);

    addProperty(_orbitSpeedFactor);
}

AutoNavigationHandler::~AutoNavigationHandler() {} // NOLINT

Camera* AutoNavigationHandler::camera() const {
    return global::navigationHandler->camera();
}

const SceneGraphNode* AutoNavigationHandler::anchor() const {
    return global::navigationHandler->anchorNode();
}

double AutoNavigationHandler::speedScale() const {
    return _speedScale;
}

bool AutoNavigationHandler::hasCurrentPath() const {
    return _currentPath != nullptr;
}

bool AutoNavigationHandler::hasFinished() const {
    if (!hasCurrentPath()) {
        return true;
    }

    return _currentPath->hasReachedEnd();
}

void AutoNavigationHandler::updateCamera(double deltaTime) {
    ghoul_assert(camera() != nullptr, "Camera must not be nullptr");

    if (!_isPlaying) {
        // TODO: Determine how this should work
        if (hasFinished() && _applyStopBehaviorWhenIdle) {
            applyStopBehavior(deltaTime);
        }
        return;
    }

    if (!hasCurrentPath()) {
        return;
    }

    // If for some reason the time is no longer paused, pause it again
    if (!global::timeManager->isPaused()) {
        global::timeManager->setPause(true);
        LINFO("Cannot start simulation time during camera motion");
    }

    CameraPose newPose = _currentPath->traversePath(deltaTime);
    const std::string newAnchor = _currentPath->currentAnchor();

    // Set anchor node in orbitalNavigator, to render visible nodes and add activate
    // navigation when we reach the end.
    std::string currentAnchor = anchor()->identifier();
    if (currentAnchor != newAnchor) {
        global::navigationHandler->orbitalNavigator().setAnchorNode(newAnchor);
    }

    if (!_includeRoll) {
        removeRollRotation(newPose, deltaTime);
    }

    camera()->setPositionVec3(newPose.position);
    camera()->setRotation(newPose.rotation);

    // TODO: make this work again
    if (_currentPath->hasReachedEnd()) {
        LINFO("Reached end of path");
        _isPlaying = false;
        return;
    }
}

void AutoNavigationHandler::createPath(PathInstruction& instruction) {
    clearPath();

    std::vector<Waypoint> waypoints = instruction.waypoints();
    Waypoint waypointToAdd;

    if (waypoints.empty()) {
        LWARNING("No path was created from instruction. Failed creating waypoints");
        return;
    }
    else {
        // TODO: allow for an instruction to represent a list of waypoints
        waypointToAdd = waypoints[0];
    }

    // TODO: Improve how curve types are handled
    const int curveType = _defaultCurveOption;

    _currentPath = std::make_unique<Path>(
        instruction.startPoint(),
        waypointToAdd,
        Path::CurveType(curveType),
        instruction.duration()
    );

    LINFO("Successfully generated camera path");
}

void AutoNavigationHandler::clearPath() {
    LINFO("Clearing path...");
    _currentPath = nullptr;
}

void AutoNavigationHandler::startPath() {
    if (!hasCurrentPath()) {
        LERROR("There is no path to start");
        return;
    }

    //OBS! Until we can handle simulation time: early out if not paused
    if (!global::timeManager->isPaused()) {
        LERROR("Simulation time must be paused to run a camera path");
        return;
    }

    LINFO("Starting path...");
    _isPlaying = true;
}

void AutoNavigationHandler::abortPath() {
    if (!_isPlaying) {
        LWARNING("No camera path is playing");
        return;
    }
    _isPlaying = false;
    LINFO("Aborted camera path");
}

void AutoNavigationHandler::pausePath() {
    if (hasFinished()) {
        LERROR("No path to pause (path is empty or has finished).");
        return;
    }

    if (!_isPlaying) {
        LERROR("Cannot pause a path that is not playing");
        return;
    }

    LINFO("Path paused");
    _isPlaying = false;
}

void AutoNavigationHandler::continuePath() {
    if (hasFinished()) {
        LERROR("No path to resume (path is empty or has finished).");
        return;
    }

    if (_isPlaying) {
        LERROR("Cannot resume a path that is already playing");
        return;
    }

    LINFO("Continuing path...");
    _isPlaying = true;
}

// TODO: remove when not needed
// Created for debugging
std::vector<glm::dvec3> AutoNavigationHandler::curvePositions(int nSteps) const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dvec3> positions;
    const double du = 1.0 / nSteps;
    const double length = _currentPath->pathLength();
    for (double u = 0.0; u < 1.0; u += du) {
        glm::dvec3 position = _currentPath->interpolatedPose(u * length).position;
        positions.push_back(position);
    }
    positions.push_back(_currentPath->endPoint().position());

    return positions;
}

// TODO: remove when not needed
// Created for debugging
std::vector<glm::dquat> AutoNavigationHandler::curveOrientations(int nSteps) const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dquat> orientations;
    const double du = 1.0 / nSteps;
    const double length = _currentPath->pathLength();
    for (double u = 0.0; u <= 1.0; u += du) {
        const glm::dquat orientation =
            _currentPath->interpolatedPose(u * length).rotation;
        orientations.push_back(orientation);
    }
    orientations.push_back(_currentPath->endPoint().rotation());

    return orientations;
}

// TODO: remove when not needed or combined into pose version
// Created for debugging
std::vector<glm::dvec3> AutoNavigationHandler::curveViewDirections(int nSteps) const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dvec3> viewDirections;
    const double du = 1.0 / nSteps;
    for (double u = 0.0; u < 1.0; u += du) {
        const glm::dquat orientation = _currentPath->interpolatedPose(u).rotation;
        const glm::dvec3 direction = glm::normalize(
            orientation * glm::dvec3(0.0, 0.0, -1.0)
        );
        viewDirections.push_back(direction);
    }

    const glm::dquat orientation = _currentPath->interpolatedPose(1.0).rotation;
    const glm::dvec3 direction = glm::normalize(
        orientation * glm::dvec3(0.0, 0.0, -1.0)
    );
    viewDirections.push_back(direction);

    return viewDirections;
}

// TODO: remove when not needed
// Created for debugging
std::vector<glm::dvec3> AutoNavigationHandler::controlPoints() const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dvec3> points;
    const std::vector<glm::dvec3> curvePoints = _currentPath->controlPoints();
    points.insert(points.end(), curvePoints.begin(), curvePoints.end());

    return points;
}

void AutoNavigationHandler::removeRollRotation(CameraPose& pose, double deltaTime) {
    const glm::dvec3 anchorPos = anchor()->worldPosition();
    const glm::dvec3 cameraDir = glm::normalize(
        pose.rotation * Camera::ViewDirectionCameraSpace
    );
    const double anchorToPosDistance = glm::distance(anchorPos, pose.position);
    const double notTooCloseDistance = deltaTime * anchorToPosDistance;
    glm::dvec3 lookAtPos = pose.position + notTooCloseDistance * cameraDir;
    glm::dquat rollFreeRotation = helpers::lookAtQuaternion(
        pose.position,
        lookAtPos,
        camera()->lookUpVectorWorldSpace()
    );
    pose.rotation = rollFreeRotation;
}

void AutoNavigationHandler::applyStopBehavior(double deltaTime) {
    switch (_stopBehavior) {
        case StopBehavior::None:
            // Do nothing
            break;
        case StopBehavior::Orbit:
            orbitAnchorNode(deltaTime);
            break;
        default:
            throw ghoul::MissingCaseException();
    }
}

void AutoNavigationHandler::orbitAnchorNode(double deltaTime) {
    ghoul_assert(anchor() != nullptr, "Node to orbit must be set!");

    const glm::dvec3 prevPosition = camera()->positionVec3();
    const glm::dquat prevRotation = camera()->rotationQuaternion();
    const glm::dvec3 nodeCenter = anchor()->worldPosition();

    const double speedFactor = 0.1 * _orbitSpeedFactor;

    // Compute orbit speed based on factor and distance to surface
    const double orbitRadius = glm::distance(prevPosition, nodeCenter);
    const double distanceToSurface = orbitRadius - anchor()->boundingSphere();
    const double orbitSpeed = distanceToSurface * speedFactor;

    // Compute a new position along the orbit
    const glm::dvec3 up = camera()->lookUpVectorWorldSpace();
    const glm::dquat lookAtNodeRotation = helpers::lookAtQuaternion(
        prevPosition,
        nodeCenter,
        up
    );
    const glm::dvec3 targetForward = lookAtNodeRotation * glm::dvec3(0.0, 0.0, -1.0);
    const glm::dvec3 rightOrbitTangent = glm::normalize(glm::cross(targetForward, up));

    glm::dvec3 newPosition = prevPosition + orbitSpeed * deltaTime * rightOrbitTangent;

    // Adjust for numerical error - make sure we stay at the same height
    const glm::dvec3 nodeToNewPos = newPosition - nodeCenter;
    const double targetHeight = glm::distance(prevPosition, nodeCenter);
    const double heightDiff = glm::length(nodeToNewPos) - targetHeight;
    newPosition -= heightDiff * glm::normalize(nodeToNewPos);

    // Rotate along the orbit, but keep relative orientation with regards to the anchor
    const glm::dquat localRotation = glm::inverse(lookAtNodeRotation) * prevRotation;
    const glm::dquat newLookAtRotation =
        helpers::lookAtQuaternion(newPosition, nodeCenter, up);

    const glm::dquat newRotation = newLookAtRotation * localRotation;

    camera()->setPositionVec3(newPosition);
    camera()->setRotation(newRotation);
}

} // namespace openspace::autonavigation
<commit_msg>Remove some TODO comments<commit_after>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2021                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include <modules/autonavigation/autonavigationhandler.h>

#include <modules/autonavigation/helperfunctions.h>
#include <modules/autonavigation/pathinstruction.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <openspace/util/timemanager.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/quaternion.hpp>
#include <vector>

namespace {
    constexpr const char* _loggerCat = "AutoNavigationHandler";

    constexpr openspace::properties::Property::PropertyInfo DefaultCurveOptionInfo = {
        "DefaultCurveOption",
        "Default Curve Option",
        "The defualt curve type chosen when generating a path, if none is specified"
        // TODO: right now there is no way to specify a type for a single path
    };

    constexpr openspace::properties::Property::PropertyInfo IncludeRollInfo = {
        "IncludeRoll",
        "Include Roll",
        "If disabled, roll is removed from the interpolation of camera orientation"
    };

    constexpr openspace::properties::Property::PropertyInfo StopBehaviorInfo = {
        "StopBehavior",
        "Stop Behavior",
        "A camera motion behavior that is applied when no path is being played"
    };

    constexpr openspace::properties::Property::PropertyInfo
        ApplyStopBehaviorWhenIdleInfo =
    {
        "ApplyStopBehaviorWhenIdle",
        "Apply Stop Behavior When Idle",
        "If enabled, the camera is controlled using the set stop behavior when "
        "no path is playing"
    };

    constexpr openspace::properties::Property::PropertyInfo SpeedScaleInfo = {
        "SpeedScale",
        "Speed Scale",
        "Scale factor that affects the default speed for a camera path."
    };

    constexpr openspace::properties::Property::PropertyInfo OrbitSpeedFactorInfo = {
        "OrbitSpeedFactor",
        "Orbit Speed Factor",
        "Controls the speed of the orbiting around an anchor."
    };
} // namespace

namespace openspace::autonavigation {

AutoNavigationHandler::AutoNavigationHandler()
    : properties::PropertyOwner({ "AutoNavigationHandler" })
    , _defaultCurveOption(
        DefaultCurveOptionInfo,
        properties::OptionProperty::DisplayType::Dropdown
    )
    , _includeRoll(IncludeRollInfo, false)
    , _stopBehavior(
        StopBehaviorInfo,
        properties::OptionProperty::DisplayType::Dropdown
    )
    , _applyStopBehaviorWhenIdle(ApplyStopBehaviorWhenIdleInfo, false)
    , _speedScale(SpeedScaleInfo, 1.f, 0.01f, 2.f)
    , _orbitSpeedFactor(OrbitSpeedFactorInfo, 0.5, 0.0, 20.0)
{
    _defaultCurveOption.addOptions({
        { Path::CurveType::AvoidCollision, "AvoidCollision" },
        { Path::CurveType::Linear, "Linear" },
        { Path::CurveType::ZoomOutOverview, "ZoomOutOverview"}
    });
    addProperty(_defaultCurveOption);

    addProperty(_includeRoll);
    addProperty(_speedScale);

    addProperty(_applyStopBehaviorWhenIdle);

    // Must be listed in the same order as in enum definition
    _stopBehavior.addOptions({
        { StopBehavior::None, "None" },
        { StopBehavior::Orbit, "Orbit" }
    });
    _stopBehavior = StopBehavior::None;
    addProperty(_stopBehavior);

    addProperty(_orbitSpeedFactor);
}

AutoNavigationHandler::~AutoNavigationHandler() {} // NOLINT

Camera* AutoNavigationHandler::camera() const {
    return global::navigationHandler->camera();
}

const SceneGraphNode* AutoNavigationHandler::anchor() const {
    return global::navigationHandler->anchorNode();
}

double AutoNavigationHandler::speedScale() const {
    return _speedScale;
}

bool AutoNavigationHandler::hasCurrentPath() const {
    return _currentPath != nullptr;
}

bool AutoNavigationHandler::hasFinished() const {
    if (!hasCurrentPath()) {
        return true;
    }

    return _currentPath->hasReachedEnd();
}

void AutoNavigationHandler::updateCamera(double deltaTime) {
    ghoul_assert(camera() != nullptr, "Camera must not be nullptr");

    if (!_isPlaying) {
        // TODO: Determine how this should work
        if (hasFinished() && _applyStopBehaviorWhenIdle) {
            applyStopBehavior(deltaTime);
        }
        return;
    }

    if (!hasCurrentPath()) {
        return;
    }

    // If for some reason the time is no longer paused, pause it again
    if (!global::timeManager->isPaused()) {
        global::timeManager->setPause(true);
        LINFO("Cannot start simulation time during camera motion");
    }

    CameraPose newPose = _currentPath->traversePath(deltaTime);
    const std::string newAnchor = _currentPath->currentAnchor();

    // Set anchor node in orbitalNavigator, to render visible nodes and add activate
    // navigation when we reach the end.
    std::string currentAnchor = anchor()->identifier();
    if (currentAnchor != newAnchor) {
        global::navigationHandler->orbitalNavigator().setAnchorNode(newAnchor);
    }

    if (!_includeRoll) {
        removeRollRotation(newPose, deltaTime);
    }

    camera()->setPositionVec3(newPose.position);
    camera()->setRotation(newPose.rotation);

    if (_currentPath->hasReachedEnd()) {
        LINFO("Reached end of path");
        _isPlaying = false;
        return;
    }
}

void AutoNavigationHandler::createPath(PathInstruction& instruction) {
    clearPath();

    std::vector<Waypoint> waypoints = instruction.waypoints();
    Waypoint waypointToAdd;

    if (waypoints.empty()) {
        LWARNING("No path was created from instruction. Failed creating waypoints");
        return;
    }
    else {
        // TODO: allow for an instruction to represent a list of waypoints
        waypointToAdd = waypoints[0];
    }

    // TODO: Improve how curve types are handled
    const int curveType = _defaultCurveOption;

    _currentPath = std::make_unique<Path>(
        instruction.startPoint(),
        waypointToAdd,
        Path::CurveType(curveType),
        instruction.duration()
    );

    LINFO("Successfully generated camera path");
}

void AutoNavigationHandler::clearPath() {
    LINFO("Clearing path...");
    _currentPath = nullptr;
}

void AutoNavigationHandler::startPath() {
    if (!hasCurrentPath()) {
        LERROR("There is no path to start");
        return;
    }

    //OBS! Until we can handle simulation time: early out if not paused
    if (!global::timeManager->isPaused()) {
        LERROR("Simulation time must be paused to run a camera path");
        return;
    }

    LINFO("Starting path...");
    _isPlaying = true;
}

void AutoNavigationHandler::abortPath() {
    if (!_isPlaying) {
        LWARNING("No camera path is playing");
        return;
    }
    _isPlaying = false;
    LINFO("Aborted camera path");
}

void AutoNavigationHandler::pausePath() {
    if (hasFinished()) {
        LERROR("No path to pause (path is empty or has finished).");
        return;
    }

    if (!_isPlaying) {
        LERROR("Cannot pause a path that is not playing");
        return;
    }

    LINFO("Path paused");
    _isPlaying = false;
}

void AutoNavigationHandler::continuePath() {
    if (hasFinished()) {
        LERROR("No path to resume (path is empty or has finished).");
        return;
    }

    if (_isPlaying) {
        LERROR("Cannot resume a path that is already playing");
        return;
    }

    LINFO("Continuing path...");
    _isPlaying = true;
}

// Created for debugging
std::vector<glm::dvec3> AutoNavigationHandler::curvePositions(int nSteps) const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dvec3> positions;
    const double du = 1.0 / nSteps;
    const double length = _currentPath->pathLength();
    for (double u = 0.0; u < 1.0; u += du) {
        glm::dvec3 position = _currentPath->interpolatedPose(u * length).position;
        positions.push_back(position);
    }
    positions.push_back(_currentPath->endPoint().position());

    return positions;
}

// Created for debugging
std::vector<glm::dquat> AutoNavigationHandler::curveOrientations(int nSteps) const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dquat> orientations;
    const double du = 1.0 / nSteps;
    const double length = _currentPath->pathLength();
    for (double u = 0.0; u <= 1.0; u += du) {
        const glm::dquat orientation =
            _currentPath->interpolatedPose(u * length).rotation;
        orientations.push_back(orientation);
    }
    orientations.push_back(_currentPath->endPoint().rotation());

    return orientations;
}

// Created for debugging
std::vector<glm::dvec3> AutoNavigationHandler::curveViewDirections(int nSteps) const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dvec3> viewDirections;
    const double du = 1.0 / nSteps;
    for (double u = 0.0; u < 1.0; u += du) {
        const glm::dquat orientation = _currentPath->interpolatedPose(u).rotation;
        const glm::dvec3 direction = glm::normalize(
            orientation * glm::dvec3(0.0, 0.0, -1.0)
        );
        viewDirections.push_back(direction);
    }

    const glm::dquat orientation = _currentPath->interpolatedPose(1.0).rotation;
    const glm::dvec3 direction = glm::normalize(
        orientation * glm::dvec3(0.0, 0.0, -1.0)
    );
    viewDirections.push_back(direction);

    return viewDirections;
}

// Created for debugging
std::vector<glm::dvec3> AutoNavigationHandler::controlPoints() const {
    if (!hasCurrentPath()) {
        LERROR("There is no current path to sample points from.");
        return {};
    }

    std::vector<glm::dvec3> points;
    const std::vector<glm::dvec3> curvePoints = _currentPath->controlPoints();
    points.insert(points.end(), curvePoints.begin(), curvePoints.end());

    return points;
}

void AutoNavigationHandler::removeRollRotation(CameraPose& pose, double deltaTime) {
    const glm::dvec3 anchorPos = anchor()->worldPosition();
    const glm::dvec3 cameraDir = glm::normalize(
        pose.rotation * Camera::ViewDirectionCameraSpace
    );
    const double anchorToPosDistance = glm::distance(anchorPos, pose.position);
    const double notTooCloseDistance = deltaTime * anchorToPosDistance;
    glm::dvec3 lookAtPos = pose.position + notTooCloseDistance * cameraDir;
    glm::dquat rollFreeRotation = helpers::lookAtQuaternion(
        pose.position,
        lookAtPos,
        camera()->lookUpVectorWorldSpace()
    );
    pose.rotation = rollFreeRotation;
}

void AutoNavigationHandler::applyStopBehavior(double deltaTime) {
    switch (_stopBehavior) {
        case StopBehavior::None:
            // Do nothing
            break;
        case StopBehavior::Orbit:
            orbitAnchorNode(deltaTime);
            break;
        default:
            throw ghoul::MissingCaseException();
    }
}

void AutoNavigationHandler::orbitAnchorNode(double deltaTime) {
    ghoul_assert(anchor() != nullptr, "Node to orbit must be set!");

    const glm::dvec3 prevPosition = camera()->positionVec3();
    const glm::dquat prevRotation = camera()->rotationQuaternion();
    const glm::dvec3 nodeCenter = anchor()->worldPosition();

    const double speedFactor = 0.1 * _orbitSpeedFactor;

    // Compute orbit speed based on factor and distance to surface
    const double orbitRadius = glm::distance(prevPosition, nodeCenter);
    const double distanceToSurface = orbitRadius - anchor()->boundingSphere();
    const double orbitSpeed = distanceToSurface * speedFactor;

    // Compute a new position along the orbit
    const glm::dvec3 up = camera()->lookUpVectorWorldSpace();
    const glm::dquat lookAtNodeRotation = helpers::lookAtQuaternion(
        prevPosition,
        nodeCenter,
        up
    );
    const glm::dvec3 targetForward = lookAtNodeRotation * glm::dvec3(0.0, 0.0, -1.0);
    const glm::dvec3 rightOrbitTangent = glm::normalize(glm::cross(targetForward, up));

    glm::dvec3 newPosition = prevPosition + orbitSpeed * deltaTime * rightOrbitTangent;

    // Adjust for numerical error - make sure we stay at the same height
    const glm::dvec3 nodeToNewPos = newPosition - nodeCenter;
    const double targetHeight = glm::distance(prevPosition, nodeCenter);
    const double heightDiff = glm::length(nodeToNewPos) - targetHeight;
    newPosition -= heightDiff * glm::normalize(nodeToNewPos);

    // Rotate along the orbit, but keep relative orientation with regards to the anchor
    const glm::dquat localRotation = glm::inverse(lookAtNodeRotation) * prevRotation;
    const glm::dquat newLookAtRotation =
        helpers::lookAtQuaternion(newPosition, nodeCenter, up);

    const glm::dquat newRotation = newLookAtRotation * localRotation;

    camera()->setPositionVec3(newPosition);
    camera()->setRotation(newRotation);
}

} // namespace openspace::autonavigation
<|endoftext|>


<commit_before>#include "joystick.h"
#include "esp_log.h"
#include <stdlib.h>

static const char *TAG = "joystick";

static QueueHandle_t *subscriptions;
static size_t num_subscriptions;

static SemaphoreHandle_t interrupt_sem;

static void joystick_check_task(void *pvParameter);
static void PCFInterrupt();

void joystick_initialize()
{
  xTaskCreatePinnedToCore(joystick_check_task, "joystick_check_task", 4096, NULL, 1, NULL, 1);
}

bool joystick_subscribe(QueueHandle_t queue)
{
  void *new_subscriptions = realloc(subscriptions, (num_subscriptions + 1) * sizeof(QueueHandle_t));
  if (!new_subscriptions) {
	ESP_LOGE(TAG, "Failed to allocate new subscription #%d", (num_subscriptions+1));
	return false;
  }

  subscriptions = (QueueHandle_t *)new_subscriptions;
  subscriptions[num_subscriptions] = queue;
  num_subscriptions++;
  return true;
}

static void joystick_check_task(void *pvParameter)
{

  joystick_check_s joystick = {0,0,0,"joystick"};

  pinMode(JOYSTICK_PIN_X, INPUT);
  pinMode(JOYSTICK_PIN_Y, INPUT);

  while (1) {

    if (millis() - joystick.previous_millis >= JOYSTICK_SAMPLE_MILLIS) {

      int x_value = analogRead(JOYSTICK_PIN_X);
      int y_value = analogRead(JOYSTICK_PIN_Y);

      bool changed = (abs(joystick.last_x - x_value) > 20) || (abs(joystick.last_y - y_value) > 20);

      if (changed) {
        //ESP_LOGI(TAG, "x %d y %d", x_value, y_value);

        joystick.previous_millis = millis();
        joystick.last_x = x_value;
        joystick.last_y = y_value;

        joystick_reading_t reading = {
        .label = joystick.label,
        .x_value = x_value,
        .y_value = y_value,
        };

        for (int i = 0; i < num_subscriptions; i++) {
          xQueueSendToBack(subscriptions[i], &reading, 0);
        }

      }

    }

    vTaskDelay(50 / portTICK_PERIOD_MS);
  }
}

static void PCFInterrupt()
{
  portBASE_TYPE higher_task_awoken;
  xSemaphoreGiveFromISR(interrupt_sem, &higher_task_awoken);
  if (higher_task_awoken) {
	portYIELD_FROM_ISR();
  }
}
<commit_msg>joystick: Remove unused ISR handler<commit_after>#include "joystick.h"
#include "esp_log.h"
#include <stdlib.h>

static const char *TAG = "joystick";

static QueueHandle_t *subscriptions;
static size_t num_subscriptions;

static void joystick_check_task(void *pvParameter);

void joystick_initialize()
{
  xTaskCreatePinnedToCore(joystick_check_task, "joystick_check_task", 4096, NULL, 1, NULL, 1);
}

bool joystick_subscribe(QueueHandle_t queue)
{
  void *new_subscriptions = realloc(subscriptions, (num_subscriptions + 1) * sizeof(QueueHandle_t));
  if (!new_subscriptions) {
	ESP_LOGE(TAG, "Failed to allocate new subscription #%d", (num_subscriptions+1));
	return false;
  }

  subscriptions = (QueueHandle_t *)new_subscriptions;
  subscriptions[num_subscriptions] = queue;
  num_subscriptions++;
  return true;
}

static void joystick_check_task(void *pvParameter)
{

  joystick_check_s joystick = {0,0,0,"joystick"};

  pinMode(JOYSTICK_PIN_X, INPUT);
  pinMode(JOYSTICK_PIN_Y, INPUT);

  while (1) {

    if (millis() - joystick.previous_millis >= JOYSTICK_SAMPLE_MILLIS) {

      int x_value = analogRead(JOYSTICK_PIN_X);
      int y_value = analogRead(JOYSTICK_PIN_Y);

      bool changed = (abs(joystick.last_x - x_value) > 20) || (abs(joystick.last_y - y_value) > 20);

      if (changed) {
        //ESP_LOGI(TAG, "x %d y %d", x_value, y_value);

        joystick.previous_millis = millis();
        joystick.last_x = x_value;
        joystick.last_y = y_value;

        joystick_reading_t reading = {
        .label = joystick.label,
        .x_value = x_value,
        .y_value = y_value,
        };

        for (int i = 0; i < num_subscriptions; i++) {
          xQueueSendToBack(subscriptions[i], &reading, 0);
        }

      }

    }

    vTaskDelay(50 / portTICK_PERIOD_MS);
  }
}
<|endoftext|>


<commit_before>#include "core/Observer.hpp"
#include "core/SquareLattice.hpp"
#include "sdl/RenderableWindow.hpp"

namespace miniascape
{

template<typename T_traits>
class GraphicalObserver : public Observer<T_traits>
{
  public:
    using base_type   = Observer<T_traits>;
    using state_type  = typename base_type::state_type;
    using cell_type   = typename base_type::cell_type;
    using time_type   = typename base_type::time_type;
    using world_type  = typename base_type::world_type;

  public:
    GraphicalObserver(const std::size_t x, const std::size_t y)
        : window_(x, y)
    {}
    ~GraphicalObserver() = default;

    void observe(const time_type& t, const world_type& world) override;

  private:
    sdl::RenderableWindow window_;
};

template<typename T_traits>
void GraphicalObserver<T_traits>::observe(
        const time_type& t, const world_type& world)
{
    const auto size = window_.size();
    const sdl::Color green{0, 255, 0, 0};
    const sdl::Color black{0,   0, 0, 0};
    window_.clear(black);
    for(int x = 0; x < size.first; ++x)
    for(int y = 0; y < size.second; ++y)
    {
        sdl::Point pos{x, y};
        if((dynamic_cast<SquareLattice<T_traits> const&>(world)(x, y))->state)
            window_.putpixel(pos, green);
    }
    window_.update();
    return;
}

}
<commit_msg>change class name and fix sdl system call<commit_after>#include "core/Observer.hpp"
#include "core/SquareLattice.hpp"
#include "sdl/RenderableWindow.hpp"
#include "sdl/System.hpp"

namespace miniascape
{

template<typename T_traits>
class ConwaysLifeGameVisualizer : public Observer<T_traits>
{
  public:
    using base_type   = Observer<T_traits>;
    using state_type  = typename base_type::state_type;
    using cell_type   = typename base_type::cell_type;
    using time_type   = typename base_type::time_type;
    using world_type  = typename base_type::world_type;

  public:
    ConwaysLifeGameVisualizer(const std::size_t x, const std::size_t y)
        : system_(SDL_INIT_VIDEO), window_(x, y)
    {
        const sdl::Color black{0, 0, 0, 0};
        window_.clear(black);
        window_.update();
    }
    ~ConwaysLifeGameVisualizer()
    {
        window_.~RenderableWindow();
        system_.~System();
    }

    void observe(const time_type& t, const world_type& world) override;

  private:
    sdl::System           system_;
    sdl::RenderableWindow window_;
};

template<typename T_traits>
void ConwaysLifeGameVisualizer<T_traits>::observe(
        const time_type& t, const world_type& world)
{
    const auto size = window_.size();
    const sdl::Color green{0, 255, 0, 0};
    const sdl::Color black{0,   0, 0, 0};
    window_.clear(black);
    for(int x = 0; x < size.first; ++x)
    for(int y = 0; y < size.second; ++y)
    {
        sdl::Point pos{x, y};
        if((dynamic_cast<SquareLattice<T_traits> const&>(world)(x, y))->state)
            window_.putpixel(pos, green);
    }
    window_.update();
    window_.wait(std::chrono::microseconds(10));
    return;
}

}
<|endoftext|>