text:
// -*- coding: utf-8 -*-
// Copyright (C) 2011 Rosen Diankov <rosen.diankov@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
#define __STDC_CONSTANT_MACROS
#include "plugindefs.h"

#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/version.hpp>

#include <boost/lexical_cast.hpp>

#ifdef _WIN32

#define AVIIF_KEYFRAME  0x00000010L // this frame is a key frame.

#include <string>
#include <list>

#include <windows.h>
#include <memory.h>
#include <mmsystem.h>
#include <vfw.h>

class VideoGlobalState
{
public:
    VideoGlobalState() {
        /* first let's make sure we are running on 1.1 */
        WORD wVer = HIWORD(VideoForWindowsVersion());
        if (wVer < 0x010a) {
            throw openrave_exception("can't init avi library");
        }
        AVIFileInit();
    }
    virtual ~VideoGlobalState() {
        AVIFileExit();
    }
};

#else

extern "C" {
#ifdef HAVE_NEW_FFMPEG
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#else
#include <ffmpeg/avformat.h>
#include <ffmpeg/avcodec.h>
#endif
}

class VideoGlobalState
{
public:
    VideoGlobalState()
    {
        av_register_all();
    }
    virtual ~VideoGlobalState() {
    }
};

#endif

static boost::shared_ptr<VideoGlobalState> s_pVideoGlobalState;

class ViewerRecorder : public ModuleBase
{
    inline boost::shared_ptr<ViewerRecorder> shared_module() {
        return boost::dynamic_pointer_cast<ViewerRecorder>(shared_from_this());
    }
    inline boost::shared_ptr<ViewerRecorder const> shared_module_const() const {
        return boost::dynamic_pointer_cast<ViewerRecorder const>(shared_from_this());
    }
    struct VideoFrame
    {
        VideoFrame() : _timestamp(0), _bProcessed(false) {
        }
        vector<uint8_t> _vimagememory;
        int _width, _height, _pixeldepth;
        uint64_t _timestamp;
        bool _bProcessed;
    };

    boost::mutex _mutex; // for video data passing
    boost::mutex _mutexlibrary; // for video encoding library resources
    boost::condition _condnewframe;
    bool _bContinueThread, _bStopRecord;
    boost::shared_ptr<boost::thread> _threadrecord;

    boost::multi_array<uint32_t,2> _vwatermarkimage;
    int _nFrameCount, _nVideoWidth, _nVideoHeight;
    float _framerate;
    uint64_t _frameindex;
    uint64_t _starttime, _frametime;
    std::string _filename;
    UserDataPtr _callback;
    int _nUseSimulationTime; // 0 to record as is, 1 to record with respect to simulation, 2 to control simulation to viewer updates
    dReal _fSimulationTimeMultiplier; // how many times to make the simulation time faster
    list<boost::shared_ptr<VideoFrame> > _listAddFrames, _listFinishedFrames;
    boost::shared_ptr<VideoFrame> _frameLastAdded;

public:
    ViewerRecorder(EnvironmentBasePtr penv, std::istream& sinput) : ModuleBase(penv)
    {
        __description = ":Interface Author: Rosen Diankov\n\nRecords the images produced from a viewer into video file. The recordings can be synchronized to real-time or simulation time, by default simulation time is used. Each instance can record only one file at a time. To record multiple files simultaneously, create multiple VideoRecorder instances";
        RegisterCommand("Start",boost::bind(&ViewerRecorder::_StartCommand,this,_1,_2),
                        "Starts recording a file, this will stop all previous recordings and overwrite any previous files stored in this location. Format::\n\n  Start [width] [height] [framerate] codec [codec] timing [simtime/realtime/controlsimtime[=timestepmult]] viewer [name]\\n filename [filename]\\n\n\nBecause the viewer and filenames can have spaces, the names are ready until a newline is encountered");
        RegisterCommand("Stop",boost::bind(&ViewerRecorder::_StopCommand,this,_1,_2),
                        "Stops recording and saves the file. Format::\n\n  Stop\n\n");
        RegisterCommand("GetCodecs",boost::bind(&ViewerRecorder::_GetCodecsCommand,this,_1,_2),
                        "Return all the possible codecs, one codec per line:[video_codec id] [name]");
        RegisterCommand("SetWatermark",boost::bind(&ViewerRecorder::_SetWatermarkCommand,this,_1,_2),
                        "Set a WxHx4 image as a watermark. Each color is an unsigned integer ordered as A|B|G|R. The origin should be the top left corner");
        _nFrameCount = _nVideoWidth = _nVideoHeight = 0;
        _framerate = 0;
        _nUseSimulationTime = 1;
        _fSimulationTimeMultiplier = 1;
        _starttime = 0;
        _bContinueThread = true;
        _bStopRecord = true;
        _frameindex = 0;
#ifdef _WIN32
        _pfile = NULL;
        _ps = NULL;
        _psCompressed = NULL;
        _psText = NULL;
        _biSizeImage = 0;
#else
        _bWroteURL = false;
        _bWroteHeader = false;
        _output = NULL;
        _stream = NULL;
        _picture = NULL;
        _yuv420p = NULL;
        _picture_buf = NULL;
        _outbuf = NULL;
        _picture_size = 0;
        _outbuf_size = 0;
#endif
        _threadrecord.reset(new boost::thread(boost::bind(&ViewerRecorder::_RecordThread,this)));
    }
    virtual ~ViewerRecorder()
    {
        RAVELOG_VERBOSE("~ViewerRecorder\n");
        _bContinueThread = false;
        _Reset();
        {
            boost::mutex::scoped_lock lock(_mutex);
            _condnewframe.notify_all();
        }
        _threadrecord->join();
    }

