<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: toolbarmanager.hxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 00:48:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_
#define __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif
#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif
#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif
#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif
#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XSTATUSLISTENER_HPP_
#include <com/sun/star/frame/XStatusListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
#include <com/sun/star/container/XIndexAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
#include <com/sun/star/frame/XModuleManager.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XUICONTROLLERREGISTRATION_HPP_
#include <com/sun/star/frame/XUIControllerRegistration.hpp>
#endif
#ifndef _COM_SUN_STAR_UI_XIMAGEMANAGER_HPP_
#include <com/sun/star/ui/XImageManager.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XSTATUSLISTENER_HPP_
#include <com/sun/star/frame/XStatusListener.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XSUBTOOLBARCONTROLLER_HPP_
#include <com/sun/star/frame/XSubToolbarController.hpp>
#endif
#ifndef _COM_SUN_STAR_UI_ITEMSTYLE_HPP_
#include <com/sun/star/ui/ItemStyle.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _RTL_USTRING_
#include <rtl/ustring.hxx>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_
#include <cppuhelper/interfacecontainer.hxx>
#endif

#include <vcl/toolbox.hxx>

namespace framework
{

class ToolBar;
class ToolBarManager : public ::com::sun::star::frame::XFrameActionListener         ,
                       public ::com::sun::star::frame::XStatusListener              ,
                       public ::com::sun::star::lang::XComponent                    ,
                       public ::com::sun::star::lang::XTypeProvider                 ,
                       public ::com::sun::star::ui::XUIConfigurationListener,
                       public ThreadHelpBase                                        ,
                       public ::cppu::OWeakObject
{
    public:
        ToolBarManager( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rServicveManager,
                        const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& rFrame,
                        const rtl::OUString& rResourceName,
                        ToolBar* pToolBar );
        virtual ~ToolBarManager();

        //  XInterface, XTypeProvider, XServiceInfo
        DECLARE_XINTERFACE
        DECLARE_XTYPEPROVIDER

        ToolBox* GetToolBar() const;

        // XFrameActionListener
        virtual void SAL_CALL frameAction( const com::sun::star::frame::FrameActionEvent& Action ) throw ( ::com::sun::star::uno::RuntimeException );

        // XStatusListener
        virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );

        // XEventListener
        virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) throw ( ::com::sun::star::uno::RuntimeException );

        // XUIConfigurationListener
        virtual void SAL_CALL elementInserted( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);

        // XComponent
        void SAL_CALL dispose() throw ( ::com::sun::star::uno::RuntimeException );
        void SAL_CALL addEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );
        void SAL_CALL removeEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );

        void CheckAndUpdateImages();
        void RefreshImages();
        void FillToolbar( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rToolBarData );
        void notifyRegisteredControllers( const rtl::OUString& aUIElementName, const rtl::OUString& aCommand );
        void Destroy();
        static sal_Int16 GetCurrentSymbolSize();

    protected:
        struct ControllerParams
        {
            sal_Int16 nWidth;
        };
        typedef std::vector< ControllerParams > ControllerParamsVector;

        DECL_LINK( Click, ToolBox * );
        DECL_LINK( DropdownClick, ToolBox * );
        DECL_LINK( DoubleClick, ToolBox * );
        DECL_LINK( Select, ToolBox * );
        DECL_LINK( Highlight, ToolBox * );
        DECL_LINK( Activate, ToolBox * );
        DECL_LINK( Deactivate, ToolBox * );
        DECL_LINK( StateChanged, StateChangedType* );
        DECL_LINK( DataChanged, DataChangedEvent* );

        DECL_LINK( MenuButton, ToolBox * );
        DECL_LINK( MenuSelect, Menu * );
        DECL_LINK( MenuDeactivate, Menu * );
        DECL_LINK( AsyncUpdateControllersHdl, Timer * );

        void RemoveControllers();
        rtl::OUString RetrieveLabelFromCommand( const rtl::OUString& aCmdURL );
        void CreateControllers( const ControllerParamsVector& );
        void UpdateControllers();
        void AddFrameActionListener();
        void AddImageOrientationListener();
        void UpdateImageOrientation();
        void ImplClearPopupMenu( ToolBox *pToolBar );
        void RequestImages();
        sal_uInt16 ConvertStyleToToolboxItemBits( sal_Int32 nStyle );
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > GetModelFromFrame() const;
        sal_Bool IsPluginMode() const;

    protected:
        struct CommandInfo
        {
            CommandInfo() : nId( 0 ),
                            nImageInfo( 0 ),
                            bMirrored( false ),
                            bRotated( false ) {}
            USHORT                  nId;
            std::vector<USHORT>     aIds;
            sal_Int16               nImageInfo;
            sal_Bool                bMirrored : 1,
                                    bRotated  : 1;
        };

        typedef std::vector< ::com::sun::star::uno::Reference< com::sun::star::frame::XStatusListener > >           ToolBarControllerVector;
        typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XSubToolbarController > > SubToolBarControllerVector;
        typedef BaseHash< CommandInfo >                                                                             CommandToInfoMap;
        typedef BaseHash< SubToolBarControllerVector >                                                              SubToolBarToSubToolBarControllerMap;

        sal_Bool                                                                                m_bDisposed : 1,
                                                                                m_bIsHiContrast : 1,
                                                                                m_bSmallSymbols : 1,
                                                                                m_bModuleIdentified : 1,
                                                                                m_bAddedToTaskPaneList : 1,
                                                                                m_bVerticalTextEnabled : 1,
                                                                                m_bFrameActionRegistered : 1,
                                                                                m_bUpdateControllers : 1;
        sal_Bool                                                                                m_bImageOrientationRegistered : 1,
                                                                                m_bImageMirrored : 1,
                                                                                m_bCanBeCustomized : 1;
        long                                                                                m_lImageRotation;
        ToolBar*                                                                                m_pToolBar;
        rtl::OUString                                                                                m_aModuleIdentifier;
        rtl::OUString                                                                                m_aResourceName;
        com::sun::star::uno::Reference< com::sun::star::frame::XFrame >                                 m_xFrame;
        com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >                        m_xUICommandLabels;
        ToolBarControllerVector                                                                         m_aControllerVector;
        ::cppu::OMultiTypeInterfaceContainerHelper                                                      m_aListenerContainer;   /// container for ALL Listener
        ::com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >                  m_xServiceManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XUIControllerRegistration >  m_xToolbarControllerRegistration;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                 m_xModuleImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                 m_xDocImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >                          m_xImageOrientationListener;
        CommandToInfoMap                                                                                m_aCommandMap;
        SubToolBarToSubToolBarControllerMap                                                             m_aSubToolBarControllerMap;
        Timer                                                                                m_aAsyncUpdateControllersTimer;
};

}

#endif // __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_
<commit_msg>INTEGRATION: CWS iconswitching1 (1.10.4); FILE MERGED 2005/11/01 20:30:08 kendy 1.10.4.3: RESYNC: (1.10-1.11); FILE MERGED 2005/07/20 14:04:03 kendy 1.10.4.2: #i36518# Implement the icon switching 2005/07/20 13:48:26 kendy 1.10.4.1: #i36518# Cleanup after cutnpaste in CWS oooicons<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: toolbarmanager.hxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: kz $ $Date: 2006-01-05 18:10:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_
#define __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif
#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif
#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif
#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif
#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XSTATUSLISTENER_HPP_
#include <com/sun/star/frame/XStatusListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
#include <com/sun/star/container/XIndexAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
#include <com/sun/star/frame/XModuleManager.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XUICONTROLLERREGISTRATION_HPP_
#include <com/sun/star/frame/XUIControllerRegistration.hpp>
#endif
#ifndef _COM_SUN_STAR_UI_XIMAGEMANAGER_HPP_
#include <com/sun/star/ui/XImageManager.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XSTATUSLISTENER_HPP_
#include <com/sun/star/frame/XStatusListener.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XSUBTOOLBARCONTROLLER_HPP_
#include <com/sun/star/frame/XSubToolbarController.hpp>
#endif
#ifndef _COM_SUN_STAR_UI_ITEMSTYLE_HPP_
#include <com/sun/star/ui/ItemStyle.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _RTL_USTRING_
#include <rtl/ustring.hxx>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_
#include <cppuhelper/interfacecontainer.hxx>
#endif

#include <vcl/toolbox.hxx>

namespace framework
{

class ToolBar;
class ToolBarManager : public ::com::sun::star::frame::XFrameActionListener         ,
                       public ::com::sun::star::frame::XStatusListener              ,
                       public ::com::sun::star::lang::XComponent                    ,
                       public ::com::sun::star::lang::XTypeProvider                 ,
                       public ::com::sun::star::ui::XUIConfigurationListener,
                       public ThreadHelpBase                                        ,
                       public ::cppu::OWeakObject
{
    public:
        ToolBarManager( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rServicveManager,
                        const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& rFrame,
                        const rtl::OUString& rResourceName,
                        ToolBar* pToolBar );
        virtual ~ToolBarManager();

        //  XInterface, XTypeProvider, XServiceInfo
        DECLARE_XINTERFACE
        DECLARE_XTYPEPROVIDER

        ToolBox* GetToolBar() const;

        // XFrameActionListener
        virtual void SAL_CALL frameAction( const com::sun::star::frame::FrameActionEvent& Action ) throw ( ::com::sun::star::uno::RuntimeException );

        // XStatusListener
        virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );

