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

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

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

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

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

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

#define WET_TEXT ""
#define WET_LONGTEXT ""

#define DRY_TEXT ""
#define DRY_LONGTEXT ""

#define DAMP_TEXT ""
#define DAMP_LONGTEXT ""

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

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

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

} aout_filter_sys_t;

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

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

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

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

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

    if ( ! b_fit )
    {
        return VLC_EGENERIC;
    }

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

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

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

    return VLC_SUCCESS;
}

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

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

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

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

    for( i = 0; i < 5 ; i ++ )
        var_Create( p_aout, psz_control_names[i], VLC_VAR_FLOAT
                            | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );

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

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

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

    return VLC_SUCCESS;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#define WET_TEXT ""
#define WET_LONGTEXT ""

#define DRY_TEXT ""
#define DRY_LONGTEXT ""

#define DAMP_TEXT ""
#define DAMP_LONGTEXT ""

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

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

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

};

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

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

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

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

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

    if ( ! b_fit )
    {
        return VLC_EGENERIC;
    }

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

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

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

    return VLC_SUCCESS;
}

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

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

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

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

    for( i = 0; i < 5 ; i ++ )
        var_Create( p_aout, psz_control_names[i], VLC_VAR_FLOAT
                            | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );

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

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

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

    return VLC_SUCCESS;
}

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

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

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

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

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

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

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

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

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

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

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

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

<|endoftext|>


<commit_before>// kmidentity.cpp

#include "kmidentity.h"
#include "kfileio.h"
#include "kmfolder.h"
#include "kmfoldermgr.h"
#include "kmkernel.h"

#include <kdebug.h>
#include <kapplication.h>
#include <kurl.h>
#include <klocale.h>
#include <ktempfile.h>
#include <kmessagebox.h>
#include <kprocess.h>
#include <kconfig.h>

#include <qstringlist.h>
#include <qfileinfo.h>
#include <qdatastream.h>

#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>

Signature::Signature()
  : mType( Disabled )
{

}

Signature::Signature( const QString & text )
  : mText( text ),
    mType( Inlined )
{

}

Signature::Signature( const QString & url, bool isExecutable )
  : mUrl( url ),
    mType( isExecutable ? FromCommand : FromFile )
{
}

bool Signature::operator==( const Signature & other ) const {
  if ( mType != other.mType ) return false;
  switch ( mType ) {
  case Inlined: return mText == other.mText;
  case FromFile:
  case FromCommand: return mUrl == other.mUrl;
  default:
  case Disabled: return true;
  }
}

QString Signature::rawText( bool * ok ) const
{
  switch ( mType ) {
  case Disabled:
    if ( ok ) *ok = true;
    return QString::null;
  case Inlined:
    if ( ok ) *ok = true;
    return mText;
  case FromFile:
    return textFromFile( ok );
  case FromCommand:
    return textFromCommand( ok );
  };
  kdFatal( 5006 ) << "Signature::type() returned unknown value!" << endl;
  return QString::null; // make compiler happy
}

QString Signature::textFromCommand( bool * ok ) const
{
  assert( mType == FromCommand );

  // handle pathological cases:
  if ( mUrl.isEmpty() ) {
    if ( ok ) *ok = true;
    return QString::null;
  }

  // create a shell process:
#if KDE_VERSION >= 305
  KProcess proc;
  proc.setUseShell(true);
#else
  KShellProcess proc;
#endif
  proc << mUrl;

  // let the kernel collect the output for us:
  QObject::connect( &proc, SIGNAL(receivedStdout(KProcess*,char*,int)),
		    kernel, SLOT(slotCollectStdOut(KProcess*,char*,int)) );

  // run the process:
  int rc = 0;
  if ( !proc.start( KProcess::Block, KProcess::Stdout ) )
    rc = -1;
  else
    rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ;

  // get output:
  QByteArray output = kernel->getCollectedStdOut( &proc );

  // handle errors, if any:
  if ( rc != 0 ) {
    if ( ok ) *ok = false;
    QString wmsg = i18n("Failed to execute signature script\n%1:\n%2")
      .arg( mUrl ).arg( strerror(rc) );
    KMessageBox::error(0, wmsg);
    return QString::null;
  }

  // no errors:
  if ( ok ) *ok = true;
  // ### hmm, should we allow other encodings, too?
  return QString::fromLocal8Bit( output.data(), output.size() );
}

QString Signature::textFromFile( bool * ok ) const
{
  assert( mType == FromFile );

  // ### FIXME: Use KIO::NetAccess to download non-local files!
  if ( !KURL(mUrl).isLocalFile() && !(QFileInfo(mUrl).isRelative()
					&& QFileInfo(mUrl).exists()) ) {
    kdDebug( 5006 ) << "Signature::textFromFile: non-local URLs are unsupported" << endl;
    if ( ok ) *ok = false;
    return QString::null;
  }
  if ( ok ) *ok = true;
  // ### hmm, should we allow other encodings, too?
  return QString::fromLocal8Bit( kFileToString( mUrl ) );
}

QString Signature::withSeparator( bool * ok ) const
{
  bool internalOK = false;
  QString signature = rawText( &internalOK );
  if ( !internalOK ) {
    if ( ok ) *ok = false;
    return QString::null;
  }
  if ( ok ) *ok = true;
  if ( signature.isEmpty() ) return signature; // don't add a separator in this case
  if ( signature.startsWith( QString::fromLatin1("-- \n") ) ||
       signature.find( QString::fromLatin1("\n-- \n") ) != -1 )
    // already have signature separator:
    return signature;
  else
    // need to prepend one:
    return QString::fromLatin1("-- \n") + signature;
}

void Signature::setUrl( const QString & url, bool isExecutable )
{
  mUrl = url;
  mType = isExecutable ? FromCommand : FromFile ;
}

// config keys and values:
static const char * sigTypeKey = "Signature Type";
static const char * sigTypeInlineValue = "inline";
static const char * sigTypeFileValue = "file";
static const char * sigTypeCommandValue = "command";
static const char * sigTypeDisabledValue = "disabled";
static const char * sigTextKey = "Inline Signature";
static const char * sigFileKey = "Signature File";
static const char * sigCommandKey = "Signature Command";

void Signature::readConfig( const KConfigBase * config )
{
  QString sigType = config->readEntry( sigTypeKey );
  if ( sigType == sigTypeInlineValue ) {
    mType = Inlined;
    mText = config->readEntry( sigTextKey );
  } else if ( sigType == sigTypeFileValue ) {
    mType = FromFile;
    mUrl = config->readEntry( sigFileKey );
  } else if ( sigType == sigTypeCommandValue ) {
    mType = FromCommand;
    mUrl = config->readEntry( sigCommandKey );
  } else {
    mType = Disabled;
  }
}

void Signature::writeConfig( KConfigBase * config ) const
{
  switch ( mType ) {
  case Inlined:
    config->writeEntry( sigTypeKey, sigTypeInlineValue );
    config->writeEntry( sigTextKey, mText );
    break;
  case FromFile:
    config->writeEntry( sigTypeKey, sigTypeFileValue );
    config->writeEntry( sigFileKey, mUrl );
    break;
  case FromCommand:
    config->writeEntry( sigTypeKey, sigTypeCommandValue );
    config->writeEntry( sigCommandKey, mUrl );
    break;
  case Disabled:
    config->writeEntry( sigTypeKey, sigTypeDisabledValue );
  default: ;
  }
}

QDataStream & operator<<( QDataStream & stream, const Signature & sig ) {
  return stream << static_cast<Q_UINT8>(sig.mType)
		<< sig.mUrl
		<< sig.mText;
}

QDataStream & operator>>( QDataStream & stream, Signature & sig ) {
  Q_UINT8 s;
  stream >> s
         >> sig.mUrl
         >> sig.mText;
  sig.mType = static_cast<Signature::Type>(s);
  return stream;
}

KMIdentity KMIdentity::null;

bool KMIdentity::isNull() const {
  return mIdentity.isNull() && mFullName.isNull() && mEmailAddr.isNull() &&
    mOrganization.isNull() && mReplyToAddr.isNull() && mBcc.isNull() &&
    mVCardFile.isNull() &&
    mPgpIdentity.isNull() && mFcc.isNull() && mDrafts.isNull() &&
    mTransport.isNull() && mSignature.type() == Signature::Disabled;
}

