コード例 #1
0
void TransitionHandler::deleteTransition(QString tag, int /*a_track*/, int b_track, GenTime in, GenTime out, QDomElement /*xml*/, bool /*do_refresh*/)
{
    QScopedPointer<Mlt::Field> field(m_tractor->field());
    field->lock();
    mlt_service nextservice = mlt_service_get_producer(field->get_service());
    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
    QString mlt_type = mlt_properties_get(properties, "mlt_type");
    QString resource = mlt_properties_get(properties, "mlt_service");

    const int old_pos = (int)((in + out).frames(m_fps) / 2);
    ////qDebug() << " del trans pos: " << in.frames(25) << '-' << out.frames(25);

    while (mlt_type == QLatin1String("transition")) {
        mlt_transition tr = (mlt_transition) nextservice;
        int currentTrack = mlt_transition_get_b_track(tr);
        int currentIn = (int) mlt_transition_get_in(tr);
        int currentOut = (int) mlt_transition_get_out(tr);
        ////qDebug() << "// FOUND EXISTING TRANS, IN: " << currentIn << ", OUT: " << currentOut << ", TRACK: " << currentTrack;

        if (resource == tag && b_track == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
            mlt_field_disconnect_service(field->get_field(), nextservice);
            break;
        }
        nextservice = mlt_service_producer(nextservice);
        if (nextservice == NULL) break;
        properties = MLT_SERVICE_PROPERTIES(nextservice);
        mlt_type = mlt_properties_get(properties, "mlt_type");
        resource = mlt_properties_get(properties, "mlt_service");
    }
    field->unlock();
    //askForRefresh();
    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
}
コード例 #2
0
ファイル: mlt_consumer.c プロジェクト: MarcAntoine-Arnaud/mlt
int mlt_consumer_put_frame( mlt_consumer self, mlt_frame frame )
{
	int error = 1;

	// Get the service assoicated to the consumer
	mlt_service service = MLT_CONSUMER_SERVICE( self );

	if ( mlt_service_producer( service ) == NULL )
	{
		struct timeval now;
		struct timespec tm;
		pthread_mutex_lock( &self->put_mutex );
		while ( self->put_active && self->put != NULL )
		{
			gettimeofday( &now, NULL );
			tm.tv_sec = now.tv_sec + 1;
			tm.tv_nsec = now.tv_usec * 1000;
			pthread_cond_timedwait( &self->put_cond, &self->put_mutex, &tm );
		}
		if ( self->put_active && self->put == NULL )
			self->put = frame;
		else
			mlt_frame_close( frame );
		pthread_cond_broadcast( &self->put_cond );
		pthread_mutex_unlock( &self->put_mutex );
	}
	else
	{
		mlt_frame_close( frame );
	}

	return error;
}
コード例 #3
0
ファイル: mlt_filter.c プロジェクト: mcfrisk/mlt
static int filter_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
{
	mlt_filter self = service->child;

	// Get coords in/out/track
	int track = mlt_filter_get_track( self );
	int in = mlt_filter_get_in( self );
	int out = mlt_filter_get_out( self );

	// Get the producer this is connected to
	mlt_service producer = mlt_service_producer( &self->parent );

	// If the frame request is for this filters track, we need to process it
	if ( index == track || track == -1 )
	{
		int ret = mlt_service_get_frame( producer, frame, index );
		if ( ret == 0 )
		{
			mlt_position position = mlt_frame_get_position( *frame );
			if ( position >= in && ( out == 0 || position <= out ) )
				*frame = mlt_filter_process( self, *frame );
			return 0;
		}
		else
		{
			*frame = mlt_frame_init( service );
			return 0;
		}
	}
	else
	{
		return mlt_service_get_frame( producer, frame, index );
	}
}
コード例 #4
0
bool TransitionHandler::moveTransition(QString type, int startTrack, int newTrack, int newTransitionTrack, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut)
{
    double fps = m_tractor->get_fps();
    int new_in = (int)newIn.frames(fps);
    int new_out = (int)newOut.frames(fps) - 1;
    if (new_in >= new_out) return false;
    int old_in = (int)oldIn.frames(fps);
    int old_out = (int)oldOut.frames(fps) - 1;

    bool doRefresh = true;
    // Check if clip is visible in monitor
    int position = mlt_producer_position(m_tractor->get_producer());
    int diff = old_out - position;
    if (diff < 0 || diff > old_out - old_in) doRefresh = false;
    if (doRefresh) {
        diff = new_out - position;
        if (diff < 0 || diff > new_out - new_in) doRefresh = false;
    }
    QScopedPointer<Mlt::Field> field(m_tractor->field());
    field->lock();
    mlt_service nextservice = mlt_service_get_producer(field->get_service());
    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
    QString resource = mlt_properties_get(properties, "mlt_service");
    int old_pos = (int)(old_in + old_out) / 2;
    bool found = false;
    mlt_service_type mlt_type = mlt_service_identify( nextservice );
    while (mlt_type == transition_type) {
        Mlt::Transition transition((mlt_transition) nextservice);
        nextservice = mlt_service_producer(nextservice);
        int currentTrack = transition.get_b_track();
        int currentIn = (int) transition.get_in();
        int currentOut = (int) transition.get_out();

        if (resource == type && startTrack == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
            found = true;
            if (newTrack - startTrack != 0) {
                Mlt::Properties trans_props(transition.get_properties());
                Mlt::Transition new_transition(*m_tractor->profile(), transition.get("mlt_service"));
                Mlt::Properties new_trans_props(new_transition.get_properties());
                // We cannot use MLT's property inherit because it also clones internal values like _unique_id which messes up the playlist
                cloneProperties(new_trans_props, trans_props);
                new_transition.set_in_and_out(new_in, new_out);
                field->disconnect_service(transition);
                plantTransition(field.data(), new_transition, newTransitionTrack, newTrack);
            } else transition.set_in_and_out(new_in, new_out);
            break;
        }
        if (nextservice == NULL) break;
        properties = MLT_SERVICE_PROPERTIES(nextservice);
        mlt_type = mlt_service_identify( nextservice );
        resource = mlt_properties_get(properties, "mlt_service");
    }
    field->unlock();
    if (doRefresh) refresh();
    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
    return found;
}
コード例 #5
0
ファイル: mlt_tractor.c プロジェクト: amongll/AVFX
int mlt_tractor_remove_track( mlt_tractor self, int index )
{
	int error = mlt_multitrack_disconnect( mlt_tractor_multitrack( self ), index );
	if ( !error )
	{
		// Update the track indices of transitions and track filters.
		mlt_service service = mlt_service_producer( MLT_TRACTOR_SERVICE( self ) );
		while ( service )
		{
			mlt_service_type type = mlt_service_identify( service );
			mlt_properties properties = MLT_SERVICE_PROPERTIES( service );

			if ( type == transition_type )
			{
				mlt_transition transition = MLT_TRANSITION( service );
				int a_track = mlt_transition_get_a_track( transition );
				int b_track = mlt_transition_get_b_track( transition );

				if ( a_track >= index || b_track >= index )
				{
					a_track = MAX( a_track >= index ? a_track - 1 : a_track, 0 );
					b_track = MAX( b_track >= index ? b_track - 1 : b_track, 0 );
					mlt_transition_set_tracks( transition, a_track, b_track );
				}
			}
			else if ( type == filter_type )
			{
				int current_track = mlt_properties_get_int( properties, "track" );
				if ( current_track >= index )
					mlt_properties_set_int( properties, "track", MAX( current_track - 1, 0 ) );
			}
			service = mlt_service_producer( service );
		}
	}
	return error;
}
コード例 #6
0
void TransitionHandler::deleteTrackTransitions(int ix)
{
    QScopedPointer<Mlt::Field> field(m_tractor->field());
    mlt_service nextservice = mlt_service_get_producer(field->get_service());
    mlt_service_type type = mlt_service_identify( nextservice );
    while (type == transition_type) {
	Mlt::Transition transition((mlt_transition) nextservice);
        nextservice = mlt_service_producer(nextservice);
        int currentTrack = transition.get_b_track();
        if (ix == currentTrack) {
            field->disconnect_service(transition);
        }
        if (nextservice == NULL) break;
        type = mlt_service_identify(nextservice );
    }
}
コード例 #7
0
// adds the transition by keeping the instance order from topmost track down to background
void TransitionHandler::plantTransition(Mlt::Field *field, Mlt::Transition &tr, int a_track, int b_track)
{
    mlt_service nextservice = mlt_service_get_producer(field->get_service());
    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
    QString mlt_type = mlt_properties_get(properties, "mlt_type");
    QString resource = mlt_properties_get(properties, "mlt_service");
    QList <Mlt::Transition *> trList;
    mlt_properties insertproperties = tr.get_properties();
    QString insertresource = mlt_properties_get(insertproperties, "mlt_service");
    bool isMixTransition = insertresource == QLatin1String("mix");

    while (mlt_type == QLatin1String("transition")) {
        Mlt::Transition transition((mlt_transition) nextservice);
        nextservice = mlt_service_producer(nextservice);
        int aTrack = transition.get_a_track();
        int bTrack = transition.get_b_track();
        int internal = transition.get_int("internal_added");
        if ((isMixTransition || resource != QLatin1String("mix")) && (internal > 0 || aTrack < a_track || (aTrack == a_track && bTrack > b_track))) {
            Mlt::Properties trans_props(transition.get_properties());
            Mlt::Transition *cp = new Mlt::Transition(*m_tractor->profile(), transition.get("mlt_service"));
            Mlt::Properties new_trans_props(cp->get_properties());
            //new_trans_props.inherit(trans_props);
            cloneProperties(new_trans_props, trans_props);
            trList.append(cp);
            field->disconnect_service(transition);
        }
        //else qDebug() << "// FOUND TRANS OK, "<<resource<< ", A_: " << aTrack << ", B_ "<<bTrack;

        if (nextservice == NULL) break;
        properties = MLT_SERVICE_PROPERTIES(nextservice);
        mlt_type = mlt_properties_get(properties, "mlt_type");
        resource = mlt_properties_get(properties, "mlt_service");
    }
    field->plant_transition(tr, a_track, b_track);

    // re-add upper transitions
    for (int i = trList.count() - 1; i >= 0; --i) {
        ////qDebug()<< "REPLANT ON TK: "<<trList.at(i)->get_a_track()<<", "<<trList.at(i)->get_b_track();
        field->plant_transition(*trList.at(i), trList.at(i)->get_a_track(), trList.at(i)->get_b_track());
    }
    qDeleteAll(trList);
}
コード例 #8
0
ファイル: mlt_field.c プロジェクト: mltframework/mlt
void mlt_field_disconnect_service( mlt_field self, mlt_service service )
{
	mlt_service p = mlt_service_producer( service );
	mlt_service c = mlt_service_consumer( service);
	int i;
	switch ( mlt_service_identify(c) )
	{
		case filter_type:
			i = mlt_filter_get_track( MLT_FILTER(c) );
			mlt_service_connect_producer( c, p, i );
			break;
		case transition_type:
			i = mlt_transition_get_a_track ( MLT_TRANSITION(c) );
			mlt_service_connect_producer( c, p, i );
			MLT_TRANSITION(c)->producer = p;
			break;
		case tractor_type:
			self->producer = p;
			mlt_tractor_connect( MLT_TRACTOR(c), p );
		default:
			break;
	}
	mlt_events_fire( mlt_field_properties( self ), "service-changed", NULL );
}
コード例 #9
0
void TransitionHandler::updateTransitionParams(QString type, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml)
{
    QScopedPointer<Mlt::Field> field(m_tractor->field());
    field->lock();

    mlt_service nextservice = mlt_service_get_producer(field->get_service());
    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
    QString mlt_type = mlt_properties_get(properties, "mlt_type");
    QString resource = mlt_properties_get(properties, "mlt_service");
    int in_pos = (int) in.frames(m_fps);
    int out_pos = (int) out.frames(m_fps) - 1;

    while (mlt_type == QLatin1String("transition")) {
        mlt_transition tr = (mlt_transition) nextservice;
        int currentTrack = mlt_transition_get_b_track(tr);
        int currentBTrack = mlt_transition_get_a_track(tr);
        int currentIn = (int) mlt_transition_get_in(tr);
        int currentOut = (int) mlt_transition_get_out(tr);

        // //qDebug()<<"Looking for transition : " << currentIn <<'x'<<currentOut<< ", OLD oNE: "<<in_pos<<'x'<<out_pos;
        if (resource == type && b_track == currentTrack && currentIn == in_pos && currentOut == out_pos) {
            QMap<QString, QString> map = getTransitionParamsFromXml(xml);
            QMap<QString, QString>::Iterator it;
            QString key;
            mlt_properties transproperties = MLT_TRANSITION_PROPERTIES(tr);

            QString currentId = mlt_properties_get(transproperties, "kdenlive_id");
            if (currentId != xml.attribute(QStringLiteral("id"))) {
                // The transition ID is not the same, so reset all properties
                mlt_properties_set(transproperties, "kdenlive_id", xml.attribute(QStringLiteral("id")).toUtf8().constData());
                // Cleanup previous properties
                QStringList permanentProps;
                permanentProps << QStringLiteral("factory") << QStringLiteral("kdenlive_id") << QStringLiteral("mlt_service") << QStringLiteral("mlt_type") << QStringLiteral("in");
                permanentProps << QStringLiteral("out") << QStringLiteral("a_track") << QStringLiteral("b_track");
                for (int i = 0; i < mlt_properties_count(transproperties); ++i) {
                    QString propName = mlt_properties_get_name(transproperties, i);
                    if (!propName.startsWith('_') && ! permanentProps.contains(propName)) {
                        mlt_properties_set(transproperties, propName.toUtf8().constData(), "");
                    }
                }
            }

            mlt_properties_set_int(transproperties, "force_track", xml.attribute(QStringLiteral("force_track")).toInt());
            mlt_properties_set_int(transproperties, "automatic", xml.attribute(QStringLiteral("automatic"), QStringLiteral("0")).toInt());

            if (currentBTrack != a_track) {
                mlt_properties_set_int(transproperties, "a_track", a_track);
            }
            for (it = map.begin(); it != map.end(); ++it) {
                key = it.key();
                mlt_properties_set(transproperties, key.toUtf8().constData(), it.value().toUtf8().constData());
                ////qDebug() << " ------  UPDATING TRANS PARAM: " << key.toUtf8().constData() << ": " << it.value().toUtf8().constData();
                //filter->set("kdenlive_id", id);
            }
            break;
        }
        nextservice = mlt_service_producer(nextservice);
        if (nextservice == NULL) break;
        properties = MLT_SERVICE_PROPERTIES(nextservice);
        mlt_type = mlt_properties_get(properties, "mlt_type");
        resource = mlt_properties_get(properties, "mlt_service");
    }
    field->unlock();
    //askForRefresh();
    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
}
コード例 #10
0
ファイル: mlt_consumer.c プロジェクト: MarcAntoine-Arnaud/mlt
mlt_frame mlt_consumer_get_frame( mlt_consumer self )
{
	// Frame to return
	mlt_frame frame = NULL;

	// Get the service assoicated to the consumer
	mlt_service service = MLT_CONSUMER_SERVICE( self );

	// Get the consumer properties
	mlt_properties properties = MLT_CONSUMER_PROPERTIES( self );

	// Get the frame
	if ( mlt_service_producer( service ) == NULL && mlt_properties_get_int( properties, "put_mode" ) )
	{
		struct timeval now;
		struct timespec tm;
		pthread_mutex_lock( &self->put_mutex );
		while ( self->put_active && self->put == NULL )
		{
			gettimeofday( &now, NULL );
			tm.tv_sec = now.tv_sec + 1;
			tm.tv_nsec = now.tv_usec * 1000;
			pthread_cond_timedwait( &self->put_cond, &self->put_mutex, &tm );
		}
		frame = self->put;
		self->put = NULL;
		pthread_cond_broadcast( &self->put_cond );
		pthread_mutex_unlock( &self->put_mutex );
		if ( frame != NULL )
			mlt_service_apply_filters( service, frame, 0 );
	}
	else if ( mlt_service_producer( service ) != NULL )
	{
		mlt_service_get_frame( service, &frame, 0 );
	}
	else
	{
		frame = mlt_frame_init( service );
	}

	if ( frame != NULL )
	{
		// Get the frame properties
		mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );

		// Get the test card producer
		mlt_producer test_card = mlt_properties_get_data( properties, "test_card_producer", NULL );

		// Attach the test frame producer to it.
		if ( test_card != NULL )
			mlt_properties_set_data( frame_properties, "test_card_producer", test_card, 0, NULL, NULL );

		// Pass along the interpolation and deinterlace options
		// TODO: get rid of consumer_deinterlace and use profile.progressive
		mlt_properties_set( frame_properties, "rescale.interp", mlt_properties_get( properties, "rescale" ) );
		mlt_properties_set_int( frame_properties, "consumer_deinterlace", mlt_properties_get_int( properties, "progressive" ) | mlt_properties_get_int( properties, "deinterlace" ) );
		mlt_properties_set( frame_properties, "deinterlace_method", mlt_properties_get( properties, "deinterlace_method" ) );
		mlt_properties_set_int( frame_properties, "consumer_tff", mlt_properties_get_int( properties, "top_field_first" ) );
	}

	// Return the frame
	return frame;
}
コード例 #11
0
void TransitionHandler::enableMultiTrack(bool enable)
{
    int tracks = m_tractor->count();
    if (tracks < 3) {
        // we need at leas 3 tracks (black bg track + 2 tracks to use this)
        return;
    }
    QScopedPointer<Mlt::Service> service(m_tractor->field());
    QScopedPointer<Mlt::Field> field(m_tractor->field());
    field->lock();
    if (enable) {
        // disable track composition (frei0r.cairoblend)
        QScopedPointer<Mlt::Field> field(m_tractor->field());
        mlt_service nextservice = mlt_service_get_producer(field->get_service());
        mlt_service_type type = mlt_service_identify( nextservice );
        while (type == transition_type) {
            Mlt::Transition transition((mlt_transition) nextservice);
            nextservice = mlt_service_producer(nextservice);
            int added = transition.get_int("internal_added");
            if (added == 237) {
                QString mlt_service = transition.get("mlt_service");
                if (mlt_service == QLatin1String("frei0r.cairoblend") && transition.get_int("disable") == 0) {
                    transition.set("disable", 1);
                    transition.set("split_disable", 1);
                }
            }
            if (nextservice == NULL) break;
            type = mlt_service_identify(nextservice);
        }
        for (int i = 1, screen = 0; i < tracks && screen < 4; ++i) {
            Mlt::Producer trackProducer(m_tractor->track(i));
            if (QString(trackProducer.get("hide")).toInt() != 1) {
                Mlt::Transition transition(*m_tractor->profile(), "composite");
                transition.set("mlt_service", "composite");
                transition.set("a_track", 0);
                transition.set("b_track", i);
                transition.set("distort", 0);
                transition.set("aligned", 0);
                // 200 is an arbitrary number so we can easily remove these transition later
                transition.set("internal_added", 200);
                QString geometry;
                switch (screen) {
                case 0:
                    geometry = QStringLiteral("0/0:50%x50%");
                    break;
                case 1:
                    geometry = QStringLiteral("50%/0:50%x50%");
                    break;
                case 2:
                    geometry = QStringLiteral("0/50%:50%x50%");
                    break;
                case 3:
                default:
                    geometry = QStringLiteral("50%/50%:50%x50%");
                    break;
                }
                transition.set("geometry", geometry.toUtf8().constData());
                transition.set("always_active", 1);
                field->plant_transition(transition, 0, i);
                screen++;
            }
        }
    } else {
        QScopedPointer<Mlt::Field> field(m_tractor->field());
        mlt_service nextservice = mlt_service_get_producer(field->get_service());
        mlt_service_type type = mlt_service_identify( nextservice );
        while (type == transition_type) {
            Mlt::Transition transition((mlt_transition) nextservice);
            nextservice = mlt_service_producer(nextservice);
            int added = transition.get_int("internal_added");
            if (added == 200) {
                field->disconnect_service(transition);
            } else if (added == 237) {
                // re-enable track compositing
                QString mlt_service = transition.get("mlt_service");
                if (mlt_service == QLatin1String("frei0r.cairoblend") && transition.get_int("split_disable") == 1) {
                    transition.set("disable", 0);
                    transition.set("split_disable", (char*) NULL);
                }
            }
            if (nextservice == NULL) break;
            type = mlt_service_identify(nextservice);
        }
    }
    field->unlock();
    emit refresh();
}
コード例 #12
0
ファイル: mlt_parser.c プロジェクト: bmatherly/mlt
int mlt_parser_start( mlt_parser self, mlt_service object )
{
	int error = 0;
	mlt_service_type type = mlt_service_identify( object );
	switch( type )
	{
		case invalid_type:
			error = self->on_invalid( self, object );
			break;
		case unknown_type:
			error = self->on_unknown( self, object );
			break;
		case producer_type:
			if ( mlt_producer_is_cut( ( mlt_producer )object ) )
				error = mlt_parser_start( self, ( mlt_service )mlt_producer_cut_parent( ( mlt_producer )object ) );
			error = self->on_start_producer( self, ( mlt_producer )object );
			if ( error == 0 )
			{
				int i = 0;
				while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
					error = mlt_parser_start( self, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
			}
			error = self->on_end_producer( self, ( mlt_producer )object );
			break;
		case playlist_type:
			error = self->on_start_playlist( self, ( mlt_playlist )object );
			if ( error == 0 )
			{
				int i = 0;
				while ( error == 0 && i < mlt_playlist_count( ( mlt_playlist )object ) )
					mlt_parser_start( self, ( mlt_service )mlt_playlist_get_clip( ( mlt_playlist )object, i ++ ) );
				i = 0;
				while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
					error = mlt_parser_start( self, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
			}
			error = self->on_end_playlist( self, ( mlt_playlist )object );
			break;
		case tractor_type:
			error = self->on_start_tractor( self, ( mlt_tractor )object );
			if ( error == 0 )
			{
				int i = 0;
				mlt_service next = mlt_service_producer( object );
				mlt_parser_start( self, ( mlt_service )mlt_tractor_multitrack( ( mlt_tractor )object ) );
				while ( next != ( mlt_service )mlt_tractor_multitrack( ( mlt_tractor )object ) )
				{
					mlt_parser_start( self, next );
					next = mlt_service_producer( next );
				}
				while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
					error = mlt_parser_start( self, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
			}
			error = self->on_end_tractor( self, ( mlt_tractor )object );
			break;
		case multitrack_type:
			error = self->on_start_multitrack( self, ( mlt_multitrack )object );
			if ( error == 0 )
			{
				int i = 0;
				while ( i < mlt_multitrack_count( ( mlt_multitrack )object ) )
				{
					self->on_start_track( self );
					mlt_parser_start( self, ( mlt_service )mlt_multitrack_track( ( mlt_multitrack )object , i ++ ) );
					self->on_end_track( self );
				}
				i = 0;
				while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
					error = mlt_parser_start( self, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
			}
			error = self->on_end_multitrack( self, ( mlt_multitrack )object );
			break;
		case filter_type:
			error = self->on_start_filter( self, ( mlt_filter )object );
			if ( error == 0 )
			{
				int i = 0;
				while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
					error = mlt_parser_start( self, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
			}
			error = self->on_end_filter( self, ( mlt_filter )object );
			break;
		case transition_type:
			error = self->on_start_transition( self, ( mlt_transition )object );
			if ( error == 0 )
			{
				int i = 0;
				while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
					error = mlt_parser_start( self, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
			}
			error = self->on_end_transition( self, ( mlt_transition )object );
			break;
		case field_type:
			break;
		case consumer_type:
			break;
	}
	return error;
}