        // XEventListener
        virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) throw ( ::com::sun::star::uno::RuntimeException );

        // XUIConfigurationListener
        virtual void SAL_CALL elementInserted( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);

        // XComponent
        void SAL_CALL dispose() throw ( ::com::sun::star::uno::RuntimeException );
        void SAL_CALL addEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );
        void SAL_CALL removeEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );

        void CheckAndUpdateImages();
        void RefreshImages();
        void FillToolbar( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rToolBarData );
        void notifyRegisteredControllers( const rtl::OUString& aUIElementName, const rtl::OUString& aCommand );
        void Destroy();

    protected:
        struct ControllerParams
        {
            sal_Int16 nWidth;
        };
        typedef std::vector< ControllerParams > ControllerParamsVector;

        DECL_LINK( Click, ToolBox * );
        DECL_LINK( DropdownClick, ToolBox * );
        DECL_LINK( DoubleClick, ToolBox * );
        DECL_LINK( Select, ToolBox * );
        DECL_LINK( Highlight, ToolBox * );
        DECL_LINK( Activate, ToolBox * );
        DECL_LINK( Deactivate, ToolBox * );
        DECL_LINK( StateChanged, StateChangedType* );
        DECL_LINK( DataChanged, DataChangedEvent* );

        DECL_LINK( MenuButton, ToolBox * );
        DECL_LINK( MenuSelect, Menu * );
        DECL_LINK( MenuDeactivate, Menu * );
        DECL_LINK( AsyncUpdateControllersHdl, Timer * );

        void RemoveControllers();
        rtl::OUString RetrieveLabelFromCommand( const rtl::OUString& aCmdURL );
        void CreateControllers( const ControllerParamsVector& );
        void UpdateControllers();
        void AddFrameActionListener();
        void AddImageOrientationListener();
        void UpdateImageOrientation();
        void ImplClearPopupMenu( ToolBox *pToolBar );
        void RequestImages();
        sal_uInt16 ConvertStyleToToolboxItemBits( sal_Int32 nStyle );
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > GetModelFromFrame() const;
        sal_Bool IsPluginMode() const;

    protected:
        struct CommandInfo
        {
            CommandInfo() : nId( 0 ),
                            nImageInfo( 0 ),
                            bMirrored( false ),
                            bRotated( false ) {}
            USHORT                  nId;
            std::vector<USHORT>     aIds;
            sal_Int16               nImageInfo;
            sal_Bool                bMirrored : 1,
                                    bRotated  : 1;
        };

        typedef std::vector< ::com::sun::star::uno::Reference< com::sun::star::frame::XStatusListener > >           ToolBarControllerVector;
        typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XSubToolbarController > > SubToolBarControllerVector;
        typedef BaseHash< CommandInfo >                                                                             CommandToInfoMap;
        typedef BaseHash< SubToolBarControllerVector >                                                              SubToolBarToSubToolBarControllerMap;

        sal_Bool                                                                                m_bDisposed : 1,
                                                                                m_bIsHiContrast : 1,
                                                                                m_bSmallSymbols : 1,
                                                                                m_bModuleIdentified : 1,
                                                                                m_bAddedToTaskPaneList : 1,
                                                                                m_bVerticalTextEnabled : 1,
                                                                                m_bFrameActionRegistered : 1,
                                                                                m_bUpdateControllers : 1;
        sal_Bool                                                                                m_bImageOrientationRegistered : 1,
                                                                                m_bImageMirrored : 1,
                                                                                m_bCanBeCustomized : 1;
        long                                                                                m_lImageRotation;
        ToolBar*                                                                                m_pToolBar;
        rtl::OUString                                                                                m_aModuleIdentifier;
        rtl::OUString                                                                                m_aResourceName;
        com::sun::star::uno::Reference< com::sun::star::frame::XFrame >                                 m_xFrame;
        com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >                        m_xUICommandLabels;
        ToolBarControllerVector                                                                         m_aControllerVector;
        ::cppu::OMultiTypeInterfaceContainerHelper                                                      m_aListenerContainer;   /// container for ALL Listener
        ::com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >                  m_xServiceManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XUIControllerRegistration >  m_xToolbarControllerRegistration;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                 m_xModuleImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                 m_xDocImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >                          m_xImageOrientationListener;
        CommandToInfoMap                                                                                m_aCommandMap;
        SubToolBarToSubToolBarControllerMap                                                             m_aSubToolBarControllerMap;
        Timer                                                                                m_aAsyncUpdateControllersTimer;
        sal_Int16                                                                                m_nSymbolsStyle;
};

}

#endif // __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_
<|endoftext|>


<commit_before>#include "chorus.hpp"

#include "core/ui/vector_graphics.hpp"

#include "util/iterator.hpp"
#include "util/utility.hpp"

namespace otto::engines {

  using namespace ui;
  using namespace ui::vg;

  struct ChorusScreen : EngineScreen<Chorus> {
    void draw(Canvas& ctx) override;
    bool keypress(Key key) override;
    void rotary(RotaryEvent e) override;

    void draw_front_head(Canvas&, Point, Colour, float);
    void draw_background_head(Canvas&, Point, Colour, float);

    std::array<ui::vg::Colour, 10> colour_list = {Colours::Yellow,
                                                  Colours::Green,
                                                  Colours::Blue,
                                                  Colours::Yellow,
                                                  Colours::Green,
                                                  Colours::Blue,
                                                  Colours::Red,
                                                  Colours::Green,
                                                  Colours::Yellow,
                                                  Colours::Red};

    float wave_height = 20;
    float intpart = 1;
    gam::AD<> env_blue{0.001, 0.004, 1, 0};
    gam::AD<> env_green{0.001, 0.004, 1, 0};
    gam::AD<> env_yellow{0.001, 0.004, 1, 0};
    gam::AD<> env_red{0.001, 0.004, 1, 0};

    using EngineScreen<Chorus>::EngineScreen;
  };

  Chorus::Chorus() : EffectEngine<Chorus>(std::make_unique<ChorusScreen>(this))
  {
    // Initialize LPF for param smoothening
    lpf.type(gam::SMOOTHING);
    lpf.freq(1000);

    // Set proper size of phase accumulator for graphics
    phase.radius(1);

    props.delay.on_change().connect([this](float delay) { chorus.delay(delay); });

    props.rate.on_change().connect([this](float rate) {
      chorus.freq(rate);
      phase.freq(rate * 0.5f);
    });

    props.feedback.on_change().connect([this](float fbk) { chorus.fbk(fbk); });

    props.depth.on_change().connect([this](float depth) {
      chorus.depth(depth);
    });
  }

  audio::ProcessData<2> Chorus::process(audio::ProcessData<1> data)
  {
    // Allocate two audio buffers (left and right channels)
    auto buf = Application::current().audio_manager->buffer_pool().allocate_multi<2>();
    // Fill buffers with processed samples
    for (auto&& [dat, bufL, bufR] : util::zip(data.audio, buf[0], buf[1])) {
      // Apply smoothening filter to depth param to reduce cracks in sound
      chorus.depth(lpf(props.depth));
      // Get one sample from chorus effect
      chorus(dat, bufL, bufR);
      // Update phase value for graphics
      props.phase_value = phase.nextPhase();
    }
    // Reassign (redirect) processed data to original data
    return data.redirect(buf);
  }

  // SCREEN //

  void ChorusScreen::rotary(ui::RotaryEvent ev)
  {
    auto& props = engine.props;
    switch (ev.rotary) {
    case Rotary::blue: {
      props.delay.step(ev.clicks);
      env_blue.resetSoft();
      break;
    }
    case Rotary::green: {
      props.rate.step(ev.clicks);
      env_green.resetSoft();
      break;
    }
    case Rotary::yellow: {
      props.feedback.step(ev.clicks);
      env_yellow.resetSoft();
      break;
    }
    case Rotary::red: {
      props.depth.step(ev.clicks);
      env_red.resetSoft();
      break;
    }
    }
  }

  bool ChorusScreen::keypress(ui::Key key)
  {
    return false;
  }