    virtual void Destroy() {
        _Reset();
    }

protected:
    bool _StartCommand(ostream& sout, istream& sinput)
    {
        if( !s_pVideoGlobalState ) {
            s_pVideoGlobalState.reset(new VideoGlobalState());
        }
        try {
            ViewerBasePtr pviewer;
            int codecid=-1;
            _Reset();
            sinput >> _nVideoWidth >> _nVideoHeight >> _framerate;
            string cmd;
            while(!sinput.eof()) {
                sinput >> cmd;
                if( !sinput ) {
                    break;
                }
                std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::tolower);
                if( cmd == "codec" ) {
                    sinput >> codecid;
                }
                else if( cmd == "filename" ) {
                    if( !getline(sinput, _filename) ) {
                        return false;
                    }
                    boost::trim(_filename);
                }
                else if( cmd == "timing" ) {
                    string type;
                    sinput >> type;
                    if( type == "simtime" ) {
                        _nUseSimulationTime = 1;
                    }
                    else if( type.size() >= 14 && type.substr(0,14) == "controlsimtime" ) {
                        if( type.size() > 14 && type[14] == '=' ) {
                            _fSimulationTimeMultiplier = boost::lexical_cast<dReal>(type.substr(15));
                        }
                        RAVELOG_DEBUG(str(boost::format("controlling sim time when recording, timestep=%f")%_fSimulationTimeMultiplier));
                        _nUseSimulationTime = 2;
                    }
                    else if( type == "realtime" ) {
                        _nUseSimulationTime = 0;
                    }
                    else {
                        RAVELOG_WARN("unknown cmd");
                    }
                }
                else if( cmd == "viewer" ) {
                    string name;
                    if( !getline(sinput, name) ) {
                        return false;
                    }
                    boost::trim(name);
                    pviewer = GetEnv()->GetViewer(name);
                }
                else {
                    return false;
                }
                if( sinput.fail() || !sinput ) {
                    break;
                }
            }
            boost::mutex::scoped_lock lock(_mutex);
            if( !pviewer ) {
                RAVELOG_WARN("invalid viewer\n");
            }
            else{
                stringstream ss;
                ss << "Resize " << _nVideoWidth << " " << _nVideoHeight << " ";
                pviewer->SendCommand(sout,ss);
            }
            RAVELOG_INFO("video filename: %s, %d x %d @ %f frames/sec\n",_filename.c_str(),_nVideoWidth,_nVideoHeight,_framerate);
            _StartVideo(_filename,_framerate,_nVideoWidth,_nVideoHeight,24,codecid);
            _starttime = 0;
            if( _nUseSimulationTime == 2 ) {
                _frametime = (uint64_t)(1000000.0f*_fSimulationTimeMultiplier/_framerate);
            }
            else {
                _frametime = (uint64_t)(1000000.0f/_framerate);
            }
            _callback = pviewer->RegisterViewerImageCallback(boost::bind(&ViewerRecorder::_ViewerImageCallback,shared_module(),_1,_2,_3,_4));
            BOOST_ASSERT(!!_callback);
            _bStopRecord = false;
            return !!_callback;
        }
        catch(const std::exception& ex) {
            RAVELOG_WARN("%s\n",ex.what());
            _Reset();
        }
        return false;
    }

    bool _StopCommand(ostream& sout, istream& sinput)
    {
        _Reset();
        return true;
    }

    bool _SetWatermarkCommand(ostream& sout, istream& sinput)
    {
        boost::mutex::scoped_lock lock(_mutex);
        int W, H;
        sinput >> W >> H;
        _vwatermarkimage.resize(boost::extents[H][W]);
        for(int i = 0; i < H; ++i) {
            for(int j = 0; j < W; ++j) {
                sinput >> _vwatermarkimage[i][j];
            }
        }
        return !!sinput;
    }

    void _ViewerImageCallback(const uint8_t* memory, int width, int height, int pixeldepth)
    {
        boost::mutex::scoped_lock lock(_mutex);
        if( !GetEnv() || !_callback ) {
            // recorder already destroyed and this thread is just remaining
            return;
        }
        uint64_t timestamp = _nUseSimulationTime ? GetEnv()->GetSimulationTime() : utils::GetMicroTime();
        boost::shared_ptr<VideoFrame> frame;

        if( _listAddFrames.size() > 0 ) {
            BOOST_ASSERT( timestamp-_starttime >= _listAddFrames.back()->_timestamp-_starttime );
            if( _listAddFrames.back()->_timestamp == timestamp ) {
                // if the timestamps match, then take the newest frame
                frame = _listAddFrames.back();
                _listAddFrames.pop_back();
            }
        }
        if( !frame ) {
            if( _listFinishedFrames.size() > 0 ) {
                frame = _listFinishedFrames.back();
                _listFinishedFrames.pop_back();
            }
            else {
                frame.reset(new VideoFrame());
            }
        }
        frame->_width = width;
        frame->_height = height;
        frame->_pixeldepth = pixeldepth;
        //RAVELOG_VERBOSE("image frame is %d x %d\n",width,height);
        frame->_timestamp = timestamp;
        frame->_vimagememory.resize(width*height*pixeldepth);
        std::copy(memory,memory+width*height*pixeldepth,frame->_vimagememory.begin());
        _listAddFrames.push_back(frame);
        if( _starttime == 0 ) {
            _starttime = timestamp;
        }
        RAVELOG_VERBOSE(str(boost::format("new frame %d\n")%(timestamp-_starttime)));
        _condnewframe.notify_one();
        if( _nUseSimulationTime == 2 ) {
            // calls the environment lock, which might be taken if the environment is destroying the problem
            // therefore need to take it first
            while(_bContinueThread && !_bStopRecord) {
                boost::shared_ptr<EnvironmentMutex::scoped_try_lock> lockenv = _LockEnvironment(100000);
                if( !!lockenv ) {
                    GetEnv()->StepSimulation(_fSimulationTimeMultiplier/_framerate);
                    break;
                }
            }
        }
    }

    boost::shared_ptr<EnvironmentMutex::scoped_try_lock> _LockEnvironment(uint64_t timeout)
    {
        // try to acquire the lock
#if BOOST_VERSION >= 103500
        boost::shared_ptr<EnvironmentMutex::scoped_try_lock> lockenv(new EnvironmentMutex::scoped_try_lock(GetEnv()->GetMutex(),boost::defer_lock_t()));
#else
        boost::shared_ptr<EnvironmentMutex::scoped_try_lock> lockenv(new EnvironmentMutex::scoped_try_lock(GetEnv()->GetMutex(),false));
#endif
        uint64_t basetime = utils::GetMicroTime();
        while(utils::GetMicroTime()-basetime<timeout ) {
            lockenv->try_lock();
            if( !!*lockenv ) {
                break;
            }
        }
        if( !*lockenv ) {
            lockenv.reset();
        }
        return lockenv;
    }

    void _RecordThread()
    {
        while(_bContinueThread) {
            boost::shared_ptr<VideoFrame> frame;
            uint64_t numstores=0;
            {
                boost::mutex::scoped_lock lock(_mutex);
                if( !_bContinueThread ) {
                    return;
                }
                if( _listAddFrames.size() == 0 ) {
                    _condnewframe.wait(lock);
                    if( _listAddFrames.size() == 0 ) {
                        continue;
                    }
                }
                if( _bStopRecord ) {
                    continue;
                }

                if(( _listAddFrames.front()->_timestamp-_starttime > _frametime) && !!_frameLastAdded ) {
                    frame = _frameLastAdded;
                    numstores = (_listAddFrames.front()->_timestamp-_starttime-1)/_frametime;
                    RAVELOG_VERBOSE(str(boost::format("previous frame repeated %d times\n")%numstores));
                }
                else {
                    uint64_t lastoffset = _listAddFrames.back()->_timestamp - _starttime;
                    if( lastoffset < _frametime ) {
                        // not enough frames to predict what's coming next so wait
                        continue;
                    }
                    list<boost::shared_ptr<VideoFrame> >::iterator itframe = _listAddFrames.begin(), itbest = _listAddFrames.end();
                    uint64_t bestdist = 0;
                    while(itframe != _listAddFrames.end()) {
                        uint64_t offset = (*itframe)->_timestamp - _starttime;
                        uint64_t dist = offset >= _frametime ? (offset-_frametime) : (_frametime-offset);
                        if(( itbest == _listAddFrames.end()) ||( bestdist > dist) ) {
                            itbest = itframe;
                            bestdist = dist;
                        }
                        if( !_bContinueThread ) {
                            return;
                        }
                        ++itframe;
                    }
                    frame = *itbest;
                    size_t prevsize = _listAddFrames.size();
                    _listAddFrames.erase(_listAddFrames.begin(),itbest);
                    if( frame->_timestamp-_starttime <= _frametime ) {
                        // the frame is before the next mark, so erase it
                        _listAddFrames.erase(itbest);
                    }
                    RAVELOG_VERBOSE(str(boost::format("frame size: %d -> %d\n")%prevsize%_listAddFrames.size()));
                    numstores = 1;
                }
            }

            if( !frame->_bProcessed ) {
                _AddWatermarkToImage(&frame->_vimagememory.at(0), frame->_width, frame->_height, frame->_pixeldepth);
                frame->_bProcessed = true;
            }

            try {
                _starttime += _frametime*numstores;
                for(uint64_t i = 0; i < numstores; ++i) {
                    _AddFrame(&frame->_vimagememory.at(0));
                }
                _frameLastAdded = frame;
            }
            catch(const std::exception& ex) {
                RAVELOG_WARN("%s\n",ex.what());
            }
        }
    }

    void _AddWatermarkToImage(uint8_t* memory, int width, int height, int pixeldepth)
    {
        if( _vwatermarkimage.size() == 0 ) {
            return;
        }
        // the origin of the image is the bottom left corner
        for(int i = 0; i < height; ++i) {
            for(int j = 0; j < width; ++j) {
                int iwater = _vwatermarkimage.shape()[0]-(i%_vwatermarkimage.shape()[0])-1;
                int jwater = j%_vwatermarkimage.shape()[1];
                uint32_t color = _vwatermarkimage[iwater][jwater];
                uint32_t A = color>>24;
                for(int k = 0; k < min(pixeldepth,3); ++k) {
                    memory[k] = ((uint32_t)memory[k]*(255-A)+((color>>(8*k))&0xff)*A)>>8;
                }
                memory += pixeldepth;
            }
        }
    }

    void _Reset()
    {
        {
            RAVELOG_DEBUG("ViewerRecorder _Reset\n");
            _bStopRecord = true;
            boost::mutex::scoped_lock lock(_mutex);
            _nFrameCount = 0;
            _nVideoWidth = _nVideoHeight = 0;
            _framerate = 30000.0f/1001.0f;
            _starttime = 0;
            _callback.reset();
            _nUseSimulationTime = true;
            _listAddFrames.clear();
            _listFinishedFrames.clear();
            _frameLastAdded.reset();
            _filename = "";
        }
        {
            RAVELOG_DEBUG("ViewerRecorder _ResetLibrary\n");
            boost::mutex::scoped_lock lock(_mutexlibrary);
            _ResetLibrary();
        }
    }