bool KMIdentity::operator==( const KMIdentity & other ) const {
    return mUoid == other.mUoid &&
      mIdentity == other.mIdentity && mFullName == other.mFullName &&
      mEmailAddr == other.mEmailAddr && mOrganization == other.mOrganization &&
      mReplyToAddr == other.mReplyToAddr && mBcc == other.mBcc &&
      mVCardFile == other.mVCardFile &&
      mPgpIdentity == other.mPgpIdentity && mFcc == other.mFcc &&
      mDrafts == other.mDrafts && mTransport == other.mTransport &&
      mSignature == other.mSignature;
}

KMIdentity::KMIdentity( const QString & id, const QString & fullName,
			const QString & emailAddr, const QString & organization,
			const QString & replyToAddr )
  : mUoid( 0 ), mIdentity( id ), mFullName( fullName ),
    mEmailAddr( emailAddr ), mOrganization( organization ),
    mReplyToAddr( replyToAddr ), mIsDefault( false )
{

}

KMIdentity::~KMIdentity()
{
}

void KMIdentity::readConfig( const KConfigBase * config )
{
  mUoid = config->readUnsignedNumEntry("uoid",0);

  mIdentity = config->readEntry("Identity");
  mFullName = config->readEntry("Name");
  mEmailAddr = config->readEntry("Email Address");
  mVCardFile = config->readEntry("VCardFile");
  mOrganization = config->readEntry("Organization");
  mPgpIdentity = config->readEntry("Default PGP Key").local8Bit();
  mReplyToAddr = config->readEntry("Reply-To Address");
  mBcc = config->readEntry("Bcc");
  mFcc = config->readEntry("Fcc");
  mDrafts = config->readEntry("Drafts");
  mTransport = config->readEntry("Transport");

  mSignature.readConfig( config );
  kdDebug() << "KMIdentity::readConfig(): UOID = " << mUoid
	    << " for identity named \"" << mIdentity << "\"" << endl;
}

void KMIdentity::writeConfig( KConfigBase * config ) const
{
  config->writeEntry("uoid", mUoid);

  config->writeEntry("Identity", mIdentity);
  config->writeEntry("Name", mFullName);
  config->writeEntry("Organization", mOrganization);
  config->writeEntry("Default PGP Key", mPgpIdentity.data());
  config->writeEntry("Email Address", mEmailAddr);
  config->writeEntry("Reply-To Address", mReplyToAddr);
  config->writeEntry("Bcc", mBcc);
  config->writeEntry("VCardFile", mVCardFile);
  config->writeEntry("Transport", mTransport);
  config->writeEntry("Fcc", mFcc);
  config->writeEntry("Drafts", mDrafts);

  mSignature.writeConfig( config );
}

QDataStream & operator<<( QDataStream & stream, const KMIdentity & i ) {
  return stream << static_cast<Q_UINT32>(i.uoid())
		<< i.identityName()
		<< i.fullName()
		<< i.organization()
		<< i.pgpIdentity()
		<< i.emailAddr()
		<< i.replyToAddr()
		<< i.bcc()
		<< i.vCardFile()
		<< i.transport()
		<< i.fcc()
		<< i.drafts()
		<< i.mSignature;
}

QDataStream & operator>>( QDataStream & stream, KMIdentity & i ) {
#if 1 // why doesn't it work like for Q_UINT8 above???
  Q_UINT32 uoid;
  stream >> uoid;
  i.mUoid = uoid;
  return stream
#else
  return stream >> (Q_UINT32)i.mUoid
#endif
		>> i.mIdentity
		>> i.mFullName
		>> i.mOrganization
		>> i.mPgpIdentity
		>> i.mEmailAddr
		>> i.mReplyToAddr
		>> i.mBcc
		>> i.mVCardFile
		>> i.mTransport
		>> i.mFcc
		>> i.mDrafts
		>> i.mSignature;
}

//-----------------------------------------------------------------------------
bool KMIdentity::mailingAllowed() const
{
  return !mEmailAddr.isEmpty();
}

void KMIdentity::setIsDefault( bool flag ) {
  mIsDefault = flag;
}

void KMIdentity::setIdentityName( const QString & name ) {
  mIdentity = name;
}