  void ChorusScreen::draw(ui::vg::Canvas& ctx)
  {
    using namespace ui::vg;
    using util::math::vec;

    auto& props = engine.props;

    ctx.font(Fonts::Norm, 35);

    constexpr float x_pad = 20;
    constexpr float y_pad = 20;

    constexpr float x_right = width - x_pad;
    constexpr float y_bottom = height - y_pad;
    constexpr float number_shift = 30;

    wave_height = props.depth * 1000;

    // Text
    ctx.font(Fonts::Norm, 25);
    ctx.fillStyle(Colours::Red);
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText("depth", x_right, y_bottom);

    ctx.fillStyle(Colours::Green);
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText("rate", x_pad, y_bottom);

    ctx.fillStyle(Colours::Yellow);
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText("feedback", x_right, y_pad);

    ctx.fillStyle(Colours::Blue);
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText("delay", x_pad, y_pad);

    // Numbers
    ctx.font(Fonts::Norm, 40);

    // chorus/RedValue/10
    ctx.fillStyle(Colours::Red.dim(1 - env_red()));
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(10000 * props.depth)), x_right, y_bottom - number_shift);

    // chorus/GreenValue/10
    ctx.fillStyle(Colours::Green.dim(1 - env_green()));
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(props.rate * 100)), x_pad, y_bottom - number_shift);

    // chorus/YellowValue/0
    ctx.fillStyle(Colours::Yellow.dim(1 - env_yellow()));
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(props.feedback * 100)), x_right, y_pad + number_shift);

    // chorus/BlueValue/1
    ctx.fillStyle(Colours::Blue.dim(1 - env_blue()));
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(10000 * props.delay)), x_pad, y_pad + number_shift);

    //Heads
    constexpr float slope = 0.5;
    constexpr float spacing_constant = 1000;
    constexpr int num_heads = 10;

    float spacing = spacing_constant * props.delay + 10;
    Point start = {140 - props.delay * 5000, 165};

    for (int i=num_heads; i>=1; i--) {
      float head_height = wave_height * gam::scl::sinP9(gam::scl::wrap(props.phase_value - 0.2f*(float)i, 1.f, -1.f));
      draw_background_head(ctx, {start.x + i*spacing, start.y + head_height}, colour_list[i].dim((float)i/(float)num_heads), 1 - i*0.07);
    }
    draw_front_head(ctx, {start.x, start.y + wave_height * gam::scl::sinP9(props.phase_value)}, Colours::Blue, 1);

  }

  void ChorusScreen::draw_front_head(ui::vg::Canvas& ctx, Point p, Colour c, float scale)
  {
    // chorus/HeadMain
    ctx.beginPath();
    ctx.scaleTowards(scale, p);
    ctx.moveTo(p.x, p.y);
    ctx.lineTo(p.x, p.y - 173.0 + 153.6);
    ctx.bezierCurveTo(p.x + 121.4 - 130.8, p.y - 173.0 + 148.5, p.x + 115.0 - 130.8, p.y - 173.0 + 138.6, p.x + 115.0 - 130.8, p.y - 173.0 + 127.1);
    ctx.lineTo(p.x + 115.0 - 130.8, p.y - 173.0 + 107.3);
    ctx.bezierCurveTo(p.x + 115.0 - 130.8, p.y - 173.0 + 85.1, p.x + 133.0 - 130.8, p.y - 173.0 + 67.0, p.x + 155.2 - 130.8, p.y - 173.0 + 67.0);
    ctx.bezierCurveTo(p.x + 177.4 - 130.8, p.y - 173.0 + 67.0, p.x + 195.5 - 130.8, p.y - 173.0 + 85.1, p.x + 195.5 - 130.8, p.y - 173.0 + 107.3);
    ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 117.8);
    ctx.lineTo(p.x + 204.4 - 130.8, p.y - 173.0 + 130.0);
    ctx.bezierCurveTo(p.x + 205.4 - 130.8, p.y - 173.0 + 131.4, p.x + 205.1 - 130.8, p.y - 173.0 + 133.4, p.x + 203.7 - 130.8, p.y - 173.0 + 134.4);
    ctx.bezierCurveTo(p.x + 203.2 - 130.8, p.y - 173.0 + 134.8, p.x + 202.5 - 130.8, p.y - 173.0 + 135.0, p.x + 201.8 - 130.8, p.y - 173.0 + 135.0);
    ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 135.0);
    ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 152.4);
    ctx.bezierCurveTo(p.x + 195.5 - 130.8, p.y - 173.0 + 155.1, p.x + 193.3 - 130.8, p.y - 173.0 + 157.2, p.x + 190.7 - 130.8, p.y - 173.0 + 157.2);
    ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 157.2);
    ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 173.0);
    ctx.fill(Colours::Black);
    ctx.strokeStyle(c);
    ctx.stroke();

  }
  void ChorusScreen::draw_background_head(ui::vg::Canvas& ctx, Point p, Colour c, float scale)
  {
    ctx.group([&] {
      ctx.beginPath();
      ctx.scaleTowards(scale, {p.x, p.y + (67.f - 173.f) / 2.f});
      ctx.lineWidth(6 / scale);
      ctx.moveTo(p.x + 115.0 - 130.8, p.y - 173.0 + 127.1);
      ctx.lineTo(p.x + 115.0 - 130.8, p.y - 173.0 + 107.3);
      ctx.bezierCurveTo(p.x + 115.0 - 130.8, p.y - 173.0 + 85.1, p.x + 133.0 - 130.8, p.y - 173.0 + 67.0,
                        p.x + 155.2 - 130.8, p.y - 173.0 + 67.0);
      ctx.bezierCurveTo(p.x + 177.4 - 130.8, p.y - 173.0 + 67.0, p.x + 195.5 - 130.8, p.y - 173.0 + 85.1,
                        p.x + 195.5 - 130.8, p.y - 173.0 + 107.3);
      ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 117.8);
      ctx.lineTo(p.x + 204.4 - 130.8, p.y - 173.0 + 130.0);
      ctx.bezierCurveTo(p.x + 205.4 - 130.8, p.y - 173.0 + 131.4, p.x + 205.1 - 130.8, p.y - 173.0 + 133.4,
                        p.x + 203.7 - 130.8, p.y - 173.0 + 134.4);
      ctx.bezierCurveTo(p.x + 203.2 - 130.8, p.y - 173.0 + 134.8, p.x + 202.5 - 130.8, p.y - 173.0 + 135.0,
                        p.x + 201.8 - 130.8, p.y - 173.0 + 135.0);
      ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 135.0);
      ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 152.4);
      ctx.bezierCurveTo(p.x + 195.5 - 130.8, p.y - 173.0 + 155.1, p.x + 193.3 - 130.8, p.y - 173.0 + 157.2,
                        p.x + 190.7 - 130.8, p.y - 173.0 + 157.2);
      ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 157.2);
      ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 173.0);
      ctx.fill(Colours::Black);
      ctx.strokeStyle(c);
      ctx.stroke();
    });
  }

} // namespace otto::engines
<commit_msg>Pedantic chorus ui changes<commit_after>#include "chorus.hpp"

#include "core/ui/vector_graphics.hpp"

#include "util/iterator.hpp"
#include "util/utility.hpp"

namespace otto::engines {

  using namespace ui;
  using namespace ui::vg;

  struct ChorusScreen : EngineScreen<Chorus> {
    void draw(Canvas& ctx) override;
    bool keypress(Key key) override;
    void rotary(RotaryEvent e) override;

    void draw_front_head(Canvas&, Point, Colour, float);
    void draw_background_head(Canvas&, Point, Colour, float);

    std::array<ui::vg::Colour, 10> colour_list = {Colours::Blue,
                                                  Colours::Green,
                                                  Colours::Yellow,
                                                  Colours::Red,
                                                  Colours::Green,
                                                  Colours::Blue,
                                                  Colours::Red,
                                                  Colours::Green,
                                                  Colours::Yellow,
                                                  Colours::Red};

    float wave_height = 20;
    float intpart = 1;
    gam::AD<> env_blue{0.0005, 0.002, 1, 0};
    gam::AD<> env_green{0.0005, 0.002, 1, 0};
    gam::AD<> env_yellow{0.0005, 0.002, 1, 0};
    gam::AD<> env_red{0.0005, 0.002, 1, 0};

    using EngineScreen<Chorus>::EngineScreen;
  };

  Chorus::Chorus() : EffectEngine<Chorus>(std::make_unique<ChorusScreen>(this))
  {
    // Initialize LPF for param smoothening
    lpf.type(gam::SMOOTHING);
    lpf.freq(1000);

    // Set proper size of phase accumulator for graphics
    phase.radius(1);

    props.delay.on_change().connect([this](float delay) { chorus.delay(delay); });

    props.rate.on_change().connect([this](float rate) {
      chorus.freq(rate);
      phase.freq(rate * 0.5f);
    });

    props.feedback.on_change().connect([this](float fbk) { chorus.fbk(fbk); });

    props.depth.on_change().connect([this](float depth) {
      chorus.depth(depth);
    });
  }

  audio::ProcessData<2> Chorus::process(audio::ProcessData<1> data)
  {
    // Allocate two audio buffers (left and right channels)
    auto buf = Application::current().audio_manager->buffer_pool().allocate_multi<2>();
    // Fill buffers with processed samples
    for (auto&& [dat, bufL, bufR] : util::zip(data.audio, buf[0], buf[1])) {
      // Apply smoothening filter to depth param to reduce cracks in sound
      chorus.depth(lpf(props.depth));
      // Get one sample from chorus effect
      chorus(dat, bufL, bufR);
      // Update phase value for graphics
      props.phase_value = phase.nextPhase();
    }
    // Reassign (redirect) processed data to original data
    return data.redirect(buf);
  }

  // SCREEN //

  void ChorusScreen::rotary(ui::RotaryEvent ev)
  {
    auto& props = engine.props;
    switch (ev.rotary) {
    case Rotary::blue: {
      props.delay.step(ev.clicks);
      env_blue.resetSoft();
      break;
    }
    case Rotary::green: {
      props.rate.step(ev.clicks);
      env_green.resetSoft();
      break;
    }
    case Rotary::yellow: {
      props.feedback.step(ev.clicks);
      env_yellow.resetSoft();
      break;
    }
    case Rotary::red: {
      props.depth.step(ev.clicks);
      env_red.resetSoft();
      break;
    }
    }
  }

  bool ChorusScreen::keypress(ui::Key key)
  {
    return false;
  }