#ifdef _WIN32
    PAVIFILE _pfile;
    PAVISTREAM _ps, _psCompressed, _psText;
    int _biSizeImage;

    bool _GetCodecsCommand(ostream& sout, istream& sinput)
    {
        return false;
    }

    void _StartVideo(const std::string& filename, double frameRate, int width, int height, int bits, int codecid=-1)
    {
        _nFrameCount = 0;
        HRESULT hr = AVIFileOpenA(&_pfile, filename.c_str(), OF_WRITE | OF_CREATE, NULL);
        BOOST_ASSERT( hr == AVIERR_OK );
        _CreateStream((int)_framerate, width*height/bits, width, height, "none");

        BITMAPINFOHEADER bi;
        memset(&bi, 0, sizeof(bi));
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = width;
        bi.biHeight = height;
        bi.biPlanes = 1;
        bi.biBitCount = bits;
        bi.biCompression = BI_RGB;
        bi.biSizeImage = width * height * bits /8;
        _SetOptions(&bi, "none");
        _biSizeImage = bi.biSizeImage;
    }

    void _ResetLibrary()
    {
        if (!!_ps) {
            AVIStreamClose(_ps);
            _ps = NULL;
        }
        if (!!_psCompressed) {
            AVIStreamClose(_psCompressed);
            _psCompressed = NULL;
        }
        if (!!_psText) {
            AVIStreamClose(_psText);
            _psText = NULL;
        }
        if( _pfile) {
            AVIFileClose(_pfile);
            _pfile = NULL;
        }
    }

    DWORD _getFOURCC(const char* value)
    {
        if(stricmp(value, "DIB") == 0) {
            return mmioFOURCC(value[0],value[1],value[2],' ');
        }
        else if((stricmp(value, "CVID") == 0) || (stricmp(value, "IV32") == 0) || (stricmp(value, "MSVC") == 0) || (stricmp(value, "IV50") == 0)) {
            return mmioFOURCC(value[0],value[1],value[2],value[3]);
        }
        else {
            return NULL;
        }
    }

    // Fill in the header for the video stream....
    // The video stream will run in rate ths of a second....
    void _CreateStream(int rate, unsigned long buffersize, int rectwidth, int rectheight, const char* _compressor)
    {
        AVISTREAMINFO strhdr;
        memset(&strhdr, 0, sizeof(strhdr));
        strhdr.fccType                = streamtypeVIDEO;    // stream type
        strhdr.fccHandler             = _getFOURCC(_compressor);
        //strhdr.fccHandler             = 0; // no compression!
        //strhdr.fccHandler             = mmioFOURCC('D','I','B',' '); // Uncompressed
        //strhdr.fccHandler             = mmioFOURCC('C','V','I','D'); // Cinpak
        //strhdr.fccHandler             = mmioFOURCC('I','V','3','2'); // Intel video 3.2
        //strhdr.fccHandler             = mmioFOURCC('M','S','V','C'); // Microsoft video 1
        //strhdr.fccHandler             = mmioFOURCC('I','V','5','0'); // Intel video 5.0
        //strhdr.dwFlags                = AVISTREAMINFO_DISABLED;
        //strhdr.dwCaps                 =
        //strhdr.wPriority              =
        //strhdr.wLanguage              =
        strhdr.dwScale                = 1;
        strhdr.dwRate                 = rate;                   // rate fps
        //strhdr.dwStart                =
        //strhdr.dwLength               =
        //strhdr.dwInitialFrames        =
        strhdr.dwSuggestedBufferSize  = buffersize;
        strhdr.dwQuality              = -1;     // use the default
        //strhdr.dwSampleSize           =
        SetRect(&strhdr.rcFrame, 0, 0, (int) rectwidth, (int) rectheight);
        //strhdr.dwEditCount            =
        //strhdr.dwFormatChangeCount    =
        //strcpy(strhdr.szName, "Full Frames (Uncompressed)");

        // And create the stream;
        HRESULT hr = AVIFileCreateStream(_pfile, &_ps, &strhdr);
        BOOST_ASSERT(hr == AVIERR_OK);
    }

    void _SetOptions(LPBITMAPINFOHEADER lpbi, const char* _compressor)
    {
        AVICOMPRESSOPTIONS opts;
        AVICOMPRESSOPTIONS FAR * aopts[1] = { &opts};

        memset(&opts, 0, sizeof(opts));
        opts.fccType = streamtypeVIDEO;
        opts.fccHandler = _getFOURCC(_compressor);

        /* display the compression options dialog box if specified compressor is unknown */
        if(_getFOURCC(_compressor) == NULL) {
            if (!AVISaveOptions(NULL, 0, 1, &_ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts)) {
                throw OPENRAVE_EXCEPTION_FORMAT0("failed to set options",ORE_Assert);
            }
        }

        HRESULT hr = AVIMakeCompressedStream(&_psCompressed, _ps, &opts, NULL);
        BOOST_ASSERT(hr == AVIERR_OK);

        hr = AVIStreamSetFormat(_psCompressed, 0, lpbi /*stream format*/, lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD) /*format size*/);
        BOOST_ASSERT(hr == AVIERR_OK);
    }

    void _SetText(char *szText, int width, int height, int TextHeight)
    {
        // Fill in the stream header for the text stream....
        AVISTREAMINFO strhdr;
        DWORD dwTextFormat;
        // The text stream is in 60ths of a second....

        memset(&strhdr, 0, sizeof(strhdr));
        strhdr.fccType                = streamtypeTEXT;
        strhdr.fccHandler             = mmioFOURCC('D', 'R', 'A', 'W');
        strhdr.dwScale                = 1;
        strhdr.dwRate                 = 60;
        strhdr.dwSuggestedBufferSize  = sizeof(szText);
        SetRect(&strhdr.rcFrame, 0, (int) height, (int) width, (int) height + TextHeight);     // #define TEXT_HEIGHT 20

        // ....and create the stream.
        HRESULT hr = AVIFileCreateStream(_pfile, &_psText, &strhdr);
        BOOST_ASSERT(hr == AVIERR_OK);

        dwTextFormat = sizeof(dwTextFormat);
        hr = AVIStreamSetFormat(_psText, 0, &dwTextFormat, sizeof(dwTextFormat));
        BOOST_ASSERT(hr == AVIERR_OK);
    }

    void _AddFrame(void* pdata)
    {
        boost::mutex::scoped_lock lock(_mutexlibrary);
        HRESULT hr = AVIStreamWrite(_psCompressed /*stream pointer*/, _nFrameCount /*time of this frame*/, 1 /*number to write*/, pdata, _biSizeImage /*size of this frame*/, AVIIF_KEYFRAME /*flags....*/, NULL, NULL);
        BOOST_ASSERT(hr == AVIERR_OK);
        _nFrameCount++;
    }

    void _AddText(int time, char *szText)
    {
        HRESULT hr = AVIStreamWrite(_psText, time,  1, szText, strlen(szText) + 1, AVIIF_KEYFRAME, NULL, NULL);
        BOOST_ASSERT(hr == AVIERR_OK);
    }

#else
    // ffmpeg

    AVFormatContext *_output;
    AVStream *_stream;
    AVFrame *_picture;
    AVFrame *_yuv420p;
    char *_picture_buf, *_outbuf;
    int _picture_size;
    int _outbuf_size;
    bool _bWroteURL, _bWroteHeader;

    void _ResetLibrary()
    {
        free(_picture_buf); _picture_buf = NULL;
        free(_picture); _picture = NULL;
        free(_yuv420p); _yuv420p = NULL;
        free(_outbuf); _outbuf = NULL;
        if( !!_stream ) {
            avcodec_close(_stream->codec);
            _stream = NULL;
        }

        if( !!_output ) {
            RAVELOG_DEBUG("stopping avi\n");
            if( _bWroteHeader ) {
                av_write_trailer(_output);
            }
            if( _bWroteURL ) {
#if LIBAVFORMAT_VERSION_INT >= (54<<16)
                avio_close(_output->pb);
#elif LIBAVFORMAT_VERSION_INT >= (52<<16)
                url_fclose(_output->pb);
#else
                url_fclose(&_output->pb);
#endif
            }
            if( _output->streams[0] ) {
                av_freep(&_output->streams[0]);
            }
            av_free(_output);
            _output = NULL;
        }
        _bWroteURL = _bWroteHeader = false;
    }

    bool _GetCodecsCommand(ostream& sout, istream& sinput)
    {
        if( !s_pVideoGlobalState ) {
            s_pVideoGlobalState.reset(new VideoGlobalState());
        }
#if LIBAVFORMAT_VERSION_INT >= (52<<16)
        AVOutputFormat *fmt = av_oformat_next(NULL); //first_oformat;
#else
        AVOutputFormat *fmt = first_oformat;
#endif
        while (fmt != NULL) {
            if( fmt->video_codec != CODEC_ID_NONE && !!fmt->name ) {
                string mime_type;
                if( !!fmt->mime_type ) {
                    mime_type = fmt->mime_type;
                }
                if( mime_type.size() == 0 ) {
                    mime_type = "*";
                }
                sout << fmt->video_codec << " " << mime_type << " " << fmt->name << endl;
            }
            fmt = fmt->next;
        }
        return true;
    }

    void _StartVideo(const std::string& filename, double frameRate, int width, int height, int bits, int codecid=-1)
    {
        OPENRAVE_ASSERT_OP_FORMAT0(bits,==,24,"START_AVI only supports 24bits",ORE_InvalidArguments);
        OPENRAVE_ASSERT_OP_FORMAT0(filename.size(),>,0,"filename needs to be valid",ORE_InvalidArguments);
        AVCodecContext *codec_ctx;
        AVCodec *codec;

#if defined(LIBAVCODEC_VERSION_INT) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54,25,0) // introduced at http://git.libav.org/?p=libav.git;a=commit;h=104e10fb426f903ba9157fdbfe30292d0e4c3d72
        AVCodecID video_codec = codecid == -1 ? CODEC_ID_MPEG4 : (AVCodecID)codecid;
#else
        CodecID video_codec = codecid == -1 ? CODEC_ID_MPEG4 : (CodecID)codecid;
#endif
#if LIBAVFORMAT_VERSION_INT >= (52<<16)
        AVOutputFormat *fmt = av_oformat_next(NULL); //first_oformat;
#else
        AVOutputFormat *fmt = first_oformat;
#endif
        while (fmt != NULL) {
            if (fmt->video_codec == video_codec) {
                break;
            }
            fmt = fmt->next;
        }
        BOOST_ASSERT(!!fmt);

        _frameindex = 0;
        _output = (AVFormatContext*)av_mallocz(sizeof(AVFormatContext));
        BOOST_ASSERT(!!_output);

        _output->oformat = fmt;
        snprintf(_output->filename, sizeof(_output->filename), "%s", filename.c_str());

#if LIBAVFORMAT_VERSION_INT >= (54<<16)
        _stream = avformat_new_stream(_output, 0);
#else
        _stream = av_new_stream(_output, 0);
#endif
        BOOST_ASSERT(!!_stream);

        codec_ctx = _stream->codec;
        codec_ctx->codec_id = video_codec;
#ifdef HAS_AVMEDIA_TYPE_VIDEO
        codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
#else
        codec_ctx->codec_type = CODEC_TYPE_VIDEO;
#endif
        codec_ctx->bit_rate = 4000000;
        codec_ctx->width = width;
        codec_ctx->height = height;
        if( RaveFabs(frameRate-29.97)<0.01 ) {
            codec_ctx->time_base.num = 1001;
            codec_ctx->time_base.den = 30000;
        }
        else {
            codec_ctx->time_base.num = 1;
            codec_ctx->time_base.den = (int)frameRate;
        }
        codec_ctx->gop_size = 10;
        codec_ctx->max_b_frames = 1;
        codec_ctx->pix_fmt = PIX_FMT_YUV420P;

#if LIBAVFORMAT_VERSION_INT >= (54<<16)
        // not necessary to set parameters?
#else
        if (av_set_parameters(_output, NULL) < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT0("set parameters failed",ORE_Assert);
        }
#endif
        codec = avcodec_find_encoder(codec_ctx->codec_id);
        BOOST_ASSERT(!!codec);

        RAVELOG_DEBUG(str(boost::format("opening %s, w:%d h:%dx fps:%f, codec: %s")%_output->filename%width%height%frameRate%codec->name));

#if LIBAVFORMAT_VERSION_INT >= (54<<16)
        AVDictionary * RetunedAVDic=NULL;
        if (avcodec_open2(codec_ctx, codec,&RetunedAVDic) < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT0("Unable to open codec",ORE_Assert);
        }

        int ret = avio_open(&_output->pb, filename.c_str(), AVIO_FLAG_WRITE);
        if (ret < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT("_StartVideo: Unable to open %s for writing: %d\n", filename%ret,ORE_Assert);
        }
        _bWroteURL = true;
        avformat_write_header(_output,NULL);
#else
        if (avcodec_open(codec_ctx, codec) < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT0("Unable to open codec",ORE_Assert);
        }

        int ret = url_fopen(&_output->pb, filename.c_str(), URL_WRONLY);
        if (ret < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT("_StartVideo: Unable to open %s for writing: %d\n", filename%ret,ORE_Assert);
        }
        _bWroteURL = true;

        av_write_header(_output);
#endif
        _bWroteHeader = true;

        _picture = avcodec_alloc_frame();
        _yuv420p = avcodec_alloc_frame();

        _outbuf_size = 500000;
        _outbuf = (char*)malloc(_outbuf_size);
        BOOST_ASSERT(!!_outbuf);

        _picture_size = avpicture_get_size(PIX_FMT_YUV420P, codec_ctx->width, codec_ctx->height);
        _picture_buf = (char*)malloc(_picture_size);
        BOOST_ASSERT(!!_picture_buf);

        avpicture_fill((AVPicture*)_yuv420p, (uint8_t*)_picture_buf, PIX_FMT_YUV420P, codec_ctx->width, codec_ctx->height);
    }

    void _AddFrame(void* pdata)
    {
        boost::mutex::scoped_lock lock(_mutexlibrary);
        if( !_output ) {
            RAVELOG_DEBUG("video resources destroyed\n");
            return;
        }

        // flip vertically
        static vector<char> newdata;
        newdata.resize(_stream->codec->height*_stream->codec->width*3);
        char* penddata = (char*)pdata + _stream->codec->height*_stream->codec->width*3;

        for(int i = 0; i < _stream->codec->height; ++i) {
            memcpy(&newdata[i*_stream->codec->width*3], (char*)penddata - (i+1)*_stream->codec->width*3, _stream->codec->width*3);
        }

        _picture->data[0] = (uint8_t*)&newdata[0];
        _picture->linesize[0] = _stream->codec->width * 3;

#ifdef HAVE_NEW_FFMPEG
        struct SwsContext *img_convert_ctx;
        img_convert_ctx = sws_getContext(_stream->codec->width, _stream->codec->height, PIX_FMT_BGR24, _stream->codec->width, _stream->codec->height, PIX_FMT_YUV420P, SWS_BICUBIC /* flags */, NULL, NULL, NULL);
        if (!sws_scale(img_convert_ctx, _picture->data, _picture->linesize, 0, _stream->codec->height, _yuv420p->data, _yuv420p->linesize)) {
            sws_freeContext(img_convert_ctx);
            throw OPENRAVE_EXCEPTION_FORMAT0("ADD_FRAME sws_scale failed",ORE_Assert);
        }

        sws_freeContext(img_convert_ctx);
#else
        if( img_convert((AVPicture*)_yuv420p, PIX_FMT_YUV420P, (AVPicture*)_picture, PIX_FMT_BGR24, _stream->codec->width, _stream->codec->height) ) {
            throw OPENRAVE_EXCEPTION_FORMAT0("ADD_FRAME img_convert failed",ORE_Assert);
        }
#endif

#if LIBAVFORMAT_VERSION_INT >= (54<<16)
        int got_packet=0;
        AVPacket pkt;
        av_init_packet(&pkt);
        pkt.data = (uint8_t*)_outbuf;
        pkt.size = _outbuf_size;
        int ret = avcodec_encode_video2(_stream->codec, &pkt, _yuv420p, &got_packet);
        if( ret < 0 ) {
            throw OPENRAVE_EXCEPTION_FORMAT("avcodec_encode_video2 failed with %d",ret,ORE_Assert);
        }
        if (got_packet ) {
            if( _stream->codec->coded_frame) {
                _stream->codec->coded_frame->pts       = pkt.pts;
                _stream->codec->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY);
            }
        }
        if( av_write_frame(_output, &pkt) < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT0("av_write_frame failed",ORE_Assert);
        }
        pkt.data = NULL;
        av_destruct_packet(&pkt);
