// ----------------------------------------------------------------------------
// NOTE: Dimmer channel should contain 0 for full off and 255 for full on and
// no other values
//
void SceneMovementAnimatorTask::populateChannelAnimations(
    ParticipantArray& participants, size_t& particpant_index,
    AngleList& tilt, AngleList& pan, ChannelValueArray& dimmer,
    ChannelValueArray& speed, size_t group_size, bool run_once )
{
    size_t end = particpant_index + group_size;

    // If run once, add last entry to shut down the lights
    if ( run_once && dimmer.size() > 0 ) {
        dimmer.push_back( 0 );
    }

    ChannelAnimationStyle style( run_once ? CAM_LIST_ONCE : CAM_LIST );

    for ( ; particpant_index < end && particpant_index < participants.size(); particpant_index++ ) {
		channel_address pan_channel = participants[ particpant_index ].m_head.m_pan;
		channel_address tilt_channel = participants[ particpant_index ].m_head.m_tilt;
		channel_address dimmer_channel = participants[ particpant_index ].m_head.m_dimmer;
		channel_address speed_channel = participants[ particpant_index ].m_head.m_speed;
        UID actor_uid = participants[ particpant_index ].m_actor_uid;

        Fixture* pf = getActorRepresentative( actor_uid );
        if ( !pf )
            continue;

        if ( tilt_channel != INVALID_CHANNEL && tilt.size() ) {
            Channel* cp = pf->getChannel( tilt_channel );
            add( actor_uid, tilt_channel, style, anglesToValues( cp, tilt, cp->getMinAngle(), cp->getMaxAngle() ) );
        }

        if ( pan_channel != INVALID_CHANNEL && pan.size() ) {
            Channel* cp = pf->getChannel( pan_channel );
            add( actor_uid, pan_channel, style, anglesToValues( cp, pan, cp->getMinAngle(), cp->getMaxAngle() ) );
        }

        if ( speed_channel != INVALID_CHANNEL && speed.size() ) {
            add( actor_uid, speed_channel, style, speed );
        }

        if ( dimmer_channel != INVALID_CHANNEL && dimmer.size() ) {
            Channel* ch = pf->getChannel( dimmer_channel );
            STUDIO_ASSERT( ch, "Can't access dimmer channel %d on fixture %s", dimmer_channel, pf->getFullName() );

            BYTE low = ch->getDimmerLowestIntensity();
            BYTE high = ch->getDimmerHighestIntensity();

            // Replace all 255 dimmer high value with the fixture's dimmer value iff the actors value != 0
            SceneActor* actor = getActor( actor_uid );
            if ( actor && actor->getFinalChannelValue( pf->getUID(), dimmer_channel ) != 0 )
                high = actor->getFinalChannelValue( pf->getUID(), dimmer_channel );

            if ( low != 0 || high != 255 ) {                // Special case odd dimmer values
                for ( size_t i=0; i < dimmer.size(); i++ )
                    dimmer[i] = ( dimmer[i] == 255 ) ? high : low;
            }

            add( actor_uid, dimmer_channel, style, dimmer );
        }
    }
}
Ejemplo n.º 2
0
// ----------------------------------------------------------------------------
//
SceneActor::SceneActor( Venue* venue, FixtureGroup *fg ) :
    m_uid( fg->getUID() ),
    m_group( true ),
    m_channels(0)
{
    reset_channel_values();

    if ( fg->getNumChannelValues() > 0 ) {
        m_channels = fg->getNumChannelValues();
        fg->getChannelValues( m_channel_values );
    }
    else {
        Fixture* pf = venue->getGroupRepresentative( fg->getUID() );

        if ( pf != NULL ) {         // Make sure this is not an empty group
            m_channels = pf->getNumChannels();

            // Copy channel defaults
            for ( channel_t channel=0; channel < m_channels; channel++ ) {
                m_channel_values[ channel ] = pf->getChannel( channel )->getDefaultValue();
            }
        }
    }
}
Ejemplo n.º 3
0
// ----------------------------------------------------------------------------
//
bool HttpRestServices::query_scenes( CString& response, LPCSTR data )
{
    if ( !studio.getVenue() || !studio.getVenue()->isRunning() )
        return false;

    JsonBuilder json( response );
    json.startArray();

    ScenePtrArray scenes = studio.getVenue()->getScenes();

    std::sort( scenes.begin(), scenes.end(), CompareObjectNumber );

    Scene* default_scene = studio.getVenue()->getDefaultScene();

    UID active_uid = studio.getVenue()->getCurrentSceneUID();

    for ( ScenePtrArray::iterator it=scenes.begin(); it != scenes.end(); it++ ) {
        Scene* scene = (*it);

        json.startObject();
        json.add( "id", scene->getUID() );
        json.add( "number", scene->getSceneNumber() );
        json.add( "name", scene->getName() );
        json.add( "bpm_rating", scene->getBPMRating() );
        json.add( "description", scene->getDescription() );
        json.add( "is_default", (scene == default_scene) );
        json.add( "is_running", (active_uid == scene->getUID()) );
        json.addArray<Acts>( "acts", scene->getActs() );

        json.startArray( "actors" );

        ActorPtrArray actors = scene->getActors();

        for ( ActorPtrArray::iterator it=actors.begin(); it != actors.end(); ++it ) {
            Fixture* fixture = NULL;

            json.startObject();
            json.add( "id", (*it)->getActorUID() );
            json.add( "is_group", (*it)->isGroup() );

            if ( (*it)->isGroup() ) {
                fixture = studio.getVenue()->getGroupRepresentative( (*it)->getActorUID() );
            }
            else {
                fixture = studio.getVenue()->getFixture( (*it)->getActorUID() );
                json.add( "address", (int)fixture->getAddress() );
            }

            json.startArray( "channels" );
            if ( fixture != NULL ) {
                for ( channel_t channel=0; channel < fixture->getNumChannels(); channel++ ) {
                    Channel* ch = fixture->getChannel( channel );
                    BYTE value = (*it)->getChannelValue( fixture->mapChannel( channel ) );
                    ChannelValueRange* range = ch->getRange( value );
                    LPCSTR range_name = range ? range->getName() : "";

                    json.startObject();
                    json.add( "channel", (int)channel );
                    json.add( "name", ch->getName() );
                    json.add( "value", value );
                    json.add( "range_name", range_name );
                    json.endObject();
                }
            }
            json.endArray( "channels" );

            json.endObject();
        }

        json.endArray( "actors" );

        json.startArray( "animations" );

        for ( size_t a=0; a < scene->getNumAnimations(); a++ ) {
            AbstractAnimation* animation = scene->getAnimation( a );

            json.startObject();
            json.add( "class_name", animation->getClassName() );
            json.add( "name", animation->getName() );
            json.add( "number", animation->getNumber() );
            json.addArray<UIDArray>( "actors", animation->getActors() );

            // Add common signal data
            AnimationSignal& signal = animation->signal();
            json.startObject( "signal" );
            json.add( "sample_rate_ms", signal.getSampleRateMS() );
            json.add( "input_type", signal.getInputType() );
            json.add( "input_low", signal.getInputLow() );
            json.add( "input_high", signal.getInputHigh() );
            json.add( "sample_decay_ms", signal.getSampleDecayMS() );
            json.add( "scale_factor", signal.getScaleFactor() );
            json.add( "max_threshold", signal.getMaxThreshold() );
            json.add( "apply_to", signal.getApplyTo() );
            json.endObject();

            // Add animation specific data
            CString json_anim_name = JsonObject::encodeJsonString( animation->getClassName() );
            json.startObject( json_anim_name );

            if ( !strcmp( animation->getClassName(), SceneStrobeAnimator::className ) ) {
                SceneStrobeAnimator* ssa = (SceneStrobeAnimator*)animation;
                json.add( "strobe_neg_color", ssa->getStrobeNegColor() );
                json.add( "strobe_pos_ms", ssa->getStrobePosMS() );
                json.add( "strobe_neg_ms", ssa->getStrobeNegMS() );
            }
            else if ( !strcmp( animation->getClassName(), ScenePatternDimmer::className ) ) {
                ScenePatternDimmer* spd = (ScenePatternDimmer*)animation;
                json.add( "dimmer_pattern", spd->getDimmerPattern() );
            }
            else if ( !strcmp( animation->getClassName(), SceneSoundLevel::className ) ) {
                SceneSoundLevel* ssl = (SceneSoundLevel*)animation;
                json.add( "fade_what", ssl->getFadeWhat() );
            }
            else if ( !strcmp( animation->getClassName(), SceneColorFader::className ) ) {
                SceneColorFader* scs = (SceneColorFader*)animation;
                json.add( "fader_effect", scs->getFaderEffect() );
                json.add( "strobe_neg_color", scs->getStrobeNegColor() );
                json.add( "strobe_pos_ms", scs->getStrobePosMS() );
                json.add( "strobe_neg_ms", scs->getStrobeNegMS() );
                json.addColorArray<RGBWAArray>( "color_progression", scs->getCustomColors() );
            }
            else if ( !strcmp( animation->getClassName(), ScenePixelAnimator::className ) ) {
                ScenePixelAnimator* spa = (ScenePixelAnimator*)animation;
                json.add( "pixel_effect", spa->getEffect() );
                json.add( "generations", spa->getGenerations() );
                json.add( "pixels", spa->getPixels() );
                json.add( "increment", spa->getIncrement() );
                json.add( "fade", spa->isFadeColors() );
                json.add( "combine", spa->getCombineFixtures() );
                json.add( "pixel_off_color", spa->getEmptyColor() );
                json.addColorArray<RGBWAArray>( "color_progression", spa->getCustomColors() );
            }
            else if ( !strcmp( animation->getClassName(), SceneChannelFilter::className ) ) {
                SceneChannelFilter* scf = (SceneChannelFilter*)animation;
                json.add( "filter", scf->getFilter() );
                json.add( "channel", scf->getChannel() );
                json.add( "step", scf->getStep() );
                json.add( "amplitude", scf->getAmplitude() );
                json.add( "offset", scf->getOffset() );
            }
            else if ( !strcmp( animation->getClassName(), SceneMovementAnimator::className ) ) {
                SceneMovementAnimator* sma = (SceneMovementAnimator*)animation;
                MovementAnimation& movement = sma->movement();

                json.add( "movement_type", movement.m_movement_type );
                json.add( "tilt_start_angle", movement.m_tilt_start );
                json.add( "tilt_end_angle", movement.m_tilt_end );
                json.add( "pan_start_angle", movement.m_pan_start );
                json.add( "pan_end_angle", movement.m_pan_end );
                json.add( "pan_increment", movement.m_pan_increment );
                json.add( "speed", movement.m_speed );
                json.add( "home_wait_periods", movement.m_home_wait_periods );
                json.add( "dest_wait_periods", movement.m_dest_wait_periods );
                json.add( "group_size", movement.m_group_size );
                json.add( "positions", movement.m_positions );
                json.add( "alternate_groups", movement.m_alternate_groups );
                json.add( "blackout_return", movement.m_backout_home_return );
                json.add( "run_once", movement.m_run_once );
                json.add( "home_x", movement.m_home_x );
                json.add( "home_y", movement.m_home_y );
                json.add( "height", movement.m_height );
                json.add( "fixture_spacing", movement.m_fixture_spacing );
                json.add( "radius", movement.m_radius );
                json.add( "head_number", movement.m_head_number );

                json.startArray( "coordinates" );
                for ( size_t index=0; index <  movement.m_coordinates.size(); index++ ) {
                    json.startObject();
                    json.add( "pan", movement.m_coordinates[index].m_pan );
                    json.add( "tilt", movement.m_coordinates[index].m_tilt );
                    json.endObject();
                }
                json.endArray( "coordinates" );
            }
            else if ( !strcmp( animation->getClassName(), SceneChannelAnimator::className ) ) {
                SceneChannelAnimator* sca = (SceneChannelAnimator*)animation;
                ChannelAnimationArray& chan_anims = sca->channelAnimations();

                json.startArray( "channel_animations" );

                for ( ChannelAnimationArray::iterator it=chan_anims.begin(); it != chan_anims.end(); ++it ) {
                    json.startObject();
                    json.add( "actor_uid", (*it).getActorUID() );
                    json.add( "channel", (*it).getChannel() );
                    json.add( "style", (*it).getAnimationStyle() );
                    json.addArray<ChannelValueArray>( "values", (*it).getChannelValues() );
                    json.endObject();
                }

                json.endArray( "channel_animations" );
            }

            json.endObject( json_anim_name );
            json.endObject();
        }

        json.endArray( "animations" );
        json.endObject();
    }

    json.endArray();

    return true;
}
void SceneMovementAnimatorTask::genRandomMovement( MovementAnimation& movement, ParticipantArray& participants )
{
    STUDIO_ASSERT( movement.m_positions > 0 && movement.m_positions < MAX_RANDOM_POSITIONS, 
        "Random postions should be between 1 and %d", MAX_RANDOM_POSITIONS );

    for ( size_t particpant_index=0; particpant_index < participants.size(); ) {
        Fixture* pf = getActorRepresentative( participants[ particpant_index ].m_actor_uid );
        if ( !pf )
            continue;

        UINT tilt_start = movement.m_tilt_start, tilt_end = movement.m_tilt_end;
        UINT pan_start = movement.m_pan_start, pan_end = movement.m_pan_end;

        AngleList pan;
        AngleList tilt;
        ChannelValueArray dimmer;
        ChannelValueArray speed;

        channel_address tilt_channel = participants[ particpant_index ].m_head.m_tilt;
        if ( tilt_channel != INVALID_CHANNEL ) {
            Channel* cp = pf->getChannel( tilt_channel );
            tilt_start = std::max<UINT>( tilt_start, cp->getMinAngle() );
            tilt_end = std::min<UINT>( tilt_end, cp->getMaxAngle() );
        }

        channel_address pan_channel = participants[ particpant_index ].m_head.m_pan;
        if ( pan_channel != INVALID_CHANNEL ) {
            Channel* cp = pf->getChannel( pan_channel );
            pan_start = std::max<UINT>( pan_start, cp->getMinAngle() );
            pan_end = std::min<UINT>( pan_end, cp->getMaxAngle() );
        }

        // Generate random locations within the tilt and pan bounds
        for ( UINT generate=0; generate < movement.m_positions; generate++ ) {
            UINT tilt_angle = random_angle( tilt_start, tilt_end );
            UINT pan_angle = random_angle( pan_start, pan_end );

            UINT wait_periods = movement.m_dest_wait_periods;

            // No light during movement
            if ( movement.m_backout_home_return && wait_periods > 1 ) {
                pan.push_back( pan_angle );
                tilt.push_back( tilt_angle );
                speed.push_back( 0 );
                dimmer.push_back( 0 );
                wait_periods--;
            }

            for ( UINT wait=0; wait < wait_periods; wait++ ) {
                pan.push_back( pan_angle );
                tilt.push_back( tilt_angle );
                speed.push_back( movement.m_speed );
                dimmer.push_back( 255 );
            }
        }

        if ( !movement.m_backout_home_return )          // TEMP fix for dimmer channel contention
            dimmer.clear();

        // Populate the channel arrays for the next group of fixtures
        populateChannelAnimations( participants, particpant_index, tilt, pan, dimmer, speed, movement.m_group_size, movement.m_run_once );
    }
}
Ejemplo n.º 5
0
// ----------------------------------------------------------------------------
//
void ScenePatternDimmerTask::generateProgram( AnimationDefinition* definition ) 
{
    ScenePatternDimmer* config = dynamic_cast< ScenePatternDimmer *>( definition );

    struct DimmerValue {
        BYTE m_on;
        BYTE m_off;

        DimmerValue( Channel* cp ) :
            m_on( cp->getDimmerHighestIntensity() ),
            m_off( cp->getDimmerLowestIntensity() )
        {}

        BYTE getValue( bool on ) const {
            return on ? m_on : m_off;
        }
    };

    ChannelProgramArray program;
    std::vector<DimmerValue> dimmer_values_array;

    // Determine which channels will be participating
	for ( SceneActor& actor : getActors() ) {
        Fixture* pf = getActorRepresentative( actor.getActorUID() );
        if ( !pf )
            continue;

        // Determine which channels will be participating
        for ( size_t channel=0; channel < pf->getNumChannels(); channel++ ) {
            Channel* cp = pf->getChannel( channel );

            if ( cp->isDimmer() ) {
                program.emplace_back( actor.getActorUID(), channel, CAM_LIST );
                dimmer_values_array.emplace_back( cp );
            }
        }
    }

    int num_channels = program.size();

    switch ( config->getDimmerPattern() ) {
        case DP_SEQUENCE: {
            int target = 0; // X - - - -> - X - - -> - - X - -> - - - X
            for ( int i=0; i < num_channels; i++ ) {
                ChannelProgram& chan_anim = program[i];
                DimmerValue& dimmer_values = dimmer_values_array[i];

                for ( int index=0; index < num_channels; index++ )
                    chan_anim.valueList().push_back( dimmer_values.getValue( target == index ) );

                target++;
            }
            break;
        }

        case DP_CYLON: { // X - - -> - X - -> - - X -> - X - -> - - X
            int target = 0;

            for ( int i=0; i < num_channels; i++ ) {
                ChannelProgram& chan_anim = program[i];
                DimmerValue& dimmer_values = dimmer_values_array[i];

                for ( int index=0; index < num_channels*2-2; index++ )
                    chan_anim.valueList().push_back( dimmer_values.getValue( target == index || num_channels*2-2-index == target ) );
                target++;
            }
            break;
        }

        case DP_PAIRS: { // X X - - -> - - X X 
            int target = 0;

            for ( int index=0; index < (num_channels+1)/2; index++ ) {
                for ( int i=0; i < num_channels; i++ ) {
                    ChannelProgram& chan_anim = program[i];
                    DimmerValue& dimmer_values = dimmer_values_array[i];
                    chan_anim.valueList().push_back( dimmer_values.getValue( target == i || target+1 == i ) );
                }
                target += 2;
            }
            break;
        }

        case DP_TOCENTER: { // X - - X -> - X X -
            int target = 0;
            for ( int i=0; i < num_channels; i++ ) {
                ChannelProgram& chan_anim = program[i];
                DimmerValue& dimmer_values = dimmer_values_array[i];

                for ( int index=0; index < num_channels; index++ )
                    chan_anim.valueList().push_back( dimmer_values.getValue( target == index || num_channels-index-1 == target ) );
                target += 1;
            }
            break;
        }

        case DP_ALTERNATE: { // X - X - -> - X - X 
            int target = 1;
            for ( int i=0; i < num_channels; i++ ) {
                ChannelProgram& chan_anim = program[i];
                DimmerValue& dimmer_values = dimmer_values_array[i];

                for ( int index=0; index < num_channels; index++ )
                    chan_anim.valueList().push_back( dimmer_values.getValue( index ^ target ? true : false ) );
                target ^= 1;
            }
            break;
        }

        case DP_ALL: {          // X X X X -> - - - - 
            for ( int i=0; i < num_channels; i++ ) {
                ChannelProgram& chan_anim = program[i];
                DimmerValue& dimmer_values = dimmer_values_array[i];

                for ( int index=0; index < 2; index++ )
                    chan_anim.valueList().push_back( dimmer_values.getValue( index ? true : false ) );
            }
            break;
        }

        case DP_RANDOM: {       // * * * * -> * * * * -> ...
            for ( int i=0; i < num_channels; i++ ) {
                ChannelProgram& chan_anim = program[i];
                DimmerValue& dimmer_values = dimmer_values_array[i];

                for ( int i=0; i < 50; i++ )   // Generate 50 states per dimmer
                    chan_anim.valueList().push_back( dimmer_values.getValue( (rand() % 2) ? true : false ) );
            }
            break;
        }

        case DP_RAMP_UP:        // - - - - -> X - - - -> X X - - -> X X X - -> X X X X
        case DP_RAMP_UP_DOWN: { // - - - - -> X - - - -> X X - - -> X X X - -> X X X X -> - X X X -> - - X X -> - - - X
            for ( int i=0; i < num_channels; i++ ) {
                ChannelProgram& chan_anim = program[i];
                DimmerValue& dimmer_values = dimmer_values_array[i];

                for ( int index=-1; index < num_channels; index++ )
                    chan_anim.valueList().push_back( dimmer_values.getValue( index >= i ) );

                if ( config->getDimmerPattern() == DP_RAMP_UP_DOWN ) {
                    for ( int index=num_channels-1; index >= 0; index-- )
                        chan_anim.valueList().push_back( dimmer_values.getValue( index >= i ) );
                }
            }
            break;
        }

        case DP_RANDOM_TO_ALL: {    // * * * * -> * * * * -> * * * * -> X X X X
            std::vector<size_t> sequence;
            for ( int i=0; i < num_channels; i++ )
                sequence.push_back( i );

            for ( int i=0; i < 50; i++ ) {   // Generated states
                std::vector<size_t> pool = sequence;
                std::set<size_t> on;

                for ( int j=0; j < num_channels; j++ ) {
                    size_t index = rand() % pool.size();
                    on.insert( pool.at( index ) );
                    pool.erase( pool.begin() + index );

                    for ( int i=0; i < num_channels; i++ ) {
                        ChannelProgram& chan_anim = program[i];
                        DimmerValue& dimmer_values = dimmer_values_array[i];

                        chan_anim.valueList().push_back( dimmer_values.getValue( on.find(i) != on.end() ) );
                    }
                }
            }
            break;
        }
    }

    add( program );
}