  void ChorusScreen::draw(ui::vg::Canvas& ctx)
  {
    using namespace ui::vg;
    using util::math::vec;

    auto& props = engine.props;

    ctx.font(Fonts::Norm, 35);

    constexpr float x_pad = 20;
    constexpr float y_pad = 20;

    constexpr float x_right = width - x_pad;
    constexpr float y_bottom = height - y_pad;
    constexpr float number_shift = 30;

    wave_height = props.depth * 1000;

    // Text
    ctx.font(Fonts::Norm, 25);
    ctx.fillStyle(Colours::Red);
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText("depth", x_right, y_bottom);

    ctx.fillStyle(Colours::Green);
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText("rate", x_pad, y_bottom);

    ctx.fillStyle(Colours::Yellow);
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText("feedback", x_right, y_pad);

    ctx.fillStyle(Colours::Blue);
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText("delay", x_pad, y_pad);

    // Numbers
    ctx.font(Fonts::Norm, 40);

    // chorus/RedValue/10
    ctx.fillStyle(Colours::Red.dim(1 - env_red()));
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(10000 * props.depth)), x_right, y_bottom - number_shift);

    // chorus/GreenValue/10
    ctx.fillStyle(Colours::Green.dim(1 - env_green()));
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(props.rate * 100)), x_pad, y_bottom - number_shift);

    // chorus/YellowValue/0
    ctx.fillStyle(Colours::Yellow.dim(1 - env_yellow()));
    ctx.textAlign(HorizontalAlign::Right, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(props.feedback * 100)), x_right, y_pad + number_shift);

    // chorus/BlueValue/1
    ctx.fillStyle(Colours::Blue.dim(1 - env_blue()));
    ctx.textAlign(HorizontalAlign::Left, VerticalAlign::Middle);
    ctx.fillText(fmt::format("{}", std::round(10000 * props.delay)), x_pad, y_pad + number_shift);

    //Heads
    constexpr float spacing_constant = 1000;
    constexpr int num_heads = 10;

    float spacing = spacing_constant * props.delay + 10;
    Point start = {120 - props.delay * 5000, 165};

    for (int i=num_heads; i>=1; i--) {
      float head_height = wave_height * gam::scl::sinP9(gam::scl::wrap(props.phase_value - 0.2f*(float)i, 1.f, -1.f));
      draw_background_head(ctx, {start.x + i*spacing, start.y + head_height}, colour_list[i], 1 - i*0.07);
    }
    draw_front_head(ctx, {start.x, start.y + wave_height * gam::scl::sinP9(props.phase_value)}, Colours::Blue, 1);

  }

  void ChorusScreen::draw_front_head(ui::vg::Canvas& ctx, Point p, Colour c, float scale)
  {
    // chorus/HeadMain
    ctx.beginPath();
    ctx.scaleTowards(scale, p);
    ctx.moveTo(p.x, p.y);
    ctx.lineTo(p.x, p.y - 173.0 + 153.6);
    ctx.bezierCurveTo(p.x + 121.4 - 130.8, p.y - 173.0 + 148.5, p.x + 115.0 - 130.8, p.y - 173.0 + 138.6, p.x + 115.0 - 130.8, p.y - 173.0 + 127.1);
    ctx.lineTo(p.x + 115.0 - 130.8, p.y - 173.0 + 107.3);
    ctx.bezierCurveTo(p.x + 115.0 - 130.8, p.y - 173.0 + 85.1, p.x + 133.0 - 130.8, p.y - 173.0 + 67.0, p.x + 155.2 - 130.8, p.y - 173.0 + 67.0);
    ctx.bezierCurveTo(p.x + 177.4 - 130.8, p.y - 173.0 + 67.0, p.x + 195.5 - 130.8, p.y - 173.0 + 85.1, p.x + 195.5 - 130.8, p.y - 173.0 + 107.3);
    ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 117.8);
    ctx.lineTo(p.x + 204.4 - 130.8, p.y - 173.0 + 130.0);
    ctx.bezierCurveTo(p.x + 205.4 - 130.8, p.y - 173.0 + 131.4, p.x + 205.1 - 130.8, p.y - 173.0 + 133.4, p.x + 203.7 - 130.8, p.y - 173.0 + 134.4);
    ctx.bezierCurveTo(p.x + 203.2 - 130.8, p.y - 173.0 + 134.8, p.x + 202.5 - 130.8, p.y - 173.0 + 135.0, p.x + 201.8 - 130.8, p.y - 173.0 + 135.0);
    ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 135.0);
    ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 152.4);
    ctx.bezierCurveTo(p.x + 195.5 - 130.8, p.y - 173.0 + 155.1, p.x + 193.3 - 130.8, p.y - 173.0 + 157.2, p.x + 190.7 - 130.8, p.y - 173.0 + 157.2);
    ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 157.2);
    ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 173.0);
    ctx.fill(Colours::Black);
    ctx.strokeStyle(c);
    ctx.stroke();

  }
  void ChorusScreen::draw_background_head(ui::vg::Canvas& ctx, Point p, Colour c, float scale)
  {
    ctx.group([&] {
      ctx.beginPath();
      ctx.scaleTowards(scale, {p.x, p.y + (67.f - 173.f) / 2.f});
      ctx.lineWidth(6 / scale);
      ctx.moveTo(p.x + 115.0 - 130.8, p.y - 173.0 + 127.1);
      ctx.lineTo(p.x + 115.0 - 130.8, p.y - 173.0 + 107.3);
      ctx.bezierCurveTo(p.x + 115.0 - 130.8, p.y - 173.0 + 85.1, p.x + 133.0 - 130.8, p.y - 173.0 + 67.0,
                        p.x + 155.2 - 130.8, p.y - 173.0 + 67.0);
      ctx.bezierCurveTo(p.x + 177.4 - 130.8, p.y - 173.0 + 67.0, p.x + 195.5 - 130.8, p.y - 173.0 + 85.1,
                        p.x + 195.5 - 130.8, p.y - 173.0 + 107.3);
      ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 117.8);
      ctx.lineTo(p.x + 204.4 - 130.8, p.y - 173.0 + 130.0);
      ctx.bezierCurveTo(p.x + 205.4 - 130.8, p.y - 173.0 + 131.4, p.x + 205.1 - 130.8, p.y - 173.0 + 133.4,
                        p.x + 203.7 - 130.8, p.y - 173.0 + 134.4);
      ctx.bezierCurveTo(p.x + 203.2 - 130.8, p.y - 173.0 + 134.8, p.x + 202.5 - 130.8, p.y - 173.0 + 135.0,
                        p.x + 201.8 - 130.8, p.y - 173.0 + 135.0);
      ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 135.0);
      ctx.lineTo(p.x + 195.5 - 130.8, p.y - 173.0 + 152.4);
      ctx.bezierCurveTo(p.x + 195.5 - 130.8, p.y - 173.0 + 155.1, p.x + 193.3 - 130.8, p.y - 173.0 + 157.2,
                        p.x + 190.7 - 130.8, p.y - 173.0 + 157.2);
      ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 157.2);
      ctx.lineTo(p.x + 179.7 - 130.8, p.y - 173.0 + 173.0);
      ctx.fill(Colours::Black);
      ctx.strokeStyle(c);
      ctx.stroke();
    });
  }

} // namespace otto::engines
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: colorlistener.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2003-04-24 13:33:02 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "classes/colorlistener.hxx"

//__________________________________________
// own includes

#ifndef __FRAMEWORK_THREADHELP_READGUARD_HXX_
#include <threadhelp/readguard.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
#include <threadhelp/writeguard.hxx>
#endif

//__________________________________________
// interface includes

#ifndef _COM_SUN_STAR_AWT_XWINDOWPEER_HPP_
#include <com/sun/star/awt/XWindowPeer.hpp>
#endif

#ifndef _COM_SUN_STAR_AWT_INVALIDATESTYLE_HPP_
#include <com/sun/star/awt/InvalidateStyle.hpp>
#endif

//__________________________________________
// other includes

#ifndef _RTL_USTRING_H_
#include <rtl/ustring.h>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
#include <toolkit/helper/vclunohelper.hxx>
#endif

#ifndef _SFXSMPLHINT_HXX
#include <svtools/smplhint.hxx>
#endif

#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif

//__________________________________________
// definition

namespace framework
{

DEFINE_XINTERFACE_1( ColorListener                             ,
                     OWeakObject                               ,
                     DIRECT_INTERFACE(css::lang::XEventListener))

//__________________________________________

/** initialize new instance of this class.

    It set the window, on which we must apply our detecte color changes.
    We start listening for changes and(!) window disposing here too.

    @attention  Some ressources will be created on demand!

    @param  xWindow
                reference to the window
 */

ColorListener::ColorListener( const css::uno::Reference< css::awt::XWindow >& xWindow )
    : ThreadHelpBase(&Application::GetSolarMutex())
    , SfxListener   (                             )
    , m_xWindow     (xWindow                      )
    , m_bListen     (sal_False                    )
    , m_pConfig     (NULL                         )
{
    impl_startListening();
    impl_applyColor(sal_True);
}

//__________________________________________

/** deinitialize new instance of this class.

    Because it's done at different places ... we use an impl method!

    see impl_die()
 */

ColorListener::~ColorListener()
{
    impl_die();
}

//__________________________________________

/** callback for color changes.

    @param  rBroadcaster
                should be our referenced config item (or any helper of it!)

    @param  rHint
                transport an ID, which identify the broadcasted message
 */

void ColorListener::Notify( SfxBroadcaster& rBroadCaster, const SfxHint& rHint )
{
    if (((SfxSimpleHint&)rHint).GetId()==SFX_HINT_COLORS_CHANGED)
        impl_applyColor(sal_True);
}

void ColorListener::impl_applyColor( sal_Bool bInvalidate )
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    if (m_pConfig)
    {
        css::uno::Reference< css::awt::XWindowPeer > xPeer(m_xWindow, css::uno::UNO_QUERY);
        ::svtools::ColorConfigValue aBackgroundColor = m_pConfig->GetColorValue( ::svtools::APPBACKGROUND );
        if (xPeer.is())
        {
            m_nColor = aBackgroundColor.nColor;
            xPeer->setBackground(m_nColor);
            if (bInvalidate)
            {
                xPeer->invalidate(
                    css::awt::InvalidateStyle::UPDATE | css::awt::InvalidateStyle::CHILDREN | css::awt::InvalidateStyle::NOTRANSPARENT );
            }
        }
    }

    aWriteLock.unlock();
    /* } SAFE */
}

//__________________________________________

/** callback for window destroy.

    We must react here automaticly and forget our window reference.
    We can die immediatly too. Because there is nothing to do any longer.

    @param  aEvent
                must referr to our window.

    @throw  ::com::sun::star::uno::RuntimeException
                if event source doesn't points to our internal saved window.
 */
void SAL_CALL ColorListener::disposing( const css::lang::EventObject& aEvent ) throw(css::uno::RuntimeException)
{
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    if (aEvent.Source!=m_xWindow)
        throw css::uno::RuntimeException(
            DECLARE_ASCII(""),
            css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY) );

    impl_die();

    aReadLock.unlock();
    /* } SAFE */
}

IMPL_LINK( ColorListener, impl_SettingsChanged, void*, pVoid )
{
    VclWindowEvent* pEvent = (VclWindowEvent*)pVoid;
    if (pEvent->GetId() != VCLEVENT_APPLICATION_DATACHANGED)
        return 0L;

    /* SAFE { */
    ReadGuard aReadLock(m_aLock);
    Window* pWindow = VCLUnoHelper::GetWindow(m_xWindow);
    if (!pWindow)
        return 0L;

    OutputDevice* pDevice = (OutputDevice*)pWindow;
    long nNewColor = (long)(pDevice->GetBackground().GetColor().GetColor());

    if (m_nColor != nNewColor)
        impl_applyColor(sal_False);
    aReadLock.unlock();
    /* } SAFE */

    return 0L;
}

//__________________________________________

/** starts listening for color changes and window destroy.

    We create the needed config singleton on demand here.
 */

void ColorListener::impl_startListening()
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    if (!m_bListen)
    {
        Application::AddEventListener( LINK( this, ColorListener, impl_SettingsChanged ) );

        if (!m_pConfig)
            m_pConfig = new ::svtools::ColorConfig();

        StartListening(*(SfxBroadcaster*)m_pConfig);

        css::uno::Reference< css::lang::XComponent > xDispose(m_xWindow, css::uno::UNO_QUERY);
        if (xDispose.is())
            xDispose->addEventListener( css::uno::Reference< css::lang::XEventListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY) );

        m_bListen = sal_True;
    }

    aWriteLock.unlock();
    /* } SAFE */
}

//__________________________________________

/** stops listening for color changes and window destroy.
 */