#else
        int size = avcodec_encode_video(_stream->codec, (uint8_t*)_outbuf, _outbuf_size, _yuv420p);
        if (size < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT0("error encoding frame",ORE_Assert);
        }

        AVPacket pkt;
        av_init_packet(&pkt);
        pkt.data = (uint8_t*)_outbuf;
        pkt.size = size;
        pkt.stream_index = _stream->index;
        //RAVELOG_INFO("%d\n",index);
        pkt.pts = _frameindex++;
        if( av_write_frame(_output, &pkt) < 0) {
            throw OPENRAVE_EXCEPTION_FORMAT0("av_write_frame failed",ORE_Assert);
        }

#endif
        _nFrameCount++;
    }
#endif
};

ModuleBasePtr CreateViewerRecorder(EnvironmentBasePtr penv, std::istream& sinput) {
    return ModuleBasePtr(new ViewerRecorder(penv,sinput));
}
void DestroyViewerRecordingStaticResources()
{
#ifdef _WIN32
    s_pVideoGlobalState.reset();
#endif
}

max_issues_repo_name: jdsika/holy

max_forks_repo_name: jdsika/holy


text: #include <boost/preprocessor/logical/bool.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#pragma once
#include <memory>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include "response.hpp"
#include <regex>
#include "error/all.hpp"
#include <exception>
#include "params.hpp"
#include <pixiu/logger.hpp>
#include <pixiu/utils.hpp>
#include <pixiu/server/request.hpp>
#include <random>
#include <nlohmann/json.hpp>
#include "session/context.hpp"

namespace pixiu::server_bits {

namespace __http    = boost::beast::http  ;
namespace __beast   = boost::beast        ;
namespace __asio    = boost::asio         ;
template<class Session = session::default_session>
struct request_router {

  using session_context       = pixiu::server_bits::session::context<Session>;
  using request               = typename session_context::request;
  static constexpr auto session_id_key = request::session_id_key;

  template<class... Args>
  using handler               = std::function<response(const session_context&, Args... args)>;

  using head_handler          = std::function<void(response&, const session_context&)>;
  using get_handler           = handler<>;
  using post_handler          = handler<>;

  template<class... Args>
  using err_handler          = handler<const error::base&, Args...>;
  template<class... Args>
  using serv_err_handler     = handler<Args...>;

  using request_handler      = std::tuple<
    std::regex, head_handler, get_handler, post_handler
  >;
  using target_request_mapper = std::vector<request_handler>;
  using target_request_index  = std::map<std::string, std::size_t>;

