int mlt_animation_get_item( mlt_animation self, mlt_animation_item item, int position ) { int error = 0; // Need to find the nearest keyframe to the position specifed animation_node node = self->nodes; // Iterate through the keyframes until we reach last or have while ( node && node->next && position >= node->next->item.frame ) node = node->next; if ( node ) { item->keyframe_type = node->item.keyframe_type; // Position is before the first keyframe. if ( position < node->item.frame ) { item->is_key = 0; if ( item->property ) mlt_property_pass( item->property, node->item.property ); } // Item exists. else if ( position == node->item.frame ) { item->is_key = node->item.is_key; if ( item->property ) mlt_property_pass( item->property, node->item.property ); } // Position is after the last keyframe. else if ( !node->next ) { item->is_key = 0; if ( item->property ) mlt_property_pass( item->property, node->item.property ); } // Interpolation needed. else { double progress; mlt_property points[4]; points[0] = node->prev? node->prev->item.property : node->item.property; points[1] = node->item.property; points[2] = node->next->item.property; points[3] = node->next->next? node->next->next->item.property : node->next->item.property; progress = position - node->item.frame; progress /= node->next->item.frame - node->item.frame; mlt_property_interpolate( item->property, points, progress, self->fps, self->locale, item->keyframe_type ); item->is_key = 0; } } else { item->frame = item->is_key = 0; error = 1; } item->frame = position; return error; }
int mlt_animation_key_get( mlt_animation self, mlt_animation_item item, int index ) { int error = 0; animation_node node = self->nodes; // Iterate through the keyframes. int i = index; while ( i-- && node ) node = node->next; if ( node ) { item->is_key = node->item.is_key; item->frame = node->item.frame; item->keyframe_type = node->item.keyframe_type; if ( item->property ) mlt_property_pass( item->property, node->item.property ); } else { item->frame = item->is_key = 0; error = 1; } return error; }
int mlt_animation_insert( mlt_animation self, mlt_animation_item item ) { int error = 0; animation_node node = calloc( 1, sizeof( *node ) ); node->item.frame = item->frame; node->item.is_key = 1; node->item.keyframe_type = item->keyframe_type; node->item.property = mlt_property_init(); mlt_property_pass( node->item.property, item->property ); // Determine if we need to insert or append to the list, or if it's a new list if ( self->nodes ) { // Get the first item animation_node current = self->nodes; // Locate an existing nearby item while ( current->next && item->frame > current->item.frame ) current = current->next; if ( item->frame < current->item.frame ) { if ( current == self->nodes ) self->nodes = node; if ( current->prev ) current->prev->next = node; node->next = current; node->prev = current->prev; current->prev = node; } else if ( item->frame > current->item.frame ) { if ( current->next ) current->next->prev = node; node->next = current->next; node->prev = current; current->next = node; } else { // Update matching node. current->item.frame = item->frame; current->item.is_key = 1; current->item.keyframe_type = item->keyframe_type; mlt_property_close( current->item.property ); current->item.property = node->item.property; free( node ); } } else { // Set the first item self->nodes = node; } return error; }
int mlt_animation_prev_key( mlt_animation self, mlt_animation_item item, int position ) { animation_node node = self->nodes; while ( node && node->next && position >= node->next->item.frame ) node = node->next; if ( node ) { item->frame = node->item.frame; item->is_key = node->item.is_key; item->keyframe_type = node->item.keyframe_type; mlt_property_pass( item->property, node->item.property ); } return ( node == NULL ); }