void ColorListener::impl_stopListening()
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    if (m_bListen)
    {
        Application::RemoveEventListener( LINK( this, ColorListener, impl_SettingsChanged ) );

        EndListeningAll();

        delete m_pConfig;
        m_pConfig = NULL;

        css::uno::Reference< css::lang::XComponent > xDispose(m_xWindow, css::uno::UNO_QUERY);
        if (xDispose.is())
            xDispose->removeEventListener( css::uno::Reference< css::lang::XEventListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY) );

        m_bListen = sal_False;
    }

    aWriteLock.unlock();
    /* } SAFE */
}

//__________________________________________

/** release all used references.

    Free all used memory and release any used references.
    Of course cancel all existing listener connections, to be
    shure never be called again.
 */
void ColorListener::impl_die()
{
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    // Attention: Deleting of our broadcaster will may force a Notify() call.
    // To supress that, we have to disable our listener connection first.
    impl_stopListening();
    m_xWindow = css::uno::Reference< css::awt::XWindow >();

    aReadLock.unlock();
    /* } SAFE */
}

} // namespace framework
<commit_msg>INTEGRATION: CWS fwkfinal2 (1.3.384); FILE MERGED 2005/03/17 09:25:32 as 1.3.384.1: #i44877# use new vcl notification about changed window color to bring a veto against external changes<commit_after>/*************************************************************************
 *
 *  $RCSfile: colorlistener.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-23 16:14:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "classes/colorlistener.hxx"

//__________________________________________
// own includes

#ifndef __FRAMEWORK_THREADHELP_READGUARD_HXX_
#include <threadhelp/readguard.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
#include <threadhelp/writeguard.hxx>
#endif

//__________________________________________
// interface includes

#ifndef _COM_SUN_STAR_AWT_XWINDOWPEER_HPP_
#include <com/sun/star/awt/XWindowPeer.hpp>
#endif

#ifndef _COM_SUN_STAR_AWT_INVALIDATESTYLE_HPP_
#include <com/sun/star/awt/InvalidateStyle.hpp>
#endif

//__________________________________________
// other includes

#ifndef _RTL_USTRING_H_
#include <rtl/ustring.h>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
#include <toolkit/helper/vclunohelper.hxx>
#endif

#ifndef _SFXSMPLHINT_HXX
#include <svtools/smplhint.hxx>
#endif

#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif

//__________________________________________
// definition

namespace framework
{

DEFINE_XINTERFACE_1( ColorListener                             ,
                     OWeakObject                               ,
                     DIRECT_INTERFACE(css::lang::XEventListener))

//__________________________________________

/** initialize new instance of this class.

    It set the window, on which we must apply our detecte color changes.
    We start listening for changes and(!) window disposing here too.

    @attention  Some ressources will be created on demand!

    @param  xWindow
                reference to the window
 */

ColorListener::ColorListener( const css::uno::Reference< css::awt::XWindow >& xWindow )
    : ThreadHelpBase(&Application::GetSolarMutex())
    , SfxListener   (                             )
    , m_xWindow     (xWindow                      )
    , m_bListen     (sal_False                    )
    , m_pConfig     (NULL                         )
{
    impl_startListening();
    impl_applyColor(sal_True);
}

//__________________________________________

/** deinitialize new instance of this class.

    Because it's done at different places ... we use an impl method!

    see impl_die()
 */

ColorListener::~ColorListener()
{
    impl_die();
}

//__________________________________________
/** callback if color config was changed.

    @param  rBroadcaster
            should be our referenced config item (or any helper of it!)

    @param  rHint
            transport an ID, which identify the broadcasted message
 */
void ColorListener::Notify(SfxBroadcaster& rBroadCaster, const SfxHint& rHint)
{
    if (((SfxSimpleHint&)rHint).GetId()==SFX_HINT_COLORS_CHANGED)
        impl_applyColor(sal_True);
}

//__________________________________________
/** callback if window color was changed by any other!
    We own this window .. and we are the only ones, which
    define the background color of this window.
 */
IMPL_LINK(ColorListener, impl_SettingsChanged, void*, pVoid)
{
    // ignore uninteressting notifications
    VclWindowEvent* pEvent = (VclWindowEvent*)pVoid;
    if (pEvent->GetId() != VCLEVENT_WINDOW_DATACHANGED)
        return 0L;

    // SAFE ->
    ReadGuard aReadLock(m_aLock);
    css::uno::Reference< css::awt::XWindow > xWindow       = m_xWindow;
    long                                     nCurrentColor = m_nColor ;
    aReadLock.unlock();
    // <- SAFE

    if (!xWindow.is())
        return 0L;

    Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
    if (!pWindow)
        return 0L;

    OutputDevice* pDevice   = (OutputDevice*)pWindow;
    long          nNewColor = (long)(pDevice->GetBackground().GetColor().GetColor());

    // Was window background changed?
    // NO  -> do nothing
    // YES -> apply our color!
    if (nCurrentColor != nNewColor)
        impl_applyColor(sal_False);

    return 0L;
}

//__________________________________________
/** set a new background color (retrieved from the configuration)
    on the window.

    @param  bInvalidate
            If it's setto TRUE it forces a synchronous update
            of the window background.
 */
void ColorListener::impl_applyColor(sal_Bool bInvalidate)
{
    // SAFE ->
    WriteGuard aWriteLock(m_aLock);

    if (!m_pConfig)
        return;
    ::svtools::ColorConfigValue aBackgroundColor = m_pConfig->GetColorValue(::svtools::APPBACKGROUND);
    m_nColor = aBackgroundColor.nColor;

    css::uno::Reference< css::awt::XWindowPeer > xPeer(m_xWindow, css::uno::UNO_QUERY);

    aWriteLock.unlock();
    // <- SAFE

    if (!xPeer.is())
        return;

    xPeer->setBackground(aBackgroundColor.nColor);
    if (bInvalidate)
    {
        xPeer->invalidate(
            css::awt::InvalidateStyle::UPDATE        |
            css::awt::InvalidateStyle::CHILDREN      |
            css::awt::InvalidateStyle::NOTRANSPARENT );
    }
}

//__________________________________________

/** callback for window destroy.

    We must react here automaticly and forget our window reference.
    We can die immediatly too. Because there is nothing to do any longer.

    @param  aEvent
                must referr to our window.

    @throw  ::com::sun::star::uno::RuntimeException
                if event source doesn't points to our internal saved window.
 */
void SAL_CALL ColorListener::disposing( const css::lang::EventObject& aEvent ) throw(css::uno::RuntimeException)
{
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    if (aEvent.Source!=m_xWindow)
        throw css::uno::RuntimeException(
            DECLARE_ASCII(""),
            css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY) );

    impl_die();

    aReadLock.unlock();
    /* } SAFE */
}

//__________________________________________

/** starts listening for color changes and window destroy.

    We create the needed config singleton on demand here.
 */

void ColorListener::impl_startListening()
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    if (!m_bListen)
    {
        Window* pWindow = VCLUnoHelper::GetWindow(m_xWindow);
        if (pWindow)
            pWindow->AddEventListener(LINK(this, ColorListener, impl_SettingsChanged));

        if (!m_pConfig)
            m_pConfig = new ::svtools::ColorConfig();

        StartListening(*(SfxBroadcaster*)m_pConfig);

        css::uno::Reference< css::lang::XComponent > xDispose(m_xWindow, css::uno::UNO_QUERY);
        if (xDispose.is())
            xDispose->addEventListener( css::uno::Reference< css::lang::XEventListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY) );

        m_bListen = sal_True;
    }

    aWriteLock.unlock();
    /* } SAFE */
}

//__________________________________________

/** stops listening for color changes and window destroy.
 */
void ColorListener::impl_stopListening()
{
    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    if (m_bListen)
    {
        Window* pWindow = VCLUnoHelper::GetWindow(m_xWindow);
        if (pWindow)
            pWindow->RemoveEventListener( LINK( this, ColorListener, impl_SettingsChanged ) );

        EndListeningAll();

        delete m_pConfig;
        m_pConfig = NULL;

        css::uno::Reference< css::lang::XComponent > xDispose(m_xWindow, css::uno::UNO_QUERY);
        if (xDispose.is())
            xDispose->removeEventListener( css::uno::Reference< css::lang::XEventListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY) );

        m_bListen = sal_False;
    }

    aWriteLock.unlock();
    /* } SAFE */
}

//__________________________________________

/** release all used references.

    Free all used memory and release any used references.
    Of course cancel all existing listener connections, to be
    shure never be called again.
 */
void ColorListener::impl_die()
{
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    // Attention: Deleting of our broadcaster will may force a Notify() call.
    // To supress that, we have to disable our listener connection first.
    impl_stopListening();
    m_xWindow = css::uno::Reference< css::awt::XWindow >();

    aReadLock.unlock();
    /* } SAFE */
}

} // namespace framework
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <set>
#include <algorithm>

std::set<int> split_list(std::string str)
{
    std::stringstream stream(str);
    std::string buffer;
    std::set<int> s;
    while(getline(stream, buffer, ','))
    {
        s.insert(std::stoi(buffer));
    }
    return s;

}
int main(int argc, char const *argv[])
{
    std::string line;
    std::ifstream file(argv[1]);
    while(getline(file, line))
    {
        if(!line.empty())
        {
            std::stringstream stream(line);
            std::string first_list, second_list;
            getline(stream, first_list, ';');
            getline(stream, second_list);
            std::set<int> first = split_list(first_list);
            std::set<int> second = split_list(second_list);
            std::vector<int> intersection;
            std::set_intersection(
                first.begin(),
                first.end(),
                second.begin(),
                second.end(),
                std::back_inserter(intersection)
                );
            if(!intersection.empty())
            {
                for(int i = 0; i < intersection.size(); i++)
                {
                    std::cout << intersection[i];
                    if(i < intersection.size() - 1)
                    {
                        std::cout << ",";
                    }
                }
                std::cout << std::endl;
            }
            else
            {
                std::cout <<  std::endl;
            }
        }
    }
    file.close();
    return 0;
}<commit_msg>refactor duplicate cout statements<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <set>
#include <algorithm>