  static auto& logger() {
    return pixiu::logger::get("router");
  }
  static response generic_error_response(const session_context& sn, const error::base& err) {
    return err.create_response(sn.req);
  }
  request_router() {
    on_err_unknown_method_      = generic_error_response;
    on_err_illegal_target_      = generic_error_response;
    on_err_target_not_found_    = generic_error_response;
    on_err_server_error_        = [](const session_context& sn, std::string what) {
      error::server_error e(what);
      return e.create_response(sn.req);
    };
  }
  template<int method_id, class Handler>
  void add_handler(const std::string& target_pattern, Handler&& h) {
    auto iter = pattern_index_.find(target_pattern);
    if(iter == pattern_index_.end()) {
      pattern_index_[target_pattern] = on_target_requests_.size();
      request_handler handler;
      std::get<0>(handler) = std::regex(target_pattern.c_str());
      std::get<method_id + 1>(handler) = std::move(h);
      on_target_requests_.emplace_back(std::move(handler));
    } else {
      std::get<method_id + 1>(on_target_requests_[iter->second]) = std::move(h);
    }
  }
  void head(const std::string& target_pattern, head_handler&& hh) {
    add_handler<0>(target_pattern, std::move(hh));
  }
  void get(const std::string& target_pattern, get_handler&& gh) {
    add_handler<1>(target_pattern, std::move(gh));
  }
  void post(const std::string& target_pattern, post_handler&& ph) {
    add_handler<2>(target_pattern, std::move(ph));
  }
  template<class... Type, class Func>
  void get(
    const std::string&    target,
    params<Type...>&&     param_types,
    Func&&                func
  ) {
    get(target, [p_t = std::move(param_types), func = std::move(func)](const auto& session) -> response {
      auto params_tuple = p_t.parse_get_url(session.req.target());
      return boost::hana::unpack(params_tuple, [&session, &func](auto&&... args){
        return func(session, std::move(args)...);
      });
    });
  }
  template<class... Type, class Func>
  void post(
    const std::string&    target,
    params<Type...>&&     param_types,
    Func&&                func
  ) {
    post(target, [p_t = std::move(param_types), func = std::move(func)](const auto& session) -> response {
      std::string req_str = session.req.body();
      logger().info("before parse: {}", req_str);
      auto params_tuple = p_t.parse_post_body(req_str);
      return boost::hana::unpack(params_tuple, [&session, &func](auto&&... args){
        return func(session, std::move(args)...);
      });
    });
  }
  void on_err_unknown_method(err_handler<>&& eh) {
    on_err_unknown_method_ = eh;
  }
  void on_err_target_not_found(err_handler<>&& eh) {
    on_err_target_not_found_ = eh;
  }
  void on_err_server_error(serv_err_handler<std::string>&& eh) {
    on_err_server_error_ = eh;
  }
  void on_err_illegal_target(err_handler<>&& eh) {
    on_err_illegal_target_ = eh;
  }
  auto search_handler(
    const std::string_view&   target,
    std::vector<std::string>& url_capts
  ) const {
    std::smatch m_url_capt;
    std::string s_target{ target.begin(), target.end() };
    for(auto&& [pattern, head, get, post] : on_target_requests_) {
      // logger().debug("search pattern: {}", pattern.str());
      if(std::regex_match(s_target, m_url_capt, pattern)) {
        for(std::size_t i = 1; i < m_url_capt.size(); i ++) {
          url_capts.push_back(m_url_capt[i].str());
        }
        return std::make_tuple(head, get, post);
      }
    }
    throw error::target_not_found(s_target);
  }
  template<class Func>
  auto operator()(
    session_context&        session,
    Func&&                  send
  ) const {
    auto& req = session.req;
    try {
      // Request path must be absolute and not contain "..".
      auto target = req.target();
      if( target.empty() ||
          target[0] != '/' ||
          target.find("..") != std::string_view::npos
      ) throw error::illegal_target(
        std::string{ target.begin(), target.end() }
      );
      // TODO: session process

      logger().debug("request target: {}", std::string{ target.begin(), target.end() });
      auto query_start = target.find_first_of('?');
      auto target_without_query = target.substr(0, query_start);
      auto handlers = search_handler(target_without_query, session.url_capt);

      // Respond to HEAD request
      switch(req.method()) {
        case __http::verb::head:
          return method_case_head(
            session,
            std::move(send),
            handlers
          );
        case __http::verb::get:
          return method_case_general<1>(
            session,
            std::move(send),
            handlers
          );
        case __http::verb::post:
          return method_case_general<2>(
            session,
            std::move(send),
            handlers
          );
        default: {
          auto method = req.method_string();
          throw error::unknown_method(std::string{method.begin(), method.end()});

        }
      };
    } catch (const error::illegal_target& err) {
      on_err_illegal_target_(session, err).write(send);
    } catch (const error::target_not_found& err) {
      on_err_target_not_found_(session, err).write(send);
    } catch (const error::unknown_method& err) {
      on_err_unknown_method_(session, err).write(send);
    } catch (const std::exception& e) {
      on_err_server_error_(session, e.what()).write(send);
    }
  }
private:
  // static constexpr int verb_to_method_id(__http::verb method) {
  //   switch(method) {
  //     case __http::verb::head:    return 0;
  //     case __http::verb::get:     return 1;
  //     case __http::verb::post:    return 2;
  //     case __http::verb::put:     return 3;
  //     case __http::verb::delete_: return 4;
  //     case __http::verb::patch:   return 5;
  //     default:                    return 6;
  //   }
  // }
  void generic_header_config(response& rep, const session_context& sn) const {
    auto& req = sn.req;
    rep.apply([&req, &sn](auto&& inter_rep){
      inter_rep.version(req.version());
      if(inter_rep.result() == __http::status::unknown) {
        inter_rep.result(__http::status::ok);
      }
      auto itr = inter_rep.find(__http::field::server);
      if(itr == inter_rep.end()) {
        inter_rep.set(__http::field::server, BOOST_BEAST_VERSION_STRING);
      }
      inter_rep.set(__http::field::set_cookie,
        fmt::format("{}={}", session_id_key, sn.session_id())
      );
      if(inter_rep.result() == __http::status::found) return;
      inter_rep.keep_alive(req.keep_alive());
    });
  }
  template<class Func, class HandlerTuple>
  auto method_case_head(const session_context& sn, Func&& send, HandlerTuple& handlers) const {
    logger().debug("head request");
    auto [head_h, get_h, post_h] = handlers;
    response rep;
    rep.emplace<__http::response<__http::empty_body>>();
    generic_header_config(rep, sn);
    head_h(rep, sn);
    return rep.write(send);
  }
  template<int method_id, class Func, class HandlerTuple>
  auto method_case_general(const session_context& sn, Func&& send, HandlerTuple& handlers) const {
    logger().debug("get request");
    auto [head_h, get_h, post_h] = handlers;
    auto rep = std::get<method_id>(handlers)(sn);
    generic_header_config(rep, sn);
    if(head_h) {
      head_h(rep, sn);
    } else {
      rep.apply([](auto& inter_rep){
        if(!inter_rep.payload_size()) {
          inter_rep.prepare_payload();
        }
        auto itr = inter_rep.find(__http::field::content_type);
        if(itr == inter_rep.end()) {
          inter_rep.set(__http::field::content_type, "text/html");
        }
      });
    }
    return rep.write(send);
  }
  err_handler<>                 on_err_unknown_method_      ;
  err_handler<>                 on_err_illegal_target_      ;
  err_handler<>                 on_err_target_not_found_    ;
  serv_err_handler<std::string> on_err_server_error_        ;
  target_request_mapper         on_target_requests_         ;
  target_request_index          pattern_index_              ;
};

}


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

#include "mopcrtfileformat.h"

#include <boost/make_shared.hpp>

#include <chemkit/atom.h>
#include <chemkit/molecule.h>
#include <chemkit/moleculefile.h>

MopcrtFileFormat::MopcrtFileFormat()
    : chemkit::MoleculeFileFormat("mopcrt")
{
}

bool MopcrtFileFormat::read(std::istream &input, chemkit::MoleculeFile *file)
{
    // create molecule
    boost::shared_ptr<chemkit::Molecule> molecule(new chemkit::Molecule);

    // keyword line
    std::string keyword;
    std::getline(input, keyword);

    // title line
    std::string title;
    std::getline(input, title);
    if(!title.empty()){
        molecule->setName(title);
    }

    // blank line
    std::string line;
    std::getline(input, line);

    // read atoms
    for(;;){
        std::getline(input, line);
        boost::trim(line);
        std::vector<std::string> tokens;
        boost::split(tokens, line, boost::is_any_of("\t "), boost::token_compress_on);
        if(tokens.size() < 7){
            break;
        }

        chemkit::Atom *atom = molecule->addAtom(tokens[0]);
        if(!atom){
            continue;
        }

        atom->setPosition(boost::lexical_cast<chemkit::Real>(tokens[1]),
                          boost::lexical_cast<chemkit::Real>(tokens[3]),
                          boost::lexical_cast<chemkit::Real>(tokens[5]));
    }

    if(molecule->isEmpty()){
        return false;
    }

    file->addMolecule(molecule);

    return true;
}

ext: cpp

max_stars_repo_name: quizzmaster/chemkit

max_issues_repo_name: soplwang/chemkit

max_forks_repo_name: soplwang/chemkit


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

/** \author Alessandro Di Fava. */

// C++ standard headers
#include <exception>
#include <string>

// Boost headers
#include <boost/shared_ptr.hpp>

// ROS headers
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <control_msgs/FollowJointTrajectoryAction.h>
#include <ros/topic.h>

// Our Action interface type for moving TIAGo's head, provided as a typedef for convenience
typedef actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> arm_control_client;
typedef boost::shared_ptr< arm_control_client>  arm_control_client_Ptr;

// Create a ROS action client to move TIAGo's arm
void createArmClient(arm_control_client_Ptr& actionClient)
{
  ROS_INFO("Creating action client to arm controller ...");

  actionClient.reset( new arm_control_client("/arm_controller/follow_joint_trajectory") );

  int iterations = 0, max_iterations = 3;
  // Wait for arm controller action server to come up
  while( !actionClient->waitForServer(ros::Duration(2.0)) && ros::ok() && iterations < max_iterations )
  {
    ROS_DEBUG("Waiting for the arm_controller_action server to come up");
    ++iterations;
  }

  if ( iterations == max_iterations )
    throw std::runtime_error("Error in createArmClient: arm controller action server not available");
}

// Generates a simple trajectory with two waypoints to move TIAGo's arm
void waypoints_arm_goal(control_msgs::FollowJointTrajectoryGoal& goal)
{
  // The joint names, which apply to all waypoints
  goal.trajectory.joint_names.push_back("arm_1_joint");
  goal.trajectory.joint_names.push_back("arm_2_joint");
  goal.trajectory.joint_names.push_back("arm_3_joint");
  goal.trajectory.joint_names.push_back("arm_4_joint");
  goal.trajectory.joint_names.push_back("arm_5_joint");
  goal.trajectory.joint_names.push_back("arm_6_joint");
  goal.trajectory.joint_names.push_back("arm_7_joint");

  // Two waypoints in this goal trajectory
  goal.trajectory.points.resize(2);

  // First trajectory point
  // Positions
  int index = 0;
  goal.trajectory.points[index].positions.resize(7);
  goal.trajectory.points[index].positions[0] = 0.2;
  goal.trajectory.points[index].positions[1] = 0.0;
  goal.trajectory.points[index].positions[2] = -1.5;
  goal.trajectory.points[index].positions[3] = 1.94;
  goal.trajectory.points[index].positions[4] = -1.57;
  goal.trajectory.points[index].positions[5] = -0.5;
  goal.trajectory.points[index].positions[6] = 0.0;
  // Velocities
  goal.trajectory.points[index].velocities.resize(7);
  for (int j = 0; j < 7; ++j)
  {
    goal.trajectory.points[index].velocities[j] = 1.0;
  }
  // To be reached 2 second after starting along the trajectory
  goal.trajectory.points[index].time_from_start = ros::Duration(2.0);

  // Second trajectory point
  // Positions
  index += 1;
  goal.trajectory.points[index].positions.resize(7);
  goal.trajectory.points[index].positions[0] = 2.5;
  goal.trajectory.points[index].positions[1] = 0.2;
  goal.trajectory.points[index].positions[2] = -2.1;
  goal.trajectory.points[index].positions[3] = 1.9;
  goal.trajectory.points[index].positions[4] = 1.0;
  goal.trajectory.points[index].positions[5] = -0.5;
  goal.trajectory.points[index].positions[6] = 0.0;
  // Velocities
  goal.trajectory.points[index].velocities.resize(7);
  for (int j = 0; j < 7; ++j)
  {
    goal.trajectory.points[index].velocities[j] = 0.0;
  }
  // To be reached 4 seconds after starting along the trajectory
  goal.trajectory.points[index].time_from_start = ros::Duration(4.0);
}