void KMIdentity::setFullName(const QString &str)
{
  mFullName = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setOrganization(const QString &str)
{
  mOrganization = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setPgpIdentity(const QCString &str)
{
  mPgpIdentity = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setEmailAddr(const QString &str)
{
  mEmailAddr = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setVCardFile(const QString &str)
{
  mVCardFile = str;
}

//-----------------------------------------------------------------------------
QString KMIdentity::fullEmailAddr(void) const
{
  if (mFullName.isEmpty()) return mEmailAddr;

  const QString specials("()<>@,.;:[]");

  QString result;

  // add DQUOTE's if necessary:
  bool needsQuotes=false;
  for (unsigned int i=0; i < mFullName.length(); i++) {
    if ( specials.contains( mFullName[i] ) )
      needsQuotes = true;
    else if ( mFullName[i] == '\\' || mFullName[i] == '"' ) {
      needsQuotes = true;
      result += '\\';
    }
    result += mFullName[i];
  }

  if (needsQuotes) {
    result.insert(0,'"');
    result += '"';
  }

  result += " <" + mEmailAddr + '>';

  return result;
}

//-----------------------------------------------------------------------------
void KMIdentity::setReplyToAddr(const QString& str)
{
  mReplyToAddr = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setSignatureFile(const QString &str)
{
  mSignature.setUrl( str, signatureIsCommand() );
}

//-----------------------------------------------------------------------------
void KMIdentity::setSignatureInlineText(const QString &str )
{
  mSignature.setText( str );
}

//-----------------------------------------------------------------------------
void KMIdentity::setTransport(const QString &str)
{
  mTransport = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setFcc(const QString &str)
{
  mFcc = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setDrafts(const QString &str)
{
  mDrafts = str;
}

//-----------------------------------------------------------------------------
QString KMIdentity::signatureText( bool * ok ) const
{
  bool internalOK = false;
  QString signatureText = mSignature.withSeparator( &internalOK );
  if ( internalOK ) {
    if ( ok ) *ok=true;
    return signatureText;
  }

  // OK, here comes the funny part. The call to
  // Signature::withSeparator() failed, so we should probably fix the
  // cause:
  if ( ok ) *ok = false;
  return QString::null;

#if 0 // ### FIXME: error handling
  if (mSignatureFile.endsWith("|"))
  {
  }
  else
  {
  }
#endif

  return QString::null;
}
<commit_msg>Fix bug 50022: kmail warning on no sent-mail folder unneeded and annoying<commit_after>// kmidentity.cpp

#include "kmidentity.h"
#include "kfileio.h"
#include "kmfolder.h"
#include "kmfoldermgr.h"
#include "kmkernel.h"

#include <kdebug.h>
#include <kapplication.h>
#include <kurl.h>
#include <klocale.h>
#include <ktempfile.h>
#include <kmessagebox.h>
#include <kprocess.h>
#include <kconfig.h>

#include <qstringlist.h>
#include <qfileinfo.h>
#include <qdatastream.h>

#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>

Signature::Signature()
  : mType( Disabled )
{

}

Signature::Signature( const QString & text )
  : mText( text ),
    mType( Inlined )
{

}

Signature::Signature( const QString & url, bool isExecutable )
  : mUrl( url ),
    mType( isExecutable ? FromCommand : FromFile )
{
}

bool Signature::operator==( const Signature & other ) const {
  if ( mType != other.mType ) return false;
  switch ( mType ) {
  case Inlined: return mText == other.mText;
  case FromFile:
  case FromCommand: return mUrl == other.mUrl;
  default:
  case Disabled: return true;
  }
}

QString Signature::rawText( bool * ok ) const
{
  switch ( mType ) {
  case Disabled:
    if ( ok ) *ok = true;
    return QString::null;
  case Inlined:
    if ( ok ) *ok = true;
    return mText;
  case FromFile:
    return textFromFile( ok );
  case FromCommand:
    return textFromCommand( ok );
  };
  kdFatal( 5006 ) << "Signature::type() returned unknown value!" << endl;
  return QString::null; // make compiler happy
}

QString Signature::textFromCommand( bool * ok ) const
{
  assert( mType == FromCommand );

  // handle pathological cases:
  if ( mUrl.isEmpty() ) {
    if ( ok ) *ok = true;
    return QString::null;
  }

  // create a shell process:
#if KDE_VERSION >= 305
  KProcess proc;
  proc.setUseShell(true);
#else
  KShellProcess proc;
#endif
  proc << mUrl;

  // let the kernel collect the output for us:
  QObject::connect( &proc, SIGNAL(receivedStdout(KProcess*,char*,int)),
		    kernel, SLOT(slotCollectStdOut(KProcess*,char*,int)) );

  // run the process:
  int rc = 0;
  if ( !proc.start( KProcess::Block, KProcess::Stdout ) )
    rc = -1;
  else
    rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ;

  // get output:
  QByteArray output = kernel->getCollectedStdOut( &proc );

  // handle errors, if any:
  if ( rc != 0 ) {
    if ( ok ) *ok = false;
    QString wmsg = i18n("Failed to execute signature script\n%1:\n%2")
      .arg( mUrl ).arg( strerror(rc) );
    KMessageBox::error(0, wmsg);
    return QString::null;
  }

  // no errors:
  if ( ok ) *ok = true;
  // ### hmm, should we allow other encodings, too?
  return QString::fromLocal8Bit( output.data(), output.size() );
}

QString Signature::textFromFile( bool * ok ) const
{
  assert( mType == FromFile );

  // ### FIXME: Use KIO::NetAccess to download non-local files!
  if ( !KURL(mUrl).isLocalFile() && !(QFileInfo(mUrl).isRelative()
					&& QFileInfo(mUrl).exists()) ) {
    kdDebug( 5006 ) << "Signature::textFromFile: non-local URLs are unsupported" << endl;
    if ( ok ) *ok = false;
    return QString::null;
  }
  if ( ok ) *ok = true;
  // ### hmm, should we allow other encodings, too?
  return QString::fromLocal8Bit( kFileToString( mUrl ) );
}

QString Signature::withSeparator( bool * ok ) const
{
  bool internalOK = false;
  QString signature = rawText( &internalOK );
  if ( !internalOK ) {
    if ( ok ) *ok = false;
    return QString::null;
  }
  if ( ok ) *ok = true;
  if ( signature.isEmpty() ) return signature; // don't add a separator in this case
  if ( signature.startsWith( QString::fromLatin1("-- \n") ) ||
       signature.find( QString::fromLatin1("\n-- \n") ) != -1 )
    // already have signature separator:
    return signature;
  else
    // need to prepend one:
    return QString::fromLatin1("-- \n") + signature;
}

void Signature::setUrl( const QString & url, bool isExecutable )
{
  mUrl = url;
  mType = isExecutable ? FromCommand : FromFile ;
}

// config keys and values:
static const char * sigTypeKey = "Signature Type";
static const char * sigTypeInlineValue = "inline";
static const char * sigTypeFileValue = "file";
static const char * sigTypeCommandValue = "command";
static const char * sigTypeDisabledValue = "disabled";
static const char * sigTextKey = "Inline Signature";
static const char * sigFileKey = "Signature File";
static const char * sigCommandKey = "Signature Command";

void Signature::readConfig( const KConfigBase * config )
{
  QString sigType = config->readEntry( sigTypeKey );
  if ( sigType == sigTypeInlineValue ) {
    mType = Inlined;
    mText = config->readEntry( sigTextKey );
  } else if ( sigType == sigTypeFileValue ) {
    mType = FromFile;
    mUrl = config->readEntry( sigFileKey );
  } else if ( sigType == sigTypeCommandValue ) {
    mType = FromCommand;
    mUrl = config->readEntry( sigCommandKey );
  } else {
    mType = Disabled;
  }
}

void Signature::writeConfig( KConfigBase * config ) const
{
  switch ( mType ) {
  case Inlined:
    config->writeEntry( sigTypeKey, sigTypeInlineValue );
    config->writeEntry( sigTextKey, mText );
    break;
  case FromFile:
    config->writeEntry( sigTypeKey, sigTypeFileValue );
    config->writeEntry( sigFileKey, mUrl );
    break;
  case FromCommand:
    config->writeEntry( sigTypeKey, sigTypeCommandValue );
    config->writeEntry( sigCommandKey, mUrl );
    break;
  case Disabled:
    config->writeEntry( sigTypeKey, sigTypeDisabledValue );
  default: ;
  }
}

QDataStream & operator<<( QDataStream & stream, const Signature & sig ) {
  return stream << static_cast<Q_UINT8>(sig.mType)
		<< sig.mUrl
		<< sig.mText;
}

QDataStream & operator>>( QDataStream & stream, Signature & sig ) {
  Q_UINT8 s;
  stream >> s
         >> sig.mUrl
         >> sig.mText;
  sig.mType = static_cast<Signature::Type>(s);
  return stream;
}

KMIdentity KMIdentity::null;

bool KMIdentity::isNull() const {
  return mIdentity.isNull() && mFullName.isNull() && mEmailAddr.isNull() &&
    mOrganization.isNull() && mReplyToAddr.isNull() && mBcc.isNull() &&
    mVCardFile.isNull() &&
    mPgpIdentity.isNull() && mFcc.isNull() && mDrafts.isNull() &&
    mTransport.isNull() && mSignature.type() == Signature::Disabled;
}

bool KMIdentity::operator==( const KMIdentity & other ) const {
    return mUoid == other.mUoid &&
      mIdentity == other.mIdentity && mFullName == other.mFullName &&
      mEmailAddr == other.mEmailAddr && mOrganization == other.mOrganization &&
      mReplyToAddr == other.mReplyToAddr && mBcc == other.mBcc &&
      mVCardFile == other.mVCardFile &&
      mPgpIdentity == other.mPgpIdentity && mFcc == other.mFcc &&
      mDrafts == other.mDrafts && mTransport == other.mTransport &&
      mSignature == other.mSignature;
}

KMIdentity::KMIdentity( const QString & id, const QString & fullName,
			const QString & emailAddr, const QString & organization,
			const QString & replyToAddr )
  : mUoid( 0 ), mIdentity( id ), mFullName( fullName ),
    mEmailAddr( emailAddr ), mOrganization( organization ),
    mReplyToAddr( replyToAddr ), mIsDefault( false )
{

}

KMIdentity::~KMIdentity()
{
}

void KMIdentity::readConfig( const KConfigBase * config )
{
  mUoid = config->readUnsignedNumEntry("uoid",0);

  mIdentity = config->readEntry("Identity");
  mFullName = config->readEntry("Name");
  mEmailAddr = config->readEntry("Email Address");
  mVCardFile = config->readEntry("VCardFile");
  mOrganization = config->readEntry("Organization");
  mPgpIdentity = config->readEntry("Default PGP Key").local8Bit();
  mReplyToAddr = config->readEntry("Reply-To Address");
  mBcc = config->readEntry("Bcc");
  mFcc = config->readEntry("Fcc", "sent-mail");
  mDrafts = config->readEntry("Drafts", "drafts");
  mTransport = config->readEntry("Transport");

  mSignature.readConfig( config );
  kdDebug() << "KMIdentity::readConfig(): UOID = " << mUoid
	    << " for identity named \"" << mIdentity << "\"" << endl;
}

void KMIdentity::writeConfig( KConfigBase * config ) const
{
  config->writeEntry("uoid", mUoid);

  config->writeEntry("Identity", mIdentity);
  config->writeEntry("Name", mFullName);
  config->writeEntry("Organization", mOrganization);
  config->writeEntry("Default PGP Key", mPgpIdentity.data());
  config->writeEntry("Email Address", mEmailAddr);
  config->writeEntry("Reply-To Address", mReplyToAddr);
  config->writeEntry("Bcc", mBcc);
  config->writeEntry("VCardFile", mVCardFile);
  config->writeEntry("Transport", mTransport);
  config->writeEntry("Fcc", mFcc);
  config->writeEntry("Drafts", mDrafts);

  mSignature.writeConfig( config );
}

QDataStream & operator<<( QDataStream & stream, const KMIdentity & i ) {
  return stream << static_cast<Q_UINT32>(i.uoid())
		<< i.identityName()
		<< i.fullName()
		<< i.organization()
		<< i.pgpIdentity()
		<< i.emailAddr()
		<< i.replyToAddr()
		<< i.bcc()
		<< i.vCardFile()
		<< i.transport()
		<< i.fcc()
		<< i.drafts()
		<< i.mSignature;
}

QDataStream & operator>>( QDataStream & stream, KMIdentity & i ) {
#if 1 // why doesn't it work like for Q_UINT8 above???
  Q_UINT32 uoid;
  stream >> uoid;
  i.mUoid = uoid;
  return stream
#else
  return stream >> (Q_UINT32)i.mUoid
#endif
		>> i.mIdentity
		>> i.mFullName
		>> i.mOrganization
		>> i.mPgpIdentity
		>> i.mEmailAddr
		>> i.mReplyToAddr
		>> i.mBcc
		>> i.mVCardFile
		>> i.mTransport
		>> i.mFcc
		>> i.mDrafts
		>> i.mSignature;
}

//-----------------------------------------------------------------------------
bool KMIdentity::mailingAllowed() const
{
  return !mEmailAddr.isEmpty();
}

void KMIdentity::setIsDefault( bool flag ) {
  mIsDefault = flag;
}

void KMIdentity::setIdentityName( const QString & name ) {
  mIdentity = name;
}

void KMIdentity::setFullName(const QString &str)
{
  mFullName = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setOrganization(const QString &str)
{
  mOrganization = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setPgpIdentity(const QCString &str)
{
  mPgpIdentity = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setEmailAddr(const QString &str)
{
  mEmailAddr = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setVCardFile(const QString &str)
{
  mVCardFile = str;
}

//-----------------------------------------------------------------------------
QString KMIdentity::fullEmailAddr(void) const
{
  if (mFullName.isEmpty()) return mEmailAddr;

  const QString specials("()<>@,.;:[]");

  QString result;

  // add DQUOTE's if necessary:
  bool needsQuotes=false;
  for (unsigned int i=0; i < mFullName.length(); i++) {
    if ( specials.contains( mFullName[i] ) )
      needsQuotes = true;
    else if ( mFullName[i] == '\\' || mFullName[i] == '"' ) {
      needsQuotes = true;
      result += '\\';
    }
    result += mFullName[i];
  }

  if (needsQuotes) {
    result.insert(0,'"');
    result += '"';
  }

  result += " <" + mEmailAddr + '>';

  return result;
}

//-----------------------------------------------------------------------------
void KMIdentity::setReplyToAddr(const QString& str)
{
  mReplyToAddr = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setSignatureFile(const QString &str)
{
  mSignature.setUrl( str, signatureIsCommand() );
}

//-----------------------------------------------------------------------------
void KMIdentity::setSignatureInlineText(const QString &str )
{
  mSignature.setText( str );
}

//-----------------------------------------------------------------------------
void KMIdentity::setTransport(const QString &str)
{
  mTransport = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setFcc(const QString &str)
{
  mFcc = str;
}

//-----------------------------------------------------------------------------
void KMIdentity::setDrafts(const QString &str)
{
  mDrafts = str;
}

//-----------------------------------------------------------------------------
QString KMIdentity::signatureText( bool * ok ) const
{
  bool internalOK = false;
  QString signatureText = mSignature.withSeparator( &internalOK );
  if ( internalOK ) {
    if ( ok ) *ok=true;
    return signatureText;
  }

  // OK, here comes the funny part. The call to
  // Signature::withSeparator() failed, so we should probably fix the
  // cause:
  if ( ok ) *ok = false;
  return QString::null;

#if 0 // ### FIXME: error handling
  if (mSignatureFile.endsWith("|"))
  {
  }
  else
  {
  }
#endif

  return QString::null;
}
<|endoftext|>


<commit_before>/*******************************************************************
 KNotes -- Notes for the KDE project

 Copyright (C) Bernd Johannes Wuebben
     wuebben@math.cornell.edu
     wuebben@kde.org

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*******************************************************************/

#include "knotesapp.h"
#include "knoteconfigdlg.h"

#include <kapp.h>
#include <kwin.h>
#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kstddirs.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <ksimpleconfig.h>

#include <qdir.h>
#include <qfont.h>

KNotesApp::KNotesApp()
    : KSystemTray()
{
    //create the dock widget....
    setPixmap( KGlobal::iconLoader()->loadIcon( "knotes", KIcon::Small ) );

    m_note_menu = new KPopupMenu( this );
    connect( m_note_menu, SIGNAL( aboutToShow() ),
             this,        SLOT( slotPrepareNoteMenu() ) );
    connect( m_note_menu, SIGNAL( activated(int) ),
             this,        SLOT( slotToNote(int) ) );

    KPopupMenu* menu = contextMenu();
    menu->insertItem( i18n("New Note"), this, SLOT(slotNewNote(int)) );
    menu->insertItem( i18n("Preferences..."), this, SLOT(slotPreferences(int)) );
    menu->insertItem( i18n("Notes"), m_note_menu );

    //initialize saved notes, if none create a note...
    QString str_notedir = KGlobal::dirs()->saveLocation( "appdata", "notes/" );
    QDir notedir( str_notedir );
    QStringList notes = notedir.entryList( QDir::Files, QDir::Name ); //doesn't list hidden files

    for( QStringList::Iterator i = notes.begin(); i != notes.end(); ++i )
    {
        QString configfile = notedir.absFilePath( *i );
        KSimpleConfig* tmp = new KSimpleConfig( configfile );
        tmp->setGroup( "General" );
        int version = tmp->readNumEntry( "version", 1 );
        delete tmp;

        KNote* tmpnote = new KNote( configfile, version == 1 );

        connect( tmpnote, SIGNAL( sigRenamed(QString&, QString&) ),
                 this,    SLOT  ( slotNoteRenamed(QString&, QString&) ) );
        connect( tmpnote, SIGNAL( sigNewNote(int) ),
                 this,    SLOT  ( slotNewNote(int) ) );
        connect( tmpnote, SIGNAL( sigKilled(QString) ),
                 this,    SLOT  ( slotNoteKilled(QString) ) );
        m_NoteList.insert( tmpnote->getName(), tmpnote );
    }

    if( m_NoteList.count() == 0 && !kapp->isRestored() )
        slotNewNote();
}

KNotesApp::~KNotesApp()
{
    delete m_note_menu;
    m_NoteList.clear();
}

void KNotesApp::copyDefaultConfig( QString& sc_filename, QString& newname )
{
    QString defaultsfile = KGlobal::dirs()->findResource( "config", "knotesrc" );
    KSimpleConfig defaults( defaultsfile );
    KSimpleConfig sc( sc_filename );

    sc.setGroup( "Display" );
    defaults.setGroup( "Display" );

    uint width  = defaults.readUnsignedNumEntry( "width", 200 );
    uint height = defaults.readUnsignedNumEntry( "height", 200 );
    QColor bgc  = defaults.readColorEntry( "bgcolor", &(Qt::yellow) );
    QColor fgc  = defaults.readColorEntry( "fgcolor", &(Qt::black) );

    sc.writeEntry( "width", width );
    sc.writeEntry( "height", height );
    sc.writeEntry( "bgcolor", bgc );
    sc.writeEntry( "fgcolor", fgc );

    sc.setGroup( "Editor" );
    defaults.setGroup( "Editor" );

    uint tabsize = defaults.readUnsignedNumEntry( "tabsize", 4 );
    bool indent  = defaults.readBoolEntry( "autoindent", true );

    sc.writeEntry( "tabsize", tabsize );
    sc.writeEntry( "autoindent", indent );

    QFont def_font( "helvetica" );
    QFont currfont = defaults.readFontEntry( "font", &def_font );
    sc.writeEntry( "font", currfont );

    sc.setGroup( "Actions" );
    defaults.setGroup( "Actions" );

    QString mailstr  = defaults.readEntry( "mail", "kmail --msg %f" );
    QString printstr = defaults.readEntry( "print", "a2ps -P %p -1 --center-title=%t --underlay=KDE %f" );

    sc.writeEntry( "mail", mailstr );
    sc.writeEntry( "print", printstr );

    sc.setGroup( "General" );
    sc.writeEntry( "version", 2 );

    sc.setGroup( "Data" );
    sc.writeEntry( "name", newname );

    // TODO: write default entries for the group "WindowDisplay"

    sc.sync();
}

void KNotesApp::slotNewNote( int /*id*/ )
{
    QString datadir = KGlobal::dirs()->saveLocation( "appdata", "notes/" );

    //find a new appropriate id for the new note...
    QString thename, configfile;
    QDir appdir( datadir );

    for( int i = 1; ; i++ )
    {
        thename = QString( "KNote %1" ).arg(i);

        if( !appdir.exists( thename ) )
        {
            configfile = appdir.absFilePath( thename );
            break;
        }
    }

    copyDefaultConfig( configfile, thename );

    KNote* newnote = new KNote( configfile );
    connect( newnote, SIGNAL( sigRenamed(QString&, QString&) ),
             this,    SLOT( slotNoteRenamed(QString&, QString&) ) );
    connect( newnote, SIGNAL( sigNewNote(int) ),
             this,    SLOT( slotNewNote(int) ) );
    connect( newnote, SIGNAL( sigKilled(QString) ),
             this,    SLOT( slotNoteKilled(QString) ) );

    m_NoteList.insert( thename, newnote );
}

void KNotesApp::slotNoteRenamed( QString& oldname, QString& newname )
{
    KNote* tmp = m_NoteList[oldname];
    m_NoteList.insert( newname, tmp );
    m_NoteList.remove( oldname );
}

void KNotesApp::slotNoteKilled( QString name )
{
    m_NoteList.remove( name );
}

void KNotesApp::slotPreferences( int )
{
    //launch preferences dialog...
    KNoteConfigDlg tmpconfig( "knotesrc", i18n("KNotes Defaults") );
    tmpconfig.exec();
}

void KNotesApp::slotToNote( int id )
{
    //tell the WM to give this note focus
    QString name = m_note_menu->text( id );

    //if it's already showing, we need to change to its desktop
    //and give it focus
    KNote* tmpnote = m_NoteList[name];
    if( !tmpnote->isHidden() )
    {
        KWin::setActiveWindow(tmpnote->winId());
        tmpnote->setFocus();
    }
    else
    {
        //if not show it on the current desktop
        tmpnote->show();
        tmpnote->slotToDesktop( KWin::currentDesktop() );
        KWin::setActiveWindow(tmpnote->winId());
        tmpnote->setFocus();
    }
}

void KNotesApp::slotPrepareNoteMenu()
{
    //find all notes- get their names and put them into the menu
    m_note_menu->clear();

    QDictIterator<KNote> it( m_NoteList );
    int id = 0;
    while( it.current() )
    {
        m_note_menu->insertItem( it.currentKey() );
        ++id;
        ++it;
    }
}

void KNotesApp::slotSaveNotes()
{
    //save all the notes...
    QDictIterator<KNote> it( m_NoteList );
    for( ; it.current(); ++it )
    {
        it.current()->saveData();
        it.current()->saveConfig();
        it.current()->saveDisplayConfig();
    }
}

void KNotesApp::mouseReleaseEvent( QMouseEvent * e)
{
    if ( rect().contains( e->pos() ) && e->button() == LeftButton )
    {
        slotPrepareNoteMenu();
        if( m_note_menu->count() > 0 )
            m_note_menu->popup( e->globalPos() );
        return;
    }
}

#include "knotesapp.moc"
<commit_msg>+ SetBackgroundMode(X11ParentRelative);<commit_after>/*******************************************************************
 KNotes -- Notes for the KDE project

 Copyright (C) Bernd Johannes Wuebben
     wuebben@math.cornell.edu
     wuebben@kde.org

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*******************************************************************/

#include "knotesapp.h"
#include "knoteconfigdlg.h"

#include <kapp.h>
#include <kwin.h>
#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kstddirs.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <ksimpleconfig.h>

#include <qdir.h>
#include <qfont.h>

KNotesApp::KNotesApp()
    : KSystemTray()
{
    //create the dock widget....
    setPixmap( KGlobal::iconLoader()->loadIcon( "knotes", KIcon::Small ) );

    m_note_menu = new KPopupMenu( this );
    connect( m_note_menu, SIGNAL( aboutToShow() ),
             this,        SLOT( slotPrepareNoteMenu() ) );
    connect( m_note_menu, SIGNAL( activated(int) ),
             this,        SLOT( slotToNote(int) ) );

    KPopupMenu* menu = contextMenu();
    menu->insertItem( i18n("New Note"), this, SLOT(slotNewNote(int)) );
    menu->insertItem( i18n("Preferences..."), this, SLOT(slotPreferences(int)) );
    menu->insertItem( i18n("Notes"), m_note_menu );

    //initialize saved notes, if none create a note...
    QString str_notedir = KGlobal::dirs()->saveLocation( "appdata", "notes/" );
    QDir notedir( str_notedir );
    QStringList notes = notedir.entryList( QDir::Files, QDir::Name ); //doesn't list hidden files

    for( QStringList::Iterator i = notes.begin(); i != notes.end(); ++i )
    {
        QString configfile = notedir.absFilePath( *i );
        KSimpleConfig* tmp = new KSimpleConfig( configfile );
        tmp->setGroup( "General" );
        int version = tmp->readNumEntry( "version", 1 );
        delete tmp;

        KNote* tmpnote = new KNote( configfile, version == 1 );

        connect( tmpnote, SIGNAL( sigRenamed(QString&, QString&) ),
                 this,    SLOT  ( slotNoteRenamed(QString&, QString&) ) );
        connect( tmpnote, SIGNAL( sigNewNote(int) ),
                 this,    SLOT  ( slotNewNote(int) ) );
        connect( tmpnote, SIGNAL( sigKilled(QString) ),
                 this,    SLOT  ( slotNoteKilled(QString) ) );
        m_NoteList.insert( tmpnote->getName(), tmpnote );
    }

    if( m_NoteList.count() == 0 && !kapp->isRestored() )
        slotNewNote();

    setBackgroundMode(X11ParentRelative);
}

KNotesApp::~KNotesApp()
{
    delete m_note_menu;
    m_NoteList.clear();
}

void KNotesApp::copyDefaultConfig( QString& sc_filename, QString& newname )
{
    QString defaultsfile = KGlobal::dirs()->findResource( "config", "knotesrc" );
    KSimpleConfig defaults( defaultsfile );
    KSimpleConfig sc( sc_filename );

    sc.setGroup( "Display" );
    defaults.setGroup( "Display" );

    uint width  = defaults.readUnsignedNumEntry( "width", 200 );
    uint height = defaults.readUnsignedNumEntry( "height", 200 );
    QColor bgc  = defaults.readColorEntry( "bgcolor", &(Qt::yellow) );
    QColor fgc  = defaults.readColorEntry( "fgcolor", &(Qt::black) );

    sc.writeEntry( "width", width );
    sc.writeEntry( "height", height );
    sc.writeEntry( "bgcolor", bgc );
    sc.writeEntry( "fgcolor", fgc );

    sc.setGroup( "Editor" );
    defaults.setGroup( "Editor" );

    uint tabsize = defaults.readUnsignedNumEntry( "tabsize", 4 );
    bool indent  = defaults.readBoolEntry( "autoindent", true );

    sc.writeEntry( "tabsize", tabsize );
    sc.writeEntry( "autoindent", indent );

    QFont def_font( "helvetica" );
    QFont currfont = defaults.readFontEntry( "font", &def_font );
    sc.writeEntry( "font", currfont );

    sc.setGroup( "Actions" );
    defaults.setGroup( "Actions" );

    QString mailstr  = defaults.readEntry( "mail", "kmail --msg %f" );
    QString printstr = defaults.readEntry( "print", "a2ps -P %p -1 --center-title=%t --underlay=KDE %f" );

    sc.writeEntry( "mail", mailstr );
    sc.writeEntry( "print", printstr );

    sc.setGroup( "General" );
    sc.writeEntry( "version", 2 );

    sc.setGroup( "Data" );
    sc.writeEntry( "name", newname );

    // TODO: write default entries for the group "WindowDisplay"

    sc.sync();
}

void KNotesApp::slotNewNote( int /*id*/ )
{
    QString datadir = KGlobal::dirs()->saveLocation( "appdata", "notes/" );

    //find a new appropriate id for the new note...
    QString thename, configfile;
    QDir appdir( datadir );

    for( int i = 1; ; i++ )
    {
        thename = QString( "KNote %1" ).arg(i);

        if( !appdir.exists( thename ) )
        {
            configfile = appdir.absFilePath( thename );
            break;
        }
    }

    copyDefaultConfig( configfile, thename );

    KNote* newnote = new KNote( configfile );
    connect( newnote, SIGNAL( sigRenamed(QString&, QString&) ),
             this,    SLOT( slotNoteRenamed(QString&, QString&) ) );
    connect( newnote, SIGNAL( sigNewNote(int) ),
             this,    SLOT( slotNewNote(int) ) );
    connect( newnote, SIGNAL( sigKilled(QString) ),
             this,    SLOT( slotNoteKilled(QString) ) );

    m_NoteList.insert( thename, newnote );
}

void KNotesApp::slotNoteRenamed( QString& oldname, QString& newname )
{
    KNote* tmp = m_NoteList[oldname];
    m_NoteList.insert( newname, tmp );
    m_NoteList.remove( oldname );
}

void KNotesApp::slotNoteKilled( QString name )
{
    m_NoteList.remove( name );
}

void KNotesApp::slotPreferences( int )
{
    //launch preferences dialog...
    KNoteConfigDlg tmpconfig( "knotesrc", i18n("KNotes Defaults") );
    tmpconfig.exec();
}

void KNotesApp::slotToNote( int id )
{
    //tell the WM to give this note focus
    QString name = m_note_menu->text( id );

    //if it's already showing, we need to change to its desktop
    //and give it focus
    KNote* tmpnote = m_NoteList[name];
    if( !tmpnote->isHidden() )
    {
        KWin::setActiveWindow(tmpnote->winId());
        tmpnote->setFocus();
    }
    else
    {
        //if not show it on the current desktop
        tmpnote->show();
        tmpnote->slotToDesktop( KWin::currentDesktop() );
        KWin::setActiveWindow(tmpnote->winId());
        tmpnote->setFocus();
    }
}

void KNotesApp::slotPrepareNoteMenu()
{
    //find all notes- get their names and put them into the menu
    m_note_menu->clear();

    QDictIterator<KNote> it( m_NoteList );
    int id = 0;
    while( it.current() )
    {
        m_note_menu->insertItem( it.currentKey() );
        ++id;
        ++it;
    }
}

void KNotesApp::slotSaveNotes()
{
    //save all the notes...
    QDictIterator<KNote> it( m_NoteList );
    for( ; it.current(); ++it )
    {
        it.current()->saveData();
        it.current()->saveConfig();
        it.current()->saveDisplayConfig();
    }
}

void KNotesApp::mouseReleaseEvent( QMouseEvent * e)
{
    if ( rect().contains( e->pos() ) && e->button() == LeftButton )
    {
        slotPrepareNoteMenu();
        if( m_note_menu->count() > 0 )
            m_note_menu->popup( e->globalPos() );
        return;
    }
}

#include "knotesapp.moc"
<|endoftext|>


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

#include "Logic/NodeType.h"
#include "Logic/NodeFactory.h"
#include "Kommon/Utils.h"

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "CV.h"

class GrayToRgbNodeType : public NodeType
{
public:
    GrayToRgbNodeType()
    {
        addInput("Gray", ENodeFlowDataType::Image);
        addOutput("Color", ENodeFlowDataType::ImageRgb);
        setDescription("Converts gray 1-channel image to 3-channel image");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImage();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageRgb();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        if(input.channels() == 3)
        {
            // no-op
            output = input;
        }
        else
        {
            if(input.data == output.data)
                output = cv::Mat();
            // Do stuff
            cv::cvtColor(input, output, CV_GRAY2BGR);
        }

        return ExecutionStatus(EStatus::Ok);
    }
};

class RgbToGrayNodeType : public NodeType
{
public:
    RgbToGrayNodeType()
    {
        addInput("Color", ENodeFlowDataType::Image);
        addOutput("Gray", ENodeFlowDataType::ImageMono);
        setDescription("Converts color 3-channel image to 1-channel gray image");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImage();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageMono();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        if(input.channels() == 1)
        {
            //no-op
            output = input;
        }
        else
        {
            if(input.data == output.data)
                output = cv::Mat();
            // Do stuff
            cv::cvtColor(input, output, CV_BGR2GRAY);
        }

        return ExecutionStatus(EStatus::Ok);
    }
};

class BayerToGrayNodeType : public NodeType
{
public:
    BayerToGrayNodeType()
        : _BayerCode(cvu::EBayerCode::RG)
    {
        addInput("Input", ENodeFlowDataType::ImageMono);
        addOutput("Output", ENodeFlowDataType::ImageMono);
        addProperty("Bayer format", _BayerCode)
            .setUiHints("item: BG, item: GB, item: RG, item: GR");
        setDescription("Performs demosaicing from Bayer pattern image to gray-scale image");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageMono();

        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::cvtColor(input, output, cvu::bayerCodeGray(_BayerCode.toEnum().cast<cvu::EBayerCode>()));

        return ExecutionStatus(EStatus::Ok);
    }

private:
    TypedNodeProperty<cvu::EBayerCode> _BayerCode;
};

class BayerToRgbNodeType : public NodeType
{
public:
    BayerToRgbNodeType()
        : _redGain(1.0)
        , _greenGain(1.0)
        , _blueGain(1.0)
        , _BayerCode(cvu::EBayerCode::RG)
    {
        addInput("Input", ENodeFlowDataType::ImageMono);
        addOutput("Output", ENodeFlowDataType::ImageRgb);
        addProperty("Bayer format", _BayerCode)
            .setUiHints("item: BG, item: GB, item: RG, item: GR");
        addProperty("Red gain", _redGain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 4.0))
            .setUiHints("min:0.0, max:4.0, step:0.001");
        addProperty("Green gain", _greenGain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 4.0))
            .setUiHints("min:0.0, max:4.0, step:0.001");
        addProperty("Blue gain", _blueGain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 4.0))
            .setUiHints("min:0.0, max:4.0, step:0.001");
        setDescription("Performs demosaicing from Bayer pattern image to RGB image.");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageRgb();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::cvtColor(input, output, cvu::bayerCodeRgb(_BayerCode.toEnum().cast<cvu::EBayerCode>()));

        if(!fcmp(_redGain.toDouble(), 1.0)
        || !fcmp(_greenGain.toDouble(), 1.0)
        || !fcmp(_blueGain.toDouble(), 1.0))
        {
            cvu::parallel_for(cv::Range(0, output.rows), [&](const cv::Range& range)
            {
                for(int y = range.start; y < range.end; ++y)
                {
                    for(int x = 0; x < output.cols; ++x)
                    {
                        cv::Vec3b rgb = output.at<cv::Vec3b>(y, x);
                        rgb[0] = cv::saturate_cast<uchar>(rgb[0] * _blueGain);
                        rgb[1] = cv::saturate_cast<uchar>(rgb[1] * _greenGain);
                        rgb[2] = cv::saturate_cast<uchar>(rgb[2] * _redGain);
                        output.at<cv::Vec3b>(y, x) = rgb;
                    }
                }
            });
        }

        return ExecutionStatus(EStatus::Ok);
    }

private:
    TypedNodeProperty<double> _redGain;
    TypedNodeProperty<double> _greenGain;
    TypedNodeProperty<double> _blueGain;
    TypedNodeProperty<cvu::EBayerCode> _BayerCode;
};

class ContrastAndBrightnessNodeType : public NodeType
{
public:
    ContrastAndBrightnessNodeType()
        : _gain(1.0)
        , _bias(0)
    {
        addInput("Input", ENodeFlowDataType::Image);
        addOutput("Output", ENodeFlowDataType::Image);
        addProperty("Gain", _gain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 16.0))
            .setUiHints("min:0.0, max:16.0");
        addProperty("Bias", _bias)
            .setValidator(make_validator<InclRangePropertyValidator<int>>(-255, 255))
            .setUiHints("min:-255, max:255");
        setDescription("Adjusts contrast and brightness of input image.");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImage();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImage();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        if(!fcmp(_gain.toDouble(), 1.0) || _bias != 0)
        {
            output = cv::Mat(input.size(), input.type());

            if(input.channels() == 1)
            {
                cvu::parallel_for(cv::Range(0, output.rows), [&](const cv::Range& range)
                {
                    for(int y = range.start; y < range.end; ++y)
                    {
                        for(int x = 0; x < output.cols; ++x)
                        {
                            output.at<uchar>(y, x) = cv::saturate_cast<uchar>(
                                _gain * input.at<uchar>(y, x) + _bias);
                        }
                    }
                });
            }
            else if(input.channels() == 3)
            {
                cvu::parallel_for(cv::Range(0, output.rows), [&](const cv::Range& range)
                {
                    for(int y = range.start; y < range.end; ++y)
                    {
                        for(int x = 0; x < output.cols; ++x)
                        {
                            cv::Vec3b rgb = input.at<cv::Vec3b>(y, x);
                            rgb[0] = cv::saturate_cast<uchar>(_gain * rgb[0] + _bias);
                            rgb[1] = cv::saturate_cast<uchar>(_gain * rgb[1] + _bias);
                            rgb[2] = cv::saturate_cast<uchar>(_gain * rgb[2] + _bias);
                            output.at<cv::Vec3b>(y, x) = rgb;
                        }
                    }
                });
            }
        }
        else
        {
            output = input;
        }

        return ExecutionStatus(EStatus::Ok);
    }

protected:
    TypedNodeProperty<double> _gain;
    TypedNodeProperty<int> _bias;
};

REGISTER_NODE("Format conversion/Contrast & brightness", ContrastAndBrightnessNodeType)
REGISTER_NODE("Format conversion/Gray de-bayer", BayerToGrayNodeType)
REGISTER_NODE("Format conversion/RGB de-bayer", BayerToRgbNodeType)
REGISTER_NODE("Format conversion/Gray to RGB", GrayToRgbNodeType)
REGISTER_NODE("Format conversion/RGB to gray", RgbToGrayNodeType)
<commit_msg>added channels splitter/merger node type<commit_after>/*
 * Copyright (c) 2013-2014 Kajetan Swierk <k0zmo@outlook.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include "Logic/NodeType.h"
#include "Logic/NodeFactory.h"
#include "Kommon/Utils.h"

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "CV.h"

class GrayToRgbNodeType : public NodeType
{
public:
    GrayToRgbNodeType()
    {
        addInput("Gray", ENodeFlowDataType::Image);
        addOutput("Color", ENodeFlowDataType::ImageRgb);
        setDescription("Converts gray 1-channel image to 3-channel image");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImage();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageRgb();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        if(input.channels() == 3)
        {
            // no-op
            output = input;
        }
        else
        {
            if(input.data == output.data)
                output = cv::Mat();
            // Do stuff
            cv::cvtColor(input, output, CV_GRAY2BGR);
        }

        return ExecutionStatus(EStatus::Ok);
    }
};

class RgbToGrayNodeType : public NodeType
{
public:
    RgbToGrayNodeType()
    {
        addInput("Color", ENodeFlowDataType::Image);
        addOutput("Gray", ENodeFlowDataType::ImageMono);
        setDescription("Converts color 3-channel image to 1-channel gray image");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImage();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageMono();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        if(input.channels() == 1)
        {
            //no-op
            output = input;
        }
        else
        {
            if(input.data == output.data)
                output = cv::Mat();
            // Do stuff
            cv::cvtColor(input, output, CV_BGR2GRAY);
        }

        return ExecutionStatus(EStatus::Ok);
    }
};

class BayerToGrayNodeType : public NodeType
{
public:
    BayerToGrayNodeType()
        : _BayerCode(cvu::EBayerCode::RG)
    {
        addInput("Input", ENodeFlowDataType::ImageMono);
        addOutput("Output", ENodeFlowDataType::ImageMono);
        addProperty("Bayer format", _BayerCode)
            .setUiHints("item: BG, item: GB, item: RG, item: GR");
        setDescription("Performs demosaicing from Bayer pattern image to gray-scale image");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageMono();

        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::cvtColor(input, output, cvu::bayerCodeGray(_BayerCode.toEnum().cast<cvu::EBayerCode>()));

        return ExecutionStatus(EStatus::Ok);
    }

private:
    TypedNodeProperty<cvu::EBayerCode> _BayerCode;
};

class BayerToRgbNodeType : public NodeType
{
public:
    BayerToRgbNodeType()
        : _redGain(1.0)
        , _greenGain(1.0)
        , _blueGain(1.0)
        , _BayerCode(cvu::EBayerCode::RG)
    {
        addInput("Input", ENodeFlowDataType::ImageMono);
        addOutput("Output", ENodeFlowDataType::ImageRgb);
        addProperty("Bayer format", _BayerCode)
            .setUiHints("item: BG, item: GB, item: RG, item: GR");
        addProperty("Red gain", _redGain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 4.0))
            .setUiHints("min:0.0, max:4.0, step:0.001");
        addProperty("Green gain", _greenGain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 4.0))
            .setUiHints("min:0.0, max:4.0, step:0.001");
        addProperty("Blue gain", _blueGain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 4.0))
            .setUiHints("min:0.0, max:4.0, step:0.001");
        setDescription("Performs demosaicing from Bayer pattern image to RGB image.");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImageRgb();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::cvtColor(input, output, cvu::bayerCodeRgb(_BayerCode.toEnum().cast<cvu::EBayerCode>()));

        if(!fcmp(_redGain.toDouble(), 1.0)
        || !fcmp(_greenGain.toDouble(), 1.0)
        || !fcmp(_blueGain.toDouble(), 1.0))
        {
            cvu::parallel_for(cv::Range(0, output.rows), [&](const cv::Range& range)
            {
                for(int y = range.start; y < range.end; ++y)
                {
                    for(int x = 0; x < output.cols; ++x)
                    {
                        cv::Vec3b rgb = output.at<cv::Vec3b>(y, x);
                        rgb[0] = cv::saturate_cast<uchar>(rgb[0] * _blueGain);
                        rgb[1] = cv::saturate_cast<uchar>(rgb[1] * _greenGain);
                        rgb[2] = cv::saturate_cast<uchar>(rgb[2] * _redGain);
                        output.at<cv::Vec3b>(y, x) = rgb;
                    }
                }
            });
        }

        return ExecutionStatus(EStatus::Ok);
    }

private:
    TypedNodeProperty<double> _redGain;
    TypedNodeProperty<double> _greenGain;
    TypedNodeProperty<double> _blueGain;
    TypedNodeProperty<cvu::EBayerCode> _BayerCode;
};

class ContrastAndBrightnessNodeType : public NodeType
{
public:
    ContrastAndBrightnessNodeType()
        : _gain(1.0)
        , _bias(0)
    {
        addInput("Input", ENodeFlowDataType::Image);
        addOutput("Output", ENodeFlowDataType::Image);
        addProperty("Gain", _gain)
            .setValidator(make_validator<InclRangePropertyValidator<double>>(0.0, 16.0))
            .setUiHints("min:0.0, max:16.0");
        addProperty("Bias", _bias)
            .setValidator(make_validator<InclRangePropertyValidator<int>>(-255, 255))
            .setUiHints("min:-255, max:255");
        setDescription("Adjusts contrast and brightness of input image.");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImage();
        // Acquire output sockets
        cv::Mat& output = writer.acquireSocket(0).getImage();

        // Validate inputs
        if(input.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        if(!fcmp(_gain.toDouble(), 1.0) || _bias != 0)
        {
            output = cv::Mat(input.size(), input.type());

            if(input.channels() == 1)
            {
                cvu::parallel_for(cv::Range(0, output.rows), [&](const cv::Range& range)
                {
                    for(int y = range.start; y < range.end; ++y)
                    {
                        for(int x = 0; x < output.cols; ++x)
                        {
                            output.at<uchar>(y, x) = cv::saturate_cast<uchar>(
                                _gain * input.at<uchar>(y, x) + _bias);
                        }
                    }
                });
            }
            else if(input.channels() == 3)
            {
                cvu::parallel_for(cv::Range(0, output.rows), [&](const cv::Range& range)
                {
                    for(int y = range.start; y < range.end; ++y)
                    {
                        for(int x = 0; x < output.cols; ++x)
                        {
                            cv::Vec3b rgb = input.at<cv::Vec3b>(y, x);
                            rgb[0] = cv::saturate_cast<uchar>(_gain * rgb[0] + _bias);
                            rgb[1] = cv::saturate_cast<uchar>(_gain * rgb[1] + _bias);
                            rgb[2] = cv::saturate_cast<uchar>(_gain * rgb[2] + _bias);
                            output.at<cv::Vec3b>(y, x) = rgb;
                        }
                    }
                });
            }
        }
        else
        {
            output = input;
        }

        return ExecutionStatus(EStatus::Ok);
    }

protected:
    TypedNodeProperty<double> _gain;
    TypedNodeProperty<int> _bias;
};

enum class EColourSpace
{
    Rgb,
    Xyz,
    YCrCb,
    Hsv,
    Lab,
    Hls,
    Luv
};

class ChannelSplitterNodeType : public NodeType
{
public:
    ChannelSplitterNodeType()
        : _colourSpace(EColourSpace::Rgb)
    {
        addInput("Image", ENodeFlowDataType::ImageRgb);
        addOutput("1st", ENodeFlowDataType::ImageMono);
        addOutput("2nd", ENodeFlowDataType::ImageMono);
        addOutput("3rd", ENodeFlowDataType::ImageMono);
        addProperty("Colour space", _colourSpace)
            .setUiHints("item: RGB, item: CIE 1931 XYZ, item: YCrCb, "
                        "item: HSV, item: CIELAB, item: HLS, item: CIELUV");
        setDescription("Splits colour image into three separate images/channels");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& input = reader.readSocket(0).getImageRgb();
        // Acquire output sockets
        cv::Mat& first = writer.acquireSocket(0).getImageMono();
        cv::Mat& second = writer.acquireSocket(1).getImageMono();
        cv::Mat& third = writer.acquireSocket(2).getImageMono();
        cv::Mat tmp;
        int dstCode = -1;

        switch (_colourSpace.cast_value<Enum>().cast<EColourSpace>())
        {
        case EColourSpace::Rgb:
            dstCode = -1;
            break;
        case EColourSpace::Xyz:
            dstCode = CV_BGR2XYZ;
            break;
        case EColourSpace::YCrCb:
            dstCode = CV_BGR2YCrCb;
            break;
        case EColourSpace::Hsv:
            dstCode = CV_BGR2HSV;
            break;
        case EColourSpace::Lab:
            dstCode = CV_BGR2Lab;
            break;
        case EColourSpace::Hls:
            dstCode = CV_BGR2HLS;
            break;
        case EColourSpace::Luv:
            dstCode = CV_BGR2Luv;
            break;
        default:
            return ExecutionStatus(EStatus::Error, "Wrong color space value");
        }

        if (dstCode > 0)
            cv::cvtColor(input, tmp, dstCode);
        else
            tmp = input;

        std::vector<cv::Mat> channels;
        cv::split(tmp, channels);

        first = channels.at(0);
        second = channels.at(1);
        third = channels.at(2);

        return ExecutionStatus(EStatus::Ok);
    }

private:
    TypedNodeProperty<EColourSpace> _colourSpace;
};

class ChannelMergerNodeType : public NodeType
{
public:
    ChannelMergerNodeType()
        : _colourSpace(EColourSpace::Rgb)
    {
        addInput("1st", ENodeFlowDataType::ImageMono);
        addInput("2nd", ENodeFlowDataType::ImageMono);
        addInput("3rd", ENodeFlowDataType::ImageMono);
        addOutput("Image", ENodeFlowDataType::ImageRgb);
        addProperty("Colour space", _colourSpace)
            .setUiHints("item: RGB, item: CIE 1931 XYZ, item: YCrCb, "
                        "item: HSV, item: CIELAB, item: HLS, item: CIELUV");
        setDescription("Merges three separate images/channels into a final colour image");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& first = reader.readSocket(0).getImageMono();
        const cv::Mat& second = reader.readSocket(1).getImageMono();
        const cv::Mat& third = reader.readSocket(2).getImageMono();
        // Acquire output sockets
        cv::Mat& dst = writer.acquireSocket(0).getImageRgb();

        // basic check
        if (first.size != second.size || first.size != third.size)
            return ExecutionStatus(EStatus::Error, "Channels have different sizes");

        cv::Mat tmp;
        std::vector<cv::Mat> channels = {first, second, third};
        cv::merge(channels, tmp);

        int dstCode = -1;

        switch (_colourSpace.cast_value<Enum>().cast<EColourSpace>())
        {
        case EColourSpace::Rgb:
            dstCode = -1;
            break;
        case EColourSpace::Xyz:
            dstCode = CV_XYZ2BGR;
            break;
        case EColourSpace::YCrCb:
            dstCode = CV_YCrCb2BGR;
            break;
        case EColourSpace::Hsv:
            dstCode = CV_HSV2BGR;
            break;
        case EColourSpace::Lab:
            dstCode = CV_Lab2BGR;
            break;
        case EColourSpace::Hls:
            dstCode = CV_HLS2BGR;
            break;
        case EColourSpace::Luv:
            dstCode = CV_Luv2BGR;
            break;
        default:
            return ExecutionStatus(EStatus::Error, "Wrong color space value");
        }

        if (dstCode > 0)
            cv::cvtColor(tmp, dst, dstCode);
        else
            dst = tmp;

        return ExecutionStatus(EStatus::Ok);
    }

private:
    TypedNodeProperty<EColourSpace> _colourSpace;
};

REGISTER_NODE("Format conversion/Channel merger", ChannelMergerNodeType);
REGISTER_NODE("Format conversion/Channel splitter", ChannelSplitterNodeType);
REGISTER_NODE("Format conversion/Contrast & brightness", ContrastAndBrightnessNodeType)
REGISTER_NODE("Format conversion/Gray de-bayer", BayerToGrayNodeType)
REGISTER_NODE("Format conversion/RGB de-bayer", BayerToRgbNodeType)
REGISTER_NODE("Format conversion/Gray to RGB", GrayToRgbNodeType)
REGISTER_NODE("Format conversion/RGB to gray", RgbToGrayNodeType)
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016-2016, Roland Bock
 * 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.
 *
 * 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 HOLDER 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 "compare.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>

#include <iostream>

SQLPP_ALIAS_PROVIDER(cheese);

int As(int, char* [])
{
  const auto foo = test::TabFoo{};
  const auto bar = test::TabBar{};

  compare(__LINE__, foo.omega.as(cheese), "tab_foo.omega AS cheese");
  compare(__LINE__, (foo.omega + 17).as(cheese), "(tab_foo.omega+17) AS cheese");
  compare(__LINE__, (foo.omega - 17).as(cheese), "(tab_foo.omega-17) AS cheese");
  compare(__LINE__, (foo.omega - uint32_t(17)).as(cheese), "(tab_foo.omega-17) AS cheese");
  compare(__LINE__, (foo.omega - bar.alpha).as(cheese), "(tab_foo.omega-tab_bar.alpha) AS cheese");
  compare(__LINE__, (count(foo.omega) - bar.alpha).as(cheese), "(COUNT(tab_foo.omega)-tab_bar.alpha) AS cheese");
  compare(__LINE__, (count(foo.omega) - uint32_t(17)).as(cheese), "(COUNT(tab_foo.omega)-17) AS cheese");

  // Auto alias
  compare(__LINE__, select(max(bar.alpha)), "SELECT MAX(tab_bar.alpha) AS max_");
  compare(__LINE__, select(max(bar.alpha).as(cheese)), "SELECT MAX(tab_bar.alpha) AS cheese");
  compare(__LINE__, select(max(bar.alpha)).from(bar).unconditionally().as(cheese),
          "(SELECT MAX(tab_bar.alpha) AS max_ FROM tab_bar) AS cheese");
  compare(__LINE__, select(max(bar.alpha)).from(bar).unconditionally().as(cheese).max, "cheese.max_");

  return 0;
}
<commit_msg>Remove superfluous semicolon<commit_after>/*
 * Copyright (c) 2016-2016, Roland Bock
 * 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.
 *
 * 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 HOLDER 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 "compare.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>

#include <iostream>

SQLPP_ALIAS_PROVIDER(cheese)

int As(int, char* [])
{
  const auto foo = test::TabFoo{};
  const auto bar = test::TabBar{};

  compare(__LINE__, foo.omega.as(cheese), "tab_foo.omega AS cheese");
  compare(__LINE__, (foo.omega + 17).as(cheese), "(tab_foo.omega+17) AS cheese");
  compare(__LINE__, (foo.omega - 17).as(cheese), "(tab_foo.omega-17) AS cheese");
  compare(__LINE__, (foo.omega - uint32_t(17)).as(cheese), "(tab_foo.omega-17) AS cheese");
  compare(__LINE__, (foo.omega - bar.alpha).as(cheese), "(tab_foo.omega-tab_bar.alpha) AS cheese");
  compare(__LINE__, (count(foo.omega) - bar.alpha).as(cheese), "(COUNT(tab_foo.omega)-tab_bar.alpha) AS cheese");
  compare(__LINE__, (count(foo.omega) - uint32_t(17)).as(cheese), "(COUNT(tab_foo.omega)-17) AS cheese");

  // Auto alias
  compare(__LINE__, select(max(bar.alpha)), "SELECT MAX(tab_bar.alpha) AS max_");
  compare(__LINE__, select(max(bar.alpha).as(cheese)), "SELECT MAX(tab_bar.alpha) AS cheese");
  compare(__LINE__, select(max(bar.alpha)).from(bar).unconditionally().as(cheese),
          "(SELECT MAX(tab_bar.alpha) AS max_ FROM tab_bar) AS cheese");
  compare(__LINE__, select(max(bar.alpha)).from(bar).unconditionally().as(cheese).max, "cheese.max_");

  return 0;
}
<|endoftext|>