std::set<int> split_list(std::string str)
{
    std::stringstream stream(str);
    std::string buffer;
    std::set<int> s;
    while(getline(stream, buffer, ','))
    {
        s.insert(std::stoi(buffer));
    }
    return s;

}
int main(int argc, char const *argv[])
{
    std::string line;
    std::ifstream file(argv[1]);
    while(getline(file, line))
    {
        if(!line.empty())
        {
            std::stringstream stream(line);
            std::string first_list, second_list;
            getline(stream, first_list, ';');
            getline(stream, second_list);
            std::set<int> first = split_list(first_list);
            std::set<int> second = split_list(second_list);
            std::vector<int> intersection;
            std::set_intersection(
                first.begin(),
                first.end(),
                second.begin(),
                second.end(),
                std::back_inserter(intersection)
                );
            if(!intersection.empty())
            {
                for(int i = 0; i < intersection.size(); i++)
                {
                    std::cout << intersection[i];
                    if(i < intersection.size() - 1)
                    {
                        std::cout << ",";
                    }
                }
            }
            std::cout <<  std::endl;
        }
    }
    file.close();
    return 0;
}
<|endoftext|>


<commit_before>/*
 * FreeGaitActionServer.cpp
 *
 *  Created on: Feb 6, 2015
 *      Author: Péter Fankhauser
 *   Institute: ETH Zurich, Autonomous Systems Lab
 */

#include <free_gait_ros/FreeGaitActionServer.hpp>
#include <free_gait_core/free_gait_core.hpp>

// ROS
#include <free_gait_msgs/ExecuteStepsFeedback.h>
#include <free_gait_msgs/ExecuteStepsResult.h>

#include <iostream>

namespace free_gait {

FreeGaitActionServer::FreeGaitActionServer(ros::NodeHandle nodeHandle, const std::string& name,
                                           std::shared_ptr<Executor> executor, std::shared_ptr<AdapterBase> adapter)
    : nodeHandle_(nodeHandle),
      name_(name),
      executor_(executor),
      rosConverter_(adapter),
      server_(nodeHandle_, name_, false),
      isPreempting_(false)
{
}

FreeGaitActionServer::~FreeGaitActionServer()
{
}

void FreeGaitActionServer::initialize()
{
  server_.registerGoalCallback(boost::bind(&FreeGaitActionServer::goalCallback, this));
  server_.registerPreemptCallback(boost::bind(&FreeGaitActionServer::preemptCallback, this));
  server_.start();
  ROS_INFO_STREAM("Started " << name_ << " action server.");
}

void FreeGaitActionServer::update()
{
  if (!server_.isActive()) return;
  Executor::Lock lock(executor_->getMutex());
  bool stepQueueEmpty = executor_->getQueue().empty();
  lock.unlock();
  if (stepQueueEmpty) {
    // Succeeded.
    if (isPreempting_) {
      // Preempted.
      setPreempted();
    } else {
      setSucceeded();
    }
  } else {
    // Ongoing.
    lock.lock();
    if (executor_->getQueue().active()) publishFeedback();
    lock.unlock();
  }
}

void FreeGaitActionServer::shutdown()
{
  server_.shutdown();
}

void FreeGaitActionServer::goalCallback()
{
  ROS_INFO("Received goal for StepAction.");
//  if (server_.isActive()) server_.setRejected();

  const auto goal = server_.acceptNewGoal();
  Executor::Lock lock(executor_->getMutex());
  lock.unlock();
  for (auto& stepMessage : goal->steps) {
    Step step;
    rosConverter_.fromMessage(stepMessage, step);
    lock.lock();
    executor_->getQueue().add(step);
    lock.unlock();
  }
}

void FreeGaitActionServer::preemptCallback()
{
  ROS_INFO("StepAction is requested to preempt.");
  Executor::Lock lock(executor_->getMutex());
  if (executor_->getQueue().empty()) return;
  if (executor_->getQueue().size() <= 1) return;
  executor_->getQueue().clearNextSteps();
  isPreempting_ = true;
}

void FreeGaitActionServer::publishFeedback()
{
  free_gait_msgs::ExecuteStepsFeedback feedback;
  Executor::Lock lock(executor_->getMutex());
  if (executor_->getQueue().empty()) return;
  // TODO Add feedback if executor multi-threading is not yet ready.
  const auto& step = executor_->getQueue().getCurrentStep();
  feedback.queue_size = executor_->getQueue().size();

  if (executor_->getAdapter().isExecutionOk() == false) {
    feedback.status = free_gait_msgs::ExecuteStepsFeedback::PROGRESS_PAUSED;
    feedback.description = "Paused.";
  } else {
      feedback.status = free_gait_msgs::ExecuteStepsFeedback::PROGRESS_EXECUTING;
      feedback.description = "Executing.";
//      default:
//        feedback.status = free_gait_msgs::ExecuteStepsFeedback::PROGRESS_UNKNOWN;
//        feedback.description = "Unknown.";
//        break;
  }

  feedback.duration = ros::Duration(step.getTotalDuration());
  feedback.phase = step.getTotalPhase();
  for (const auto& leg : executor_->getAdapter().getLimbs()) {
    if (step.hasLegMotion(leg)) {
      const std::string legName(executor_->getAdapter().getLimbStringFromLimbEnum(leg));
      feedback.swing_leg_names.push_back(legName);
    }
  }
  lock.unlock();
  server_.publishFeedback(feedback);
}

void FreeGaitActionServer::setSucceeded()
{
  ROS_INFO("StepAction succeeded.");
  free_gait_msgs::ExecuteStepsResult result;
  result.status = free_gait_msgs::ExecuteStepsResult::RESULT_REACHED;
  server_.setSucceeded(result, "Step action has been reached.");
}

void FreeGaitActionServer::setPreempted()
{
  ROS_INFO("StepAction preempted.");
  free_gait_msgs::ExecuteStepsResult result;
  result.status = free_gait_msgs::ExecuteStepsResult::RESULT_FAILED;
  server_.setPreempted(result, "Step action has been preempted.");
  isPreempting_ = false;
}

void FreeGaitActionServer::setAborted()
{
  ROS_INFO("StepAction aborted.");
  free_gait_msgs::ExecuteStepsResult result;
  result.status = free_gait_msgs::ExecuteStepsResult::RESULT_FAILED;
  server_.setAborted(result, "Step action has failed.");
}

} /* namespace */
<commit_msg>Added some debugging output.<commit_after>/*
 * FreeGaitActionServer.cpp
 *
 *  Created on: Feb 6, 2015
 *      Author: Péter Fankhauser
 *   Institute: ETH Zurich, Autonomous Systems Lab
 */

#include <free_gait_ros/FreeGaitActionServer.hpp>
#include <free_gait_core/free_gait_core.hpp>

// ROS
#include <free_gait_msgs/ExecuteStepsFeedback.h>
#include <free_gait_msgs/ExecuteStepsResult.h>

#include <iostream>

namespace free_gait {

FreeGaitActionServer::FreeGaitActionServer(ros::NodeHandle nodeHandle, const std::string& name,
                                           std::shared_ptr<Executor> executor, std::shared_ptr<AdapterBase> adapter)
    : nodeHandle_(nodeHandle),
      name_(name),
      executor_(executor),
      rosConverter_(adapter),
      server_(nodeHandle_, name_, false),
      isPreempting_(false)
{
}

FreeGaitActionServer::~FreeGaitActionServer()
{
}

void FreeGaitActionServer::initialize()
{
  server_.registerGoalCallback(boost::bind(&FreeGaitActionServer::goalCallback, this));
  server_.registerPreemptCallback(boost::bind(&FreeGaitActionServer::preemptCallback, this));
  server_.start();
  ROS_INFO_STREAM("Started " << name_ << " action server.");
}

void FreeGaitActionServer::update()
{
  ROS_INFO("FreeGaitActionServer::update START");
  if (!server_.isActive()) return;
  Executor::Lock lock(executor_->getMutex());
  bool stepQueueEmpty = executor_->getQueue().empty();
  lock.unlock();
  if (stepQueueEmpty) {
    // Succeeded.
    if (isPreempting_) {
      // Preempted.
      setPreempted();
    } else {
      setSucceeded();
    }
  } else {
    // Ongoing.
    lock.lock();
    if (executor_->getQueue().active()) publishFeedback();
    lock.unlock();
  }
  ROS_INFO("FreeGaitActionServer::update END");
}

void FreeGaitActionServer::shutdown()
{
  server_.shutdown();
}

void FreeGaitActionServer::goalCallback()
{
  ROS_INFO("goalCallback START");
  ROS_INFO("Received goal for StepAction.");
//  if (server_.isActive()) server_.setRejected();

  const auto goal = server_.acceptNewGoal();
  Executor::Lock lock(executor_->getMutex());
  lock.unlock();
  for (auto& stepMessage : goal->steps) {
    Step step;
    rosConverter_.fromMessage(stepMessage, step);
    lock.lock();
    executor_->getQueue().add(step);
    lock.unlock();
  }
  ROS_INFO("goalCallback END");
}

void FreeGaitActionServer::preemptCallback()
{
  ROS_INFO("StepAction is requested to preempt.");
  Executor::Lock lock(executor_->getMutex());
  if (executor_->getQueue().empty()) return;
  if (executor_->getQueue().size() <= 1) return;
  executor_->getQueue().clearNextSteps();
  isPreempting_ = true;
}

void FreeGaitActionServer::publishFeedback()
{
  ROS_INFO("publishFeedback START");
  free_gait_msgs::ExecuteStepsFeedback feedback;
  Executor::Lock lock(executor_->getMutex());
  if (executor_->getQueue().empty()) return;
  // TODO Add feedback if executor multi-threading is not yet ready.
  const auto& step = executor_->getQueue().getCurrentStep();
  feedback.queue_size = executor_->getQueue().size();

  if (executor_->getAdapter().isExecutionOk() == false) {
    feedback.status = free_gait_msgs::ExecuteStepsFeedback::PROGRESS_PAUSED;
    feedback.description = "Paused.";
  } else {
      feedback.status = free_gait_msgs::ExecuteStepsFeedback::PROGRESS_EXECUTING;
      feedback.description = "Executing.";
//      default:
//        feedback.status = free_gait_msgs::ExecuteStepsFeedback::PROGRESS_UNKNOWN;
//        feedback.description = "Unknown.";
//        break;
  }

  feedback.duration = ros::Duration(step.getTotalDuration());
  feedback.phase = step.getTotalPhase();
  for (const auto& leg : executor_->getAdapter().getLimbs()) {
    if (step.hasLegMotion(leg)) {
      const std::string legName(executor_->getAdapter().getLimbStringFromLimbEnum(leg));
      feedback.swing_leg_names.push_back(legName);
    }
  }
  lock.unlock();
  server_.publishFeedback(feedback);
  ROS_INFO("publishFeedback END");
}

void FreeGaitActionServer::setSucceeded()
{
  ROS_INFO("StepAction succeeded.");
  free_gait_msgs::ExecuteStepsResult result;
  result.status = free_gait_msgs::ExecuteStepsResult::RESULT_REACHED;
  server_.setSucceeded(result, "Step action has been reached.");
}

void FreeGaitActionServer::setPreempted()
{
  ROS_INFO("StepAction preempted.");
  free_gait_msgs::ExecuteStepsResult result;
  result.status = free_gait_msgs::ExecuteStepsResult::RESULT_FAILED;
  server_.setPreempted(result, "Step action has been preempted.");
  isPreempting_ = false;
}

void FreeGaitActionServer::setAborted()
{
  ROS_INFO("StepAction aborted.");
  free_gait_msgs::ExecuteStepsResult result;
  result.status = free_gait_msgs::ExecuteStepsResult::RESULT_FAILED;
  server_.setAborted(result, "Step action has failed.");
}

} /* namespace */
<|endoftext|>