// Entry point
int main(int argc, char** argv)
{
  // Init the ROS node
  ros::init(argc, argv, "run_traj_control");

  ROS_INFO("Starting run_traj_control application ...");

  // Precondition: Valid clock
  ros::NodeHandle nh;
  if (!ros::Time::waitForValid(ros::WallDuration(10.0))) // NOTE: Important when using simulated clock
  {
    ROS_FATAL("Timed-out waiting for valid time.");
    return EXIT_FAILURE;
  }

  // Create an arm controller action client to move the TIAGo's arm
  arm_control_client_Ptr ArmClient;
  createArmClient(ArmClient);

  // Generates the goal for the TIAGo's arm
  control_msgs::FollowJointTrajectoryGoal arm_goal;
  waypoints_arm_goal(arm_goal);

  // Sends the command to start the given trajectory 1s from now
  arm_goal.trajectory.header.stamp = ros::Time::now() + ros::Duration(1.0);
  ArmClient->sendGoal(arm_goal);

  // Wait for trajectory execution
  while(!(ArmClient->getState().isDone()) && ros::ok())
  {
    ros::Duration(4).sleep(); // sleep for four seconds
  }

  return EXIT_SUCCESS;
}


text:
// Copyright 2011-2012 Renato Tegon Forti
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
// Copyright 2015-2016, Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)

// For more information, see http://www.boost.org

// MinGW related workaround
#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION

#include <boost/config.hpp>
#include <boost/dll/alias.hpp>
#include <iostream>
#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/fusion/container.hpp>

#define LIBRARY_API BOOST_SYMBOL_EXPORT

extern "C" void LIBRARY_API say_hello(void);
extern "C" float LIBRARY_API lib_version(void);
extern "C" int LIBRARY_API increment(int);

extern "C" int LIBRARY_API integer_g;
extern "C" const int LIBRARY_API const_integer_g = 777;

namespace foo {
    std::size_t bar(const std::vector<int>& v) {
        return v.size();
    }

    std::size_t variable = 42;
}

// Make sure that aliases have no problems with memory allocations and different types of input parameters
namespace namespace1 { namespace namespace2 { namespace namespace3 {
    typedef
        boost::fusion::vector<std::vector<int>, std::vector<int>, std::vector<int>, const std::vector<int>*, std::vector<int>* >
    do_share_res_t;

    boost::shared_ptr<do_share_res_t> do_share(
            std::vector<int> v1,
            std::vector<int>& v2,
            const std::vector<int>& v3,
            const std::vector<int>* v4,
            std::vector<int>* v5
        )
    {
        v2.back() = 777;
        v5->back() = 9990;
        return boost::make_shared<do_share_res_t>(v1, v2, v3, v4, v5);
    }

    std::string info("I am a std::string from the test_library (Think of me as of 'Hello world'. Long 'Hello world').");

    int& ref_returning_function() {
        static int i = 0;
        return i;
    }
}}}

BOOST_DLL_ALIAS(foo::bar, foo_bar)
BOOST_DLL_ALIAS(foo::variable, foo_variable)
BOOST_DLL_ALIAS(namespace1::namespace2::namespace3::do_share, do_share)
BOOST_DLL_ALIAS(namespace1::namespace2::namespace3::info, info)
BOOST_DLL_ALIAS(const_integer_g, const_integer_g_alias)
BOOST_DLL_ALIAS(namespace1::namespace2::namespace3::ref_returning_function, ref_returning_function)

int integer_g = 100;

void say_hello(void)
{
   std::cout << "Hello, Boost.Application!" << std::endl;
}

float lib_version(void)
{
   return 1.0;
}

int increment(int n)
{
   return ++n;
}

#include <boost/dll/runtime_symbol_info.hpp>

boost::filesystem::path this_module_location_from_itself() {
    return boost::dll::this_line_location();
}

BOOST_DLL_ALIAS(this_module_location_from_itself, module_location_from_itself)

int internal_integer_i = 0xFF0000;
extern "C" LIBRARY_API int& reference_to_internal_integer;
int& reference_to_internal_integer = internal_integer_i;

#ifndef BOOST_NO_RVALUE_REFERENCES
extern "C" LIBRARY_API int&& rvalue_reference_to_internal_integer;
int&& rvalue_reference_to_internal_integer = static_cast<int&&>(internal_integer_i);
#endif


text:
/*
 * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
 */

#include "io/ssl_session.h"

#include <string>

#include <boost/asio.hpp>
#include <boost/bind.hpp>

#include "io/event_manager.h"
#include "io/io_log.h"
#include "io/io_utils.h"

using boost::asio::async_write;
using boost::asio::buffer;
using boost::asio::buffer_cast;
using boost::asio::mutable_buffer;
using boost::asio::mutable_buffers_1;
using boost::asio::null_buffers;
using boost::asio::placeholders::error;
using boost::asio::placeholders::bytes_transferred;
using boost::asio::ssl::stream_base;
using boost::bind;
using boost::function;
using boost::system::error_code;
using std::size_t;
using std::srand;
using std::string;
using std::time;

class SslSession::SslReader : public Task {
public:
    typedef function<void(Buffer)> ReadHandler;

    SslReader(int task_id, SslSessionPtr session, ReadHandler read_fn,
              Buffer buffer)
       : Task(task_id, session->GetSessionInstance()),
         session_(session), read_fn_(read_fn), buffer_(buffer) {
    }
    virtual bool Run() {
        if (session_->IsEstablished()) {
            session_->ssl_last_read_len_ = BufferSize(buffer_);
            read_fn_(buffer_);
            if (session_->IsReaderDeferred()) {
                // Update socket read block count.
                session_->stats_.read_block_start_time = UTCTimestampUsec();
                session_->stats_.read_blocked++;
                session_->server()->stats_.read_blocked++;
            } else {
                if (session_->IsSslDisabled()) {
                     session_->AsyncReadStart();
                } else if (!session_->IsSslHandShakeInProgress()) {
                    session_->AsyncReadStart();
                }
            }
        }
        return true;
    }
    string Description() const { return "SslSession::SslReader"; }

private:
    SslSessionPtr session_;
    ReadHandler read_fn_;
    Buffer buffer_;
};

SslSession::SslSession(SslServer *server, SslSocket *ssl_socket,
                       bool async_read_ready)
    : TcpSession(server, NULL, async_read_ready),
      ssl_socket_(ssl_socket),
      ssl_handshake_in_progress_(false),
      ssl_handshake_success_(false),
      ssl_enabled_(true),
      ssl_handshake_delayed_(false),
      ssl_last_read_len_(0) {

    if (server) {
        ssl_enabled_ = server->ssl_enabled_;
        ssl_handshake_delayed_ = server->ssl_handshake_delayed_;
    }
}

SslSession::~SslSession() {
}

Task* SslSession::CreateReaderTask(mutable_buffer buffer,
                                   size_t bytes_transferred) {
    Buffer rdbuf(buffer_cast<const uint8_t *>(buffer), bytes_transferred);
    SslReader *task = new SslReader(this->reader_task_id(),
        SslSessionPtr(this), bind(&SslSession::OnRead, this, _1), rdbuf);
    return (task);
}

TcpSession::Socket *SslSession::socket() const {
    if (ssl_socket_) {
        // return tcp socket
        return &ssl_socket_->next_layer();
    }
    return NULL;
}

// Register for data read notification from the tcp socket or from the ssl
// socket, as appropriate.
void SslSession::AsyncReadSome() {
    if (established()) {
        if (ssl_last_read_len_ == 0) {
            // we have drained the read buffer of the socket
            // register for a read notification from the tcp socket
            TcpSession::AsyncReadSome();
        } else {
            // trigger Async Read Handler for immediate read
            TriggerAsyncReadHandler();
        }
    }
}

// Tests with large data have consistently shown 16K as the maximum read data
// size even though when a lot more data was available in the underlying socket.
// Also, there is no available() api for the ssl socket.
size_t SslSession::GetReadBufferSize() const {
    return kDefaultBufferSize;
}

//
// Check if a socker error is hard and fatal. Only then should we close the
// socket. Soft errors like EINTR and EAGAIN should be ignored or properly
// handled with retries
//
bool SslSession::IsSocketErrorHard(const error_code &ec) {

    bool error;
    error = TcpSession::IsSocketErrorHard(ec);
    if (ec.value() == ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ)) {
        error = false;
    }

    return error;
}

size_t SslSession::ReadSome(mutable_buffer buffer, error_code *error) {
    // Read data from the tcp socket or from the ssl socket, as appropriate.
    assert(!ssl_handshake_in_progress_);
    if (!IsSslHandShakeSuccessLocked())
        return TcpSession::ReadSome(buffer, error);

    return ssl_socket_->read_some(mutable_buffers_1(buffer), *error);
}

void SslSession::AsyncWrite(const uint8_t *data, size_t size) {
    if (IsSslHandShakeSuccessLocked()) {
        async_write(*ssl_socket_.get(), buffer(data, size),
            bind(&TcpSession::AsyncWriteHandler,
                 TcpSessionPtr(this), error, bytes_transferred));
    } else {
        return (TcpSession::AsyncWrite(data, size));
    }
}

void SslSession::SslHandShakeCallback(SslHandShakeCallbackHandler cb,
                                      SslSessionPtr session,
                                      const error_code &error) {
    session->ssl_handshake_in_progress_ = false;
    if (!error) {
        session->SetSslHandShakeSuccess();
    } else {
        session->SetSslHandShakeFailure();
    }

    if (session->socket() != NULL && !(session->IsClosed())) {
        cb(session, error);
    }
}

void SslSession::TriggerSslHandShakeInternal(
        SslSessionPtr session, SslHandShakeCallbackHandler cb) {
    srand(static_cast<unsigned>(time(0)));
    error_code ec;
    session->ssl_handshake_in_progress_ = true;
    if (session->IsServerSession()) {
        session->ssl_socket_->async_handshake(stream_base::server,
            bind(&SslSession::SslHandShakeCallback, cb, session,
            error));
    } else {
        session->ssl_socket_->async_handshake(stream_base::client,
            bind(&SslSession::SslHandShakeCallback, cb, session,
                 error));
    }
}

void SslSession::TriggerSslHandShake(SslHandShakeCallbackHandler cb) {
    server()->event_manager()->io_service()->post(
        bind(&TriggerSslHandShakeInternal, SslSessionPtr(this), cb));
}

ext: cc

max_stars_repo_name: atsgen/tf-common

max_issues_repo_name: atsgen/tf-common

max_forks_repo_name: atsgen/tf-common


text:
//
//=======================================================================
// Copyright 1997-2001 University of Notre Dame.
// Copyright 2009 Trustees of Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
//

#ifndef BOOST_INCREMENTAL_COMPONENTS_HPP
#define BOOST_INCREMENTAL_COMPONENTS_HPP

#include <boost/detail/iterator.hpp>
#include <boost/graph/detail/incremental_components.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/make_shared.hpp>
#include <boost/pending/disjoint_sets.hpp>
#include <iterator>

namespace boost {

  // A connected component algorithm for the case when dynamically
  // adding (but not removing) edges is common.  The
  // incremental_components() function is a preparing operation. Call
  // same_component to check whether two vertices are in the same
  // component, or use disjoint_set::find_set to determine the
  // representative for a vertex.

  // This version of connected components does not require a full
  // Graph. Instead, it just needs an edge list, where the vertices of
  // each edge need to be of integer type. The edges are assumed to
  // be undirected. The other difference is that the result is stored in
  // a container, instead of just a decorator.  The container should be
  // empty before the algorithm is called. It will grow during the
  // course of the algorithm. The container must be a model of
  // BackInsertionSequence and RandomAccessContainer
  // (std::vector is a good choice). After running the algorithm the
  // index container will map each vertex to the representative
  // vertex of the component to which it belongs.
  //
  // Adapted from an implementation by Alex Stepanov. The disjoint
  // sets data structure is from Tarjan's "Data Structures and Network
  // Algorithms", and the application to connected components is
  // similar to the algorithm described in Ch. 22 of "Intro to
  // Algorithms" by Cormen, et. all.
  //

  // An implementation of disjoint sets can be found in
  // boost/pending/disjoint_sets.hpp

  template <class EdgeListGraph, class DisjointSets>
  void incremental_components(EdgeListGraph& g, DisjointSets& ds)
  {
    typename graph_traits<EdgeListGraph>::edge_iterator e, end;
    for (boost::tie(e,end) = edges(g); e != end; ++e)
      ds.union_set(source(*e,g),target(*e,g));
  }

  template <class ParentIterator>
  void compress_components(ParentIterator first, ParentIterator last)
  {
    for (ParentIterator current = first; current != last; ++current)
      detail::find_representative_with_full_compression(first, current-first);
  }

  template <class ParentIterator>
  typename boost::detail::iterator_traits<ParentIterator>::difference_type
  component_count(ParentIterator first, ParentIterator last)
  {
    std::ptrdiff_t count = 0;
    for (ParentIterator current = first; current != last; ++current)
      if (*current == current - first) ++count;
    return count;
  }

  // This algorithm can be applied to the result container of the
  // connected_components algorithm to normalize
  // the components.
  template <class ParentIterator>
  void normalize_components(ParentIterator first, ParentIterator last)
  {
    for (ParentIterator current = first; current != last; ++current)
      detail::normalize_node(first, current - first);
  }

  template <class VertexListGraph, class DisjointSets>
  void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds)
  {
    typename graph_traits<VertexListGraph>
      ::vertex_iterator v, vend;
    for (boost::tie(v, vend) = vertices(G); v != vend; ++v)
      ds.make_set(*v);
  }

  template <class Vertex, class DisjointSet>
  inline bool same_component(Vertex u, Vertex v, DisjointSet& ds)
  {
    return ds.find_set(u) == ds.find_set(v);
  }

  // Class that builds a quick-access indexed linked list that allows
  // for fast iterating through a parent component's children.
  template <typename IndexType>
  class component_index {

  private:
    typedef std::vector<IndexType> IndexContainer;

  public:
    typedef counting_iterator<IndexType> iterator;
    typedef iterator const_iterator;
    typedef IndexType value_type;
    typedef IndexType size_type;

    typedef detail::component_index_iterator<typename IndexContainer::iterator>
      component_iterator;

  public:
    template <typename ParentIterator,
              typename ElementIndexMap>
    component_index(ParentIterator parent_start,
                    ParentIterator parent_end,
                    const ElementIndexMap& index_map) :
      m_num_elements(std::distance(parent_start, parent_end)),
      m_components(make_shared<IndexContainer>()),
      m_index_list(make_shared<IndexContainer>(m_num_elements)) {

      build_index_lists(parent_start, index_map);

    } // component_index

    template <typename ParentIterator>
    component_index(ParentIterator parent_start,
                    ParentIterator parent_end) :
      m_num_elements(std::distance(parent_start, parent_end)),
      m_components(make_shared<IndexContainer>()),
      m_index_list(make_shared<IndexContainer>(m_num_elements)) {

      build_index_lists(parent_start, boost::identity_property_map());

    } // component_index

    // Returns the number of components
    inline std::size_t size() const {
      return (m_components->size());
    }

    // Beginning iterator for component indices
    iterator begin() const {
      return (iterator(0));
    }

    // End iterator for component indices
    iterator end() const {
      return (iterator(this->size()));
    }

    // Returns a pair of begin and end iterators for the child
    // elements of component [component_index].
    std::pair<component_iterator, component_iterator>
    operator[](IndexType component_index) const {

      IndexType first_index = (*m_components)[component_index];

      return (std::make_pair
              (component_iterator(m_index_list->begin(), first_index),
               component_iterator(m_num_elements)));
    }

  private:
    template <typename ParentIterator,
              typename ElementIndexMap>
    void build_index_lists(ParentIterator parent_start,
                           const ElementIndexMap& index_map) {

      typedef typename std::iterator_traits<ParentIterator>::value_type Element;
      typename IndexContainer::iterator index_list =
        m_index_list->begin();

      // First pass - find root elements, construct index list
      for (IndexType element_index = 0; element_index < m_num_elements;
           ++element_index) {

        Element parent_element = parent_start[element_index];
        IndexType parent_index = get(index_map, parent_element);

        if (element_index != parent_index) {
          index_list[element_index] = parent_index;
        }
        else {
          m_components->push_back(element_index);

          // m_num_elements is the linked list terminator
          index_list[element_index] = m_num_elements;
        }
      }

      // Second pass - build linked list
      for (IndexType element_index = 0; element_index < m_num_elements;
           ++element_index) {

        Element parent_element = parent_start[element_index];
        IndexType parent_index = get(index_map, parent_element);

        if (element_index != parent_index) {

          // Follow list until a component parent is found
          while (index_list[parent_index] != m_num_elements) {
            parent_index = index_list[parent_index];
          }

          // Push element to the front of the linked list
          index_list[element_index] = index_list[parent_index];
          index_list[parent_index] = element_index;
        }
      }

    } // build_index_lists

  protected:
    IndexType m_num_elements;
    shared_ptr<IndexContainer> m_components, m_index_list;

  }; // class component_index

} // namespace boost

#endif // BOOST_INCREMENTAL_COMPONENTS_HPP


text:
/**
 * @file ltl2fsm/representation/Graphviz_Representation.hpp
 *
 * $Id$
 *
 * @author Oliver Arafat
 *
 * @brief @ref
 *
 * @note DOCUMENTED
 *
 * @test
 *
 * @todo Documentation
 */

#ifndef LTL2FSM__REPRESENTATION__GRAPHVIZ_REPRESENTATION__HPP
#define LTL2FSM__REPRESENTATION__GRAPHVIZ_REPRESENTATION__HPP

#include <ltl2fsm/base/config.hpp>

#include <iostream>