<commit_before>//===- Errno.cpp - errno support --------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the errno wrappers.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Errno.h"
#include "llvm/Config/config.h"     // Get autoconf configuration settings

#if HAVE_STRING_H
#include <string.h>

#if HAVE_ERRNO_H
#include <errno.h>
#endif

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

namespace llvm {
namespace sys {

#if HAVE_ERRNO_H
std::string StrError() {
  return StrError(errno);
}
#endif  // HAVE_ERRNO_H

std::string StrError(int errnum) {
  const int MaxErrStrLen = 2000;
  char buffer[MaxErrStrLen];
  buffer[0] = '\0';
  char* str = buffer;
#ifdef HAVE_STRERROR_R
  // strerror_r is thread-safe.
  if (errnum)
# if defined(__GLIBC__) && defined(_GNU_SOURCE)
    // glibc defines its own incompatible version of strerror_r
    // which may not use the buffer supplied.
    str = strerror_r(errnum,buffer,MaxErrStrLen-1);
# else
    strerror_r(errnum,buffer,MaxErrStrLen-1);
# endif
#elif HAVE_DECL_STRERROR_S // "Windows Secure API"
    if (errnum)
      strerror_s(buffer, errnum);
#elif defined(HAVE_STRERROR)
  // Copy the thread un-safe result of strerror into
  // the buffer as fast as possible to minimize impact
  // of collision of strerror in multiple threads.
  if (errnum)
    strncpy(buffer,strerror(errnum),MaxErrStrLen-1);
  buffer[MaxErrStrLen-1] = '\0';
#else
  // Strange that this system doesn't even have strerror
  // but, oh well, just use a generic message
  sprintf(buffer, "Error #%d", errnum);
#endif
  return str;
}

}  // namespace sys
}  // namespace llvm

#endif  // HAVE_STRING_H
<commit_msg>llvm/lib/Support/Errno.cpp: [Win32] Fix usage of strerror_s().<commit_after>//===- Errno.cpp - errno support --------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the errno wrappers.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Errno.h"
#include "llvm/Config/config.h"     // Get autoconf configuration settings

#if HAVE_STRING_H
#include <string.h>

#if HAVE_ERRNO_H
#include <errno.h>
#endif

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

namespace llvm {
namespace sys {

#if HAVE_ERRNO_H
std::string StrError() {
  return StrError(errno);
}
#endif  // HAVE_ERRNO_H

std::string StrError(int errnum) {
  const int MaxErrStrLen = 2000;
  char buffer[MaxErrStrLen];
  buffer[0] = '\0';
  char* str = buffer;
#ifdef HAVE_STRERROR_R
  // strerror_r is thread-safe.
  if (errnum)
# if defined(__GLIBC__) && defined(_GNU_SOURCE)
    // glibc defines its own incompatible version of strerror_r
    // which may not use the buffer supplied.
    str = strerror_r(errnum,buffer,MaxErrStrLen-1);
# else
    strerror_r(errnum,buffer,MaxErrStrLen-1);
# endif
#elif HAVE_DECL_STRERROR_S // "Windows Secure API"
    if (errnum)
      strerror_s(buffer, MaxErrStrLen - 1, errnum);
#elif defined(HAVE_STRERROR)
  // Copy the thread un-safe result of strerror into
  // the buffer as fast as possible to minimize impact
  // of collision of strerror in multiple threads.
  if (errnum)
    strncpy(buffer,strerror(errnum),MaxErrStrLen-1);
  buffer[MaxErrStrLen-1] = '\0';
#else
  // Strange that this system doesn't even have strerror
  // but, oh well, just use a generic message
  sprintf(buffer, "Error #%d", errnum);
#endif
  return str;
}

}  // namespace sys
}  // namespace llvm

#endif  // HAVE_STRING_H
<|endoftext|>


<commit_before>#include <xzero/executor/NativeScheduler.h>
#include <xzero/RuntimeError.h>
#include <xzero/WallClock.h>
#include <xzero/sysconfig.h>
#include <algorithm>
#include <vector>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>

namespace xzero {

#define PIPE_READ_END  0
#define PIPE_WRITE_END 1

/**
 * XXX
 * - registering a key should be *ONESHOT* and *Edge Triggered*
 * - rename NativeScheduler to SimpleScheduler
 *
 * XXX LinuxScheduler
 * - epoll fuer i/o notification
 * - eventfd for wakeup implementation
 * - timerfd_* for timer impl
 */

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock,
    std::function<void()> preInvoke,
    std::function<void()> postInvoke)
    : Scheduler(std::move(errorLogger)),
      clock_(clock ? clock : WallClock::system()),
      lock_(),
      wakeupPipe_(),
      onPreInvokePending_(preInvoke),
      onPostInvokePending_(postInvoke) {
  if (pipe(wakeupPipe_) < 0) {
    throw SYSTEM_ERROR(errno);
  }
  fcntl(wakeupPipe_[0], F_SETFL, O_NONBLOCK);
  fcntl(wakeupPipe_[1], F_SETFL, O_NONBLOCK);
}

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock)
    : NativeScheduler(errorLogger, clock, nullptr, nullptr) {
}

NativeScheduler::NativeScheduler()
    : NativeScheduler(nullptr, nullptr, nullptr, nullptr) {
}

NativeScheduler::~NativeScheduler() {
  ::close(wakeupPipe_[PIPE_READ_END]);
  ::close(wakeupPipe_[PIPE_WRITE_END]);
}

void NativeScheduler::execute(Task&& task) {
  {
    std::lock_guard<std::mutex> lk(lock_);
    tasks_.push_back(task);
  }
  breakLoop();
}

std::string NativeScheduler::toString() const {
  return "NativeScheduler";
}

Scheduler::HandleRef NativeScheduler::executeAfter(TimeSpan delay, Task task) {
  auto onCancel = [this](Handle* handle) {
    removeFromTimersList(handle);
  };

  return insertIntoTimersList(clock_->get() + delay,
                              std::make_shared<Handle>(task, onCancel));
}

Scheduler::HandleRef NativeScheduler::executeAt(DateTime when, Task task) {
  return insertIntoTimersList(
      when,
      std::make_shared<Handle>(task,
                               std::bind(&NativeScheduler::removeFromTimersList,
                                         this,
                                         std::placeholders::_1)));
}

Scheduler::HandleRef NativeScheduler::insertIntoTimersList(DateTime dt,
                                                           HandleRef handle) {
  Timer t = { dt, handle };

  std::lock_guard<std::mutex> lk(lock_);

  auto i = timers_.end();
  auto e = timers_.begin();

  while (i != e) {
    i--;
    const Timer& current = *i;
    if (current.when >= t.when) {
      timers_.insert(i, t);
      return handle;
    }
  }

  timers_.push_front(t);
  return handle;
}

void NativeScheduler::removeFromTimersList(Handle* handle) {
  std::lock_guard<std::mutex> lk(lock_);

  for (auto i = timers_.begin(), e = timers_.end(); i != e; ++i) {
    if (i->handle.get() == handle) {
      timers_.erase(i);
      break;
    }
  }
}

void NativeScheduler::collectTimeouts() {
  const DateTime now = clock_->get();

  std::lock_guard<std::mutex> lk(lock_);

  for (;;) {
    if (timers_.empty())
      break;

    const Timer& job = timers_.front();

    if (job.when > now)
      break;

    tasks_.push_back(job.handle->getAction());
    timers_.pop_front();
  }
}

inline Scheduler::HandleRef registerInterest(
    std::mutex* registryLock,
    std::list<std::pair<int, Scheduler::HandleRef>>* registry,
    int fd,
    Executor::Task task) {

  auto onCancel = [=](Scheduler::Handle* h) {
    std::lock_guard<std::mutex> lk(*registryLock);
    for (auto i: *registry) {
      if (i.second.get() == h) {
        return registry->remove(i);
      }
    }
  };

  std::lock_guard<std::mutex> lk(*registryLock);
  auto handle = std::make_shared<Scheduler::Handle>(task, onCancel);
  registry->push_back(std::make_pair(fd, handle));

  return handle;
}

Scheduler::HandleRef NativeScheduler::executeOnReadable(int fd, Task task) {
  return registerInterest(&lock_, &readers_, fd, task);
}

Scheduler::HandleRef NativeScheduler::executeOnWritable(int fd, Task task) {
  return registerInterest(&lock_, &writers_, fd, task);
}

inline void collectActiveHandles(
    std::list<std::pair<int, Scheduler::HandleRef>>* interests,
    fd_set* fdset,
    std::vector<Scheduler::HandleRef>* result) {

  auto i = interests->begin();
  auto e = interests->end();

  while (i != e) {
    if (FD_ISSET(i->first, fdset)) {
      result->push_back(i->second);
      i = interests->erase(i);
    } else {
      i++;
    }
  }
}