// Boost graph library
#include <boost/graph/graphviz.hpp>
#include <boost/graph/strong_components.hpp>

LTL2FSM__BEGIN__NAMESPACE__LTL2FSM;

/**
 * @class Graphviz_Representation
 *
 * @brief A Graphviz_Representation holds all relevant datastructures
 * of @ref ::boost::GraphvizDigraph. It is used to model automata that
 * are based on a graphviz description.
 *
 * A Graphviz_Representation can be used as a concrete representation
 * of @ref Automaton.
 *
 * @nosubgrouping
 */
class Graphviz_Representation
{
    ////////////////////////////////////////////////////////////////////////////////
    /**
     * @name Creation / Destruction
     * @{
     */
private:
    typedef Graphviz_Representation Self;

public:
    explicit Graphviz_Representation(::boost::GraphvizDigraph const & graph);
    Graphviz_Representation(Self const & other);
    Graphviz_Representation & operator=(Self const & other);
    ~Graphviz_Representation();
    // @}

    ////////////////////////////////////////////////////////////////////////////////
    /**
     * @name Types
     * @{
     */
public:
    typedef ::boost::graph_traits< ::boost::GraphvizDigraph>::out_edge_iterator Out_Edge_Iterator_t;
    typedef ::boost::graph_traits< ::boost::GraphvizDigraph>::edge_iterator Edge_Iterator_t;
    typedef ::boost::graph_traits< ::boost::GraphvizDigraph>::vertex_iterator Vertex_Iterator_t;
    typedef ::boost::graph_traits< ::boost::GraphvizDigraph>::vertex_descriptor Vertex_Descriptor_t;
    typedef ::boost::graph_traits< ::boost::GraphvizDigraph>::edge_descriptor Edge_Descriptor_t;
    typedef ::boost::property_map< ::boost::GraphvizDigraph, ::boost::vertex_attribute_t>::type Property_Vertex_Map_t;
    typedef ::boost::property_map< ::boost::GraphvizDigraph, ::boost::edge_attribute_t>::type Property_Edge_Map_t;
    typedef ::std::pair<Out_Edge_Iterator_t, Out_Edge_Iterator_t> Out_Edge_Iterator_Pair_t;
    typedef ::std::pair<Vertex_Iterator_t, Vertex_Iterator_t> Vertex_Iterator_Pair_t;
    typedef ::std::pair<Edge_Iterator_t, Edge_Iterator_t> Edge_Iterator_Pair_t;
    typedef ::std::map<Vertex_Descriptor_t, int> Strong_Components_t;
    typedef ::boost::GraphvizDigraph Graph_t;
    // @}

    ////////////////////////////////////////////////////////////////////////////////
    /**
     * @name Field access
     * @{
     */
public:
    Vertex_Iterator_Pair_t vertex_pair();
    Edge_Iterator_Pair_t edge_pair();
    Property_Vertex_Map_t const & property_vertex_map();
    Property_Edge_Map_t const & property_edge_map();
    // @}

    ////////////////////////////////////////////////////////////////////////////////
    /**
     * @name Automaton construction
     * @{
     */
public:
    /**
     * @brief Returns a vertex descriptor for the new vertex.
     *
     * The Property_Vertex_Map_t is initialized with all neccessary
     * attributes that are needed during the conversion process.
     * By default, "label" is set to "unnamed", "peripheries" is set to "1".
     *
     * Additionally, specific labels, such as "shape" and "fontname"
     * are added.  They are not directly needed for the conversion
     * process but for a correct dot-format output.
     */
    Vertex_Descriptor_t add_vertex();

    /**
     * @brief Returns an edge descriptor for the new edge.
     *
     * The Property_Edge_Map_t is initialized with all neccessary
     * attributes that are needed during the conversion process. By
     * default, "label" is set to "unnamed".
     *
     * Additionally, specific labels, such as "fontname" are
     * added. They are not directly needed for the conversion process
     * but for a correct dot-format output.
     *
     * The graphviz representation allows it to add multiple edges with
     * the same source and target vertex.
     */
    Edge_Descriptor_t add_edge(Vertex_Descriptor_t const & source,
			       Vertex_Descriptor_t const & target);

    /**
     * @brief Sets the attribute 'label' of vertex @a v to @a name.
     */
    void set_label(Vertex_Descriptor_t const & v,
		   ::std::string const & name);

    /**
     * @brief Sets the attribute 'label' of edge @a e to @a name.
     */
    void set_label(Edge_Descriptor_t const & e,
		   ::std::string const & name);

    /**
     * @brief Sets vertex @a v to an accepting state.
     */
    void set_accepting(Vertex_Descriptor_t const & v);

    /**
     * @brief Returns a ::std::pair of Out_Edge_Iterator_t, i.e. all
     * outgoing edges from vertex @a v.
     */
    Out_Edge_Iterator_Pair_t out_edges(Vertex_Descriptor_t const & v);

    /**
     * @brief Returns the vertex that is the target of @a e.
     */
    Vertex_Descriptor_t const target(Edge_Descriptor_t const & e);

    /**
     * @brief Marks the state @v as top (peripheries=3).
     */
    void set_top(Vertex_Descriptor_t const & v);

    /**
     * @brief Marks the state @v as bottom (peripheries=4).
     */
    void set_bottom(Vertex_Descriptor_t const & v);

    /**
     * @brief Marks the state @v as inconclusive (peripheries=5).
     */
    void set_inconclusive(Vertex_Descriptor_t const & v);
    // @}

    ////////////////////////////////////////////////////////////////////////////////
    /**
     * @name Automaton properties
     * @{
     */
public:
    /**
     * @brief Returns true if vertex @a v is an accepting state, false
     * if it is a non accepting state.
     */
    bool accepting(Vertex_Descriptor_t const & v);

    /**
     * @brief Returns true if @a v is not element of the set of
     * accepting states of the DFA that corresponds to some negated
     * ltl formula p.
     */
    bool top(Vertex_Descriptor_t const & v);

    /**
     * @brief Returns true if @a v is not element of the set of
     * accepting states of the DFA that corresponds to some ltl
     * formula p.
     */
    bool bottom(Vertex_Descriptor_t const & v);

    /**
     * @brief Returns true if @a v is both element of the set of
     * accepting states of a DFA that corresponds to some ltl formula
     * 'p' and of a DFA that corresponds to '!p'.
     */
    bool inconclusive(Vertex_Descriptor_t const & v);

    /**
     * @brief Returns the label of the vertex @a v.
     */
    ::std::string const & vertex_label(Vertex_Descriptor_t const & v);

    /**
     * @brief Returns the label of the edge @a e.
     */
    ::std::string const & edge_label(Edge_Descriptor_t const & e);

    /**
     * @brief This method initializes @ component, i.e. it associates
     * to every vertex its strongly connected component id it belongs
     * to.
     */
    void strong_components(Strong_Components_t & component);

    /**
     * @brief Returns the vertex descriptor of the vertex with name @a name.
     *
     * @note It is assumed, that every name of a vertex is unique,
     * i.e. there do not exist two vertices within the same graph with
     * the same name.
     *
     * @throws Invalid_Vertex_Name
     */
    Vertex_Descriptor_t const & vertex_descriptor(::std::string const & name);
    // @}

    ////////////////////////////////////////////////////////////////////////////////
    /**
     * @name State
     * @{
     */
private:
    /**
     * @brief The @ref ::boost::GraphvizDigraph object that stores the
     * automaton structure.
     */
    Graph_t m_graph;

    /**
     * @brief A Prop_Vertex_Map_t stores all vertex labels that
     * are defined in the graphviz description.
     */
    Property_Vertex_Map_t m_vertex_map;

    /**
     * @brief A Prop_Edge_Map_t stores all edge labels that
     * are defined in the graphviz description.
     */
    Property_Edge_Map_t m_edge_map;

    /**
     * @brief A ::std::pair of Vertex_Iterator_Pair_t. The first
     * iterator points to the first vertex in the sequence, the second
     * to the last one.
     */
    Vertex_Iterator_Pair_t m_vertex_iterator_pair;

    /**
     * @brief A ::std::pair of Edge_Iterator_Pair_t. The first
     * iterator points to the first edge in the sequence, the second
     * to the last one.
     */
    Edge_Iterator_Pair_t m_edge_iterator_pair;
    // @}

#if LTL2FSM_DEBUG__LEVEL__ > 1
public:
    void m_class_invariance() const;
#endif
};

LTL2FSM__END__NAMESPACE__LTL2FSM;

#endif


text:
// ===================================================================
//
// Description
//		Contains the implementation of UserProperties
//
// Revision history
//		Date			Description
//		30-Nov-2012		First version
//
// ===================================================================
#include "UserProperties.h"
#include <boost/exception/exception.hpp>
#include <boost/exception/all.hpp>

namespace Sfs2X {
namespace Entities {
namespace Match {

boost::shared_ptr<string> UserProperties::NAME (new string("${N}"));
boost::shared_ptr<string> UserProperties::IS_PLAYER (new string("${ISP}"));
boost::shared_ptr<string> UserProperties::IS_SPECTATOR (new string("${ISS}"));
boost::shared_ptr<string> UserProperties::IS_NPC (new string("${ISN}"));
boost::shared_ptr<string> UserProperties::PRIVILEGE_ID (new string("${PRID}"));
boost::shared_ptr<string> UserProperties::IS_IN_ANY_ROOM (new string("${IAR}"));

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
UserProperties::UserProperties()
{
	boost::throw_exception(boost::enable_error_info (std::runtime_error("This class cannot be instantiated")));
}

}	// namespace Match
}	// namespace Entities
}	// namespace Sfs2X