size_t NativeScheduler::timerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return timers_.size();
}

size_t NativeScheduler::readerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return readers_.size();
}

size_t NativeScheduler::writerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return writers_.size();
}

void NativeScheduler::runLoopOnce() {
  fd_set input, output, error;
  FD_ZERO(&input);
  FD_ZERO(&output);
  FD_ZERO(&error);

  int wmark = 0;
  timeval tv;

  {
    std::lock_guard<std::mutex> lk(lock_);

    for (auto i: readers_) {
      FD_SET(i.first, &input);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    for (auto i: writers_) {
      FD_SET(i.first, &output);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    const TimeSpan nextTimeout = !tasks_.empty()
                               ? TimeSpan::Zero
                               : !timers_.empty()
                                 ? timers_.front().when - clock_->get()
                                 : TimeSpan::fromSeconds(4);

    tv.tv_sec = static_cast<time_t>(nextTimeout.totalSeconds()),
    tv.tv_usec = nextTimeout.microseconds();
  }

  FD_SET(wakeupPipe_[PIPE_READ_END], &input);

  int rv;
  do rv = ::select(wmark + 1, &input, &output, &error, &tv);
  while (rv < 0 && errno == EINTR);

  if (rv < 0)
    throw SYSTEM_ERROR(errno);

  if (FD_ISSET(wakeupPipe_[PIPE_READ_END], &input)) {
    bool consumeMore = true;
    while (consumeMore) {
      char buf[sizeof(int) * 128];
      consumeMore = ::read(wakeupPipe_[PIPE_READ_END], buf, sizeof(buf)) > 0;
    }
  }

  collectTimeouts();

  std::vector<HandleRef> activeHandles;
  activeHandles.reserve(rv);

  std::deque<Task> activeTasks;
  {
    std::lock_guard<std::mutex> lk(lock_);

    collectActiveHandles(&readers_, &input, &activeHandles);
    collectActiveHandles(&writers_, &output, &activeHandles);
    activeTasks = std::move(tasks_);
  }

  safeCall(onPreInvokePending_);
  safeCallEach(activeHandles);
  safeCallEach(activeTasks);
  safeCall(onPostInvokePending_);
}

void NativeScheduler::breakLoop() {
  int dummy = 42;
  ::write(wakeupPipe_[PIPE_WRITE_END], &dummy, sizeof(dummy));
}

} // namespace xzero
<commit_msg>NativeScheduler: attempt to remove the race in cancel() operation<commit_after>#include <xzero/executor/NativeScheduler.h>
#include <xzero/RuntimeError.h>
#include <xzero/WallClock.h>
#include <xzero/sysconfig.h>
#include <algorithm>
#include <vector>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>

namespace xzero {

#define PIPE_READ_END  0
#define PIPE_WRITE_END 1

/**
 * XXX
 * - registering a key should be *ONESHOT* and *Edge Triggered*
 * - rename NativeScheduler to SimpleScheduler
 *
 * XXX LinuxScheduler
 * - epoll fuer i/o notification
 * - eventfd for wakeup implementation
 * - timerfd_* for timer impl
 */

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock,
    std::function<void()> preInvoke,
    std::function<void()> postInvoke)
    : Scheduler(std::move(errorLogger)),
      clock_(clock ? clock : WallClock::system()),
      lock_(),
      wakeupPipe_(),
      onPreInvokePending_(preInvoke),
      onPostInvokePending_(postInvoke) {
  if (pipe(wakeupPipe_) < 0) {
    throw SYSTEM_ERROR(errno);
  }
  fcntl(wakeupPipe_[0], F_SETFL, O_NONBLOCK);
  fcntl(wakeupPipe_[1], F_SETFL, O_NONBLOCK);
}

NativeScheduler::NativeScheduler(
    std::function<void(const std::exception&)> errorLogger,
    WallClock* clock)
    : NativeScheduler(errorLogger, clock, nullptr, nullptr) {
}

NativeScheduler::NativeScheduler()
    : NativeScheduler(nullptr, nullptr, nullptr, nullptr) {
}

NativeScheduler::~NativeScheduler() {
  ::close(wakeupPipe_[PIPE_READ_END]);
  ::close(wakeupPipe_[PIPE_WRITE_END]);
}

void NativeScheduler::execute(Task&& task) {
  {
    std::lock_guard<std::mutex> lk(lock_);
    tasks_.push_back(task);
  }
  breakLoop();
}

std::string NativeScheduler::toString() const {
  return "NativeScheduler";
}

Scheduler::HandleRef NativeScheduler::executeAfter(TimeSpan delay, Task task) {
  auto onCancel = [this](Handle* handle) {
    removeFromTimersList(handle);
  };

  return insertIntoTimersList(clock_->get() + delay,
                              std::make_shared<Handle>(task, onCancel));
}

Scheduler::HandleRef NativeScheduler::executeAt(DateTime when, Task task) {
  return insertIntoTimersList(
      when,
      std::make_shared<Handle>(task,
                               std::bind(&NativeScheduler::removeFromTimersList,
                                         this,
                                         std::placeholders::_1)));
}

Scheduler::HandleRef NativeScheduler::insertIntoTimersList(DateTime dt,
                                                           HandleRef handle) {
  Timer t = { dt, handle };

  std::lock_guard<std::mutex> lk(lock_);

  auto i = timers_.end();
  auto e = timers_.begin();

  while (i != e) {
    i--;
    const Timer& current = *i;
    if (current.when >= t.when) {
      timers_.insert(i, t);
      return handle;
    }
  }

  timers_.push_front(t);
  return handle;
}

void NativeScheduler::removeFromTimersList(Handle* handle) {
  std::lock_guard<std::mutex> lk(lock_);

  for (auto i = timers_.begin(), e = timers_.end(); i != e; ++i) {
    if (i->handle.get() == handle) {
      timers_.erase(i);
      break;
    }
  }
}

void NativeScheduler::collectTimeouts(std::vector<HandleRef>* result) {
  const DateTime now = clock_->get();

  std::lock_guard<std::mutex> lk(lock_);

  for (;;) {
    if (timers_.empty())
      break;

    const Timer& job = timers_.front();

    if (job.when > now)
      break;

    result->push_back(job.handle);
    timers_.pop_front();
  }
}

inline Scheduler::HandleRef registerInterest(
    std::mutex* registryLock,
    std::list<std::pair<int, Scheduler::HandleRef>>* registry,
    int fd,
    Executor::Task task) {

  auto onCancel = [=](Scheduler::Handle* h) {
    std::lock_guard<std::mutex> lk(*registryLock);
    for (auto i: *registry) {
      if (i.second.get() == h) {
        return registry->remove(i);
      }
    }
  };

  std::lock_guard<std::mutex> lk(*registryLock);
  auto handle = std::make_shared<Scheduler::Handle>(task, onCancel);
  registry->push_back(std::make_pair(fd, handle));

  return handle;
}

Scheduler::HandleRef NativeScheduler::executeOnReadable(int fd, Task task) {
  return registerInterest(&lock_, &readers_, fd, task);
}

Scheduler::HandleRef NativeScheduler::executeOnWritable(int fd, Task task) {
  return registerInterest(&lock_, &writers_, fd, task);
}

inline void collectActiveHandles(
    std::list<std::pair<int, Scheduler::HandleRef>>* interests,
    fd_set* fdset,
    std::vector<Scheduler::HandleRef>* result) {

  auto i = interests->begin();
  auto e = interests->end();

  while (i != e) {
    if (FD_ISSET(i->first, fdset)) {
      result->push_back(i->second);
      i = interests->erase(i);
    } else {
      i++;
    }
  }
}

size_t NativeScheduler::timerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return timers_.size();
}

size_t NativeScheduler::readerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return readers_.size();
}

size_t NativeScheduler::writerCount() {
  std::lock_guard<std::mutex> lk(lock_);
  return writers_.size();
}

void NativeScheduler::runLoopOnce() {
  fd_set input, output, error;
  FD_ZERO(&input);
  FD_ZERO(&output);
  FD_ZERO(&error);

  int wmark = 0;
  timeval tv;

  {
    std::lock_guard<std::mutex> lk(lock_);

    for (auto i: readers_) {
      FD_SET(i.first, &input);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    for (auto i: writers_) {
      FD_SET(i.first, &output);
      if (i.first > wmark) {
        wmark = i.first;
      }
    }

    const TimeSpan nextTimeout = !tasks_.empty()
                               ? TimeSpan::Zero
                               : !timers_.empty()
                                 ? timers_.front().when - clock_->get()
                                 : TimeSpan::fromSeconds(4);

    tv.tv_sec = static_cast<time_t>(nextTimeout.totalSeconds()),
    tv.tv_usec = nextTimeout.microseconds();
  }

  FD_SET(wakeupPipe_[PIPE_READ_END], &input);

  int rv;
  do rv = ::select(wmark + 1, &input, &output, &error, &tv);
  while (rv < 0 && errno == EINTR);

  if (rv < 0)
    throw SYSTEM_ERROR(errno);

  if (FD_ISSET(wakeupPipe_[PIPE_READ_END], &input)) {
    bool consumeMore = true;
    while (consumeMore) {
      char buf[sizeof(int) * 128];
      consumeMore = ::read(wakeupPipe_[PIPE_READ_END], buf, sizeof(buf)) > 0;
    }
  }

  std::vector<HandleRef> activeHandles;
  activeHandles.reserve(rv);

  collectTimeouts(&activeHandles);

  std::deque<Task> activeTasks;
  {
    std::lock_guard<std::mutex> lk(lock_);

    collectActiveHandles(&readers_, &input, &activeHandles);
    collectActiveHandles(&writers_, &output, &activeHandles);
    activeTasks = std::move(tasks_);
  }

  safeCall(onPreInvokePending_);
  safeCallEach(activeHandles);
  safeCallEach(activeTasks);
  safeCall(onPostInvokePending_);
}

void NativeScheduler::breakLoop() {
  int dummy = 42;
  ::write(wakeupPipe_[PIPE_WRITE_END], &dummy, sizeof(dummy));
}

} // namespace xzero
<|endoftext|>