drummer/lv2_plugin.c
Arnaud G. GIBERT 0082554711 - Factorise DRT_Drummer_URIS & DR_LV2_Map_URIS into new common lv2 files lv2_utils.h & lv2_utils.c,
- Implement Kit_Update_Request & Kit_Update_Reply,
- Update Kit ComboBox on Kit_Update_Reply,
- Need to fix Kit_Update_Reply on async sample load...
2024-04-10 23:53:45 +02:00

1588 lines
48 KiB
C

/*----------------------------------------------------------------------------*/
/* Includes */
/*----------------------------------------------------------------------------*/
#define _LV2_PLUGIN_C_
#include <drummer.h>
static int current_kit_changed = 0;
/*----------------------------------------------------------------------------*/
/* DR_LV2_Log_Write */
/*----------------------------------------------------------------------------*/
DRT_Status DR_LV2_Log_Write( DRT_Log_Type_Id Log_Type_Id, char *Out_Fmt, va_list Args)
{
LV2_URID type;
switch( Log_Type_Id)
{
case DRD_LOG_TYPE_ID_TRACE:
{
type = DRG_LV2_Base.Logger.Trace;
break;
}
case DRD_LOG_TYPE_ID_INFO:
{
type = DRG_LV2_Base.Logger.Note;
break;
}
case DRD_LOG_TYPE_ID_WARNING:
{
type = DRG_LV2_Base.Logger.Warning;
break;
}
case DRD_LOG_TYPE_ID_ERROR:
case DRD_LOG_TYPE_ID_UNKNOWN:
default:
{
type = DRG_LV2_Base.Logger.Error;
break;
}
}
if( lv2_log_vprintf( &(DRG_LV2_Base.Logger), type, Out_Fmt, Args) == 0)
{
fprintf( stderr, "LV2 logger error...\n");
}
return( DRS_OK);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
/*
static inline void DR_LV2_Map_URIS( LV2_URID_Map *Map_Ptr, DRT_Drummer_URIS *URIS)
{
URIS->Atom_Object = Map_Ptr->map( Map_Ptr->handle, LV2_ATOM__Object);
URIS->String_URId = Map_Ptr->map( Map_Ptr->handle, LV2_ATOM__String);
URIS->Bool_URId = Map_Ptr->map( Map_Ptr->handle, LV2_ATOM__Bool);
URIS->Int_URId = Map_Ptr->map( Map_Ptr->handle, LV2_ATOM__Int);
URIS->Long_URId = Map_Ptr->map( Map_Ptr->handle, LV2_ATOM__Long);
URIS->Tuple_URId = Map_Ptr->map( Map_Ptr->handle, LV2_ATOM__Tuple);
URIS->Midi_Event = Map_Ptr->map( Map_Ptr->handle, "http://lv2plug.in/ns/ext/midi#MidiEvent");
URIS->Atom_EventTransfer = Map_Ptr->map( Map_Ptr->handle, LV2_ATOM__eventTransfer);
URIS->UI_Msg = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#uimsg");
URIS->UI_Enable = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#uienable");
URIS->UI_Disable = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#uidisable");
URIS->Kit_Update_Request = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#kitupdaterequest");
URIS->Kit_Update_Reply = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#kitupdatereply");
URIS->Velocity_Ignore_Flag_Toggle = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#velocitytoggle");
URIS->Note_Off_Ignore_Flag_Toggle = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#noteofftoggle");
/*
URIS->kit_path = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#kitpath");
URIS->get_state = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#getstate");
URIS->midi_info = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#midiinfo");
URIS->sample_trigger = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#sampletrigger");
URIS->velocity_toggle = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#velocitytoggle");
URIS->note_off_toggle = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#noteofftoggle");
URIS->channel_id = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#channelid");
URIS->zero_position = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#zeroposition");
URIS->sample_add = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#sampleadd");
URIS->sample_remove = Map_Ptr->map( Map_Ptr->handle, DRD_DRUMMER_URI "#sampleremove");
*/
/*
}
*/
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
DRT_Status DR_LV2_Kit_Sample_Load( DRT_Kit *Kit_Ptr)
{
DRT_Status status;
NDT_Node *cur_node_ptr;
int sample_id = 0;
if( Kit_Ptr != NULL)
{
// fprintf( stderr, "Sample Rate: (%d)\n", DRG_LV2_Base.Base.SampleRate);
if( ( status = DR_Kit_Sample_Load( Kit_Ptr)) == DRS_OK)
{
DRG_LV2_Base.Kit_Ptr = Kit_Ptr;
cur_node_ptr = Kit_Ptr->Instrument_DS_Ptr->Index_Tab[NDD_INDEX_PRIMARY].Head;
pthread_mutex_lock( &( DRG_LV2_Base.Load_Mutex));
for( sample_id = 0; sample_id < DRD_PORT_NUMBER_MAX; sample_id++)
{
DRG_LV2_Base.Samples[sample_id].Active = 0;
DRG_LV2_Base.Samples[sample_id].Offset = 0;
DRG_LV2_Base.Samples[sample_id].Limit = 0;
DRG_LV2_Base.Samples[sample_id].Velocity = 0;
DRG_LV2_Base.Samples[sample_id].Layer_Ptr = 0;
DRG_LV2_Base.Samples[sample_id].Data_Ptr = NULL;
DRG_LV2_Base.Samples[sample_id].Data_Offset = 0;
DRG_LV2_Base.Samples[sample_id].Sustained = false;
if( cur_node_ptr == NULL)
{
// fprintf( stderr, "Skip sample\n");
DRG_LV2_Base.Samples[sample_id].Instrument_Ptr = NULL;
}
else
{
DRG_LV2_Base.Samples[sample_id].Instrument_Ptr = (DRT_Instrument *)cur_node_ptr->Value;
cur_node_ptr = cur_node_ptr->Right;
// fprintf( stderr, "Add sample: [%s]\n", DRG_LV2_Base.Samples[sample_id].Instrument_Ptr->Name);
}
}
pthread_mutex_unlock( &( DRG_LV2_Base.Load_Mutex));
DRG_LV2_Base.Sample_Number = Kit_Ptr->Instrument_DS_Ptr->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
DR_LOG_INFO_1( "Loaded: (%d) instruments!", DRG_LV2_Base.Sample_Number);
// DR_Kit_Dump( Kit_Ptr, 0);
}
}
return( status);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
DRT_Status DR_LV2_CurKit_Sample_Load()
{
DRT_Status status;
DRT_Kit *Kit_Ptr;
DRT_Kit_Id kit_id;
if( DRG_LV2_Base.Kit_Id_New != DRG_LV2_Base.Kit_Id)
{
DRG_LV2_Base.Program_Id_New = DRG_LV2_Base.Kit_Id_New % 128;
DRG_LV2_Base.Bank_Id_MSB_New = ( DRG_LV2_Base.Kit_Id_New / 128) % 128;
DRG_LV2_Base.Bank_Id_LSB_New = ( DRG_LV2_Base.Kit_Id_New / 128) / 128;
}
kit_id = ( DRG_LV2_Base.Bank_Id_LSB_New * 128 + DRG_LV2_Base.Bank_Id_MSB_New) * 128 + DRG_LV2_Base.Program_Id_New;
if( kit_id == DRG_LV2_Base.Kit_Id)
{
DR_LOG_INFO_5( "Same kit id: (%d) Bank/Program: (%d/%d/%d) Name: [%s]!",
kit_id, DRG_LV2_Base.Bank_Id_LSB_New, DRG_LV2_Base.Bank_Id_MSB_New, DRG_LV2_Base.Program_Id_New, DRG_LV2_Base.Kit_Ptr->Name);
status = DRS_OK;
}
else
{
if( ( status = DR_Kit_Logical_Id_Find( &Kit_Ptr, kit_id)) != DRS_OK)
{
fprintf( stderr, "Can't find kit id: (%d) Bank/Program: (%d/%d/%d)!\n",
kit_id, DRG_LV2_Base.Bank_Id_LSB_New, DRG_LV2_Base.Bank_Id_MSB_New, DRG_LV2_Base.Program_Id_New);
if( DRG_LV2_Base.Kit_Id == DRD_ID_UNKNOWN)
{
fprintf( stderr, "No Kit available!\n");
status = DRS_KO;
}
else
{
DR_LOG_INFO_5( "Keep kit id: (%d) Bank/Program: (%d/%d/%d) Name: [%s]!",
DRG_LV2_Base.Kit_Id, DRG_LV2_Base.Bank_Id_LSB, DRG_LV2_Base.Bank_Id_MSB, DRG_LV2_Base.Program_Id, DRG_LV2_Base.Kit_Ptr->Name);
}
}
else
{
DR_LOG_INFO_5( "New kit id: (%d) Bank/Program: (%d/%d/%d) Name: [%s]!",
kit_id, DRG_LV2_Base.Bank_Id_LSB_New, DRG_LV2_Base.Bank_Id_MSB_New, DRG_LV2_Base.Program_Id_New, Kit_Ptr->Name);
DRG_LV2_Base.Bank_Id_LSB = DRG_LV2_Base.Bank_Id_LSB_New;
DRG_LV2_Base.Bank_Id_MSB = DRG_LV2_Base.Bank_Id_MSB_New;
DRG_LV2_Base.Program_Id = DRG_LV2_Base.Program_Id_New;
DRG_LV2_Base.Kit_Id = kit_id;
DRG_LV2_Base.Kit_Id_New = kit_id;
DRG_LV2_Base.Kit_Ptr = Kit_Ptr;
status = DR_LV2_Kit_Sample_Load( Kit_Ptr);
LV2_Atom_Forge_Frame obj_frame;
DR_LOG_INFO_0( "Sample loaded!");
lv2_atom_forge_frame_time( &( DRG_LV2_Base.Forge), 0);
lv2_atom_forge_object( &( DRG_LV2_Base.Forge), &obj_frame, 1, DRG_LV2_Base.URIS.UI_Msg);
lv2_atom_forge_property_head( &( DRG_LV2_Base.Forge), DRG_LV2_Base.URIS.Kit_Update_Reply, 0);
lv2_atom_forge_long( &( DRG_LV2_Base.Forge), DRG_LV2_Base.Kit_Id); // Cur kit Id
lv2_atom_forge_pop( &( DRG_LV2_Base.Forge), &obj_frame);
DR_LOG_INFO_2( "Kit Update Reply: Kit_Id: (%ld) Kit_Name: [%s]", DRG_LV2_Base.Kit_Id, DRG_LV2_Base.Kit_Ptr->Name);
}
}
return( status);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void *DR_LV2_Load_Thread()
{
DRT_Status status;
DR_LOG_INFO_0( "Start Load Thread!");
for(;;)
{
pthread_mutex_lock( &( DRG_LV2_Base.Load_Mutex));
pthread_cond_wait( &( DRG_LV2_Base.Load_Cond), &( DRG_LV2_Base.Load_Mutex));
DR_LOG_INFO_0( "Load_Thread: New load!\n");
pthread_mutex_unlock( &(DRG_LV2_Base.Load_Mutex));
if( ( status = DR_LV2_CurKit_Sample_Load()) != DRS_OK)
{
fprintf( stderr, "Can't load kit sample (%d) !", status);
}
pthread_mutex_lock( &(DRG_LV2_Base.Load_Mutex));
pthread_mutex_unlock( &(DRG_LV2_Base.Load_Mutex));
/*
// old_samples = DRG_LV2_Base.Samples;
// old_scount = DRG_LV2_Base.Num_Samples;
request_orig = request = DRG_LV2_Base.Request_Buf[ DRG_LV2_Base.CurReq];
if( !strncmp( request, "file://", 7))
{
request += 7;
}
// loaded_samples = load_hydrogen_kit(request,drmr->rate,&loaded_count);
if( !loaded_samples)
{
fprintf(stderr,"Failed to load kit at: %s\n",request);
pthread_mutex_lock( &(DRG_LV2_Base.Load_Mutex));
// DRG_LV2_Base.Num_Samples = 0;
// DRG_LV2_Base.Samples = NULL;
pthread_mutex_unlock( &(DRG_LV2_Base.Load_Mutex));
}
else
{
// just lock for the critical moment when we swap in the new kit
printf( "loaded kit at: %s\n", request);
pthread_mutex_lock( &(DRG_LV2_Base.Load_Mutex));
// DRG_LV2_Base.Samples = loaded_samples;
// DRG_LV2_Base.Num_Samples = loaded_count;
pthread_mutex_unlock( &(DRG_LV2_Base.Load_Mutex));
}
// if( old_scount > 0) free_samples( old_samples, old_scount);
DRG_LV2_Base.Current_Path = request_orig;
current_kit_changed = 1;
*/
}
return 0;
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
/*
static inline LV2_Atom *build_state_message(DrMr *drmr)
{
LV2_Atom_Forge_Frame set_frame;
LV2_Atom *msg = (LV2_Atom *)lv2_atom_forge_object( &drmr->forge, &set_frame, 1, drmr->uris.get_state);
if( drmr->current_path)
{
lv2_atom_forge_property_head( &drmr->forge, drmr->uris.kit_path, 0);
lv2_atom_forge_string( &drmr->forge, drmr->current_path, strlen( drmr->current_path));
}
lv2_atom_forge_property_head(&drmr->forge, drmr->uris.velocity_toggle,0);
lv2_atom_forge_bool(&drmr->forge, drmr->ignore_velocity?true:false);
lv2_atom_forge_property_head(&drmr->forge, drmr->uris.note_off_toggle,0);
lv2_atom_forge_bool(&drmr->forge, drmr->ignore_note_off?true:false);
lv2_atom_forge_property_head(&drmr->forge, drmr->uris.channel_nb,0);
lv2_atom_forge_int(&drmr->forge, drmr->channel_nb);
lv2_atom_forge_property_head(&drmr->forge, drmr->uris.zero_position,0);
lv2_atom_forge_int(&drmr->forge, drmr->zero_position);
lv2_atom_forge_pop(&drmr->forge,&set_frame);
return msg;
}
*/
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
/*
static inline LV2_Atom *DR_LV2_Message_Midi_Info_Build( DRT_LV2_Base *LV2_Base_Ptr, uint8_t *Data)
{
LV2_Atom_Forge_Frame set_frame;
LV2_Atom *msg;
msg = (LV2_Atom *)lv2_atom_forge_object( &( DRG_LV2_Base.Forge), &set_frame, 1, DRG_LV2_Base.URIS.midi_info);
lv2_atom_forge_property_head( &( DRG_LV2_Base.Forge), DRG_LV2_Base.URIS.midi_event, 0);
lv2_atom_forge_write( &( DRG_LV2_Base.Forge), Data, 3);
lv2_atom_forge_pop( &( DRG_LV2_Base.Forge), &set_frame);
return( msg);
}
*/
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
DRT_Status DR_UI_Port_Notify( LV2_URID URId, float Value)
{
LV2_Atom_Forge_Frame set_frame;
lv2_atom_forge_frame_time( &( DRG_LV2_Base.Forge), 0);
lv2_atom_forge_object( &( DRG_LV2_Base.Forge), &set_frame, 1, DRG_LV2_Base.URIS.UI_Msg);
lv2_atom_forge_property_head( &( DRG_LV2_Base.Forge), URId, 0);
lv2_atom_forge_float( &( DRG_LV2_Base.Forge), Value);
lv2_atom_forge_pop( &( DRG_LV2_Base.Forge), &set_frame);
DR_LOG_INFO_2( "Notify: URId: (%d) Value: (%d)!", URId, (int)Value);
return( DRS_OK);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
/*
static inline void layer_to_sample( drmr_sample *sample, float gain)
{
int i;
float mapped_gain = ( 1 - ( gain / GAIN_MIN));
if( mapped_gain > 1.0f) mapped_gain = 1.0f;
for( i = 0; i < sample->layer_count; i++)
{
if( sample->layers[i].min <= mapped_gain &&
(sample->layers[i].max > mapped_gain ||
(sample->layers[i].max == 1 && mapped_gain == 1)))
{
sample->limit = sample->layers[i].limit;
sample->info = sample->layers[i].info;
sample->data = sample->layers[i].data;
return;
}
}
fprintf(stderr,"Couldn't find layer for gain %f in sample\n\n",gain);
// to avoid not playing something, and to deal with kits like the
// k-27_trash_kit, let's just use the first layer
sample->limit = sample->layers[0].limit;
sample->info = sample->layers[0].info;
sample->data = sample->layers[0].data;
}
*/
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static inline void DR_Layer_To_Sample( DRT_Sample *Sample_Ptr, float Gain)
{
NDT_Node *first_node_ptr, *cur_node_ptr;
DRT_Layer *cur_layer_ptr;
int i = 0;
DRT_Boolean found = DRD_FALSE;
// float mapped_gain = ( 1 - ( Gain / DRD_GAIN_MIN));
float mapped_gain = Gain;
if( mapped_gain > 1.0f) mapped_gain = 1.0f;
first_node_ptr = Sample_Ptr->Instrument_Ptr->Layer_DS_Ptr->Index_Tab[NDD_INDEX_PRIMARY].Head;
cur_node_ptr = first_node_ptr;
while( ( cur_node_ptr != NULL) && ( found == DRD_FALSE))
{
cur_layer_ptr = (DRT_Layer *)cur_node_ptr->Value;
if( ( cur_layer_ptr->Min <= mapped_gain) &&
( ( cur_layer_ptr->Max > mapped_gain) || ( ( cur_layer_ptr->Max == 1) && ( mapped_gain == 1))))
{
found = DRD_TRUE;
}
else
{
cur_node_ptr = cur_node_ptr->Right;
i++;
}
}
if( cur_node_ptr == NULL)
{
cur_node_ptr = first_node_ptr;
cur_layer_ptr = (DRT_Layer *)cur_node_ptr->Value;
i=0;
}
Sample_Ptr->Layer_Ptr = cur_layer_ptr;
Sample_Ptr->Data_Ptr = cur_layer_ptr->Sample_Ptr;
Sample_Ptr->Limit = cur_layer_ptr->Sample_Size;
Sample_Ptr->SF_Info_Ptr = cur_layer_ptr->SF_Info_Ptr;
DR_LOG_INFO_3( "Layer: (%d) MGain: (%f) Gain: (%f)", i, mapped_gain, Gain);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static inline void DR_Sample_Trigger( int Sample_Id, uint8_t *const Data, uint32_t Offset)
{
// need to mutex this to avoid getting the samples array
// changed after the check that the midi-note is valid
pthread_mutex_lock( &( DRG_LV2_Base.Load_Mutex));
DR_LOG_INFO_2( "Trigger Sample: Id: (%d) Offset: (%d)", Sample_Id, Offset);
if( ( Sample_Id >= 0) && ( Sample_Id < DRG_LV2_Base.Sample_Number))
{
/*
if( Data)
{
lv2_atom_forge_frame_time( &( DRG_LV2_Base.Forge), 0);
DR_LV2_Message_Midi_Info_Build( LV2_Base_Ptr, Data);
}
*/
DRG_LV2_Base.Samples[Sample_Id].Active = 1;
DRG_LV2_Base.Samples[Sample_Id].Offset = 0;
DRG_LV2_Base.Samples[Sample_Id].Velocity = *( DRG_Base.Velocity_Ignore_Flag_Ptr) ? 1.0f : ( (float)Data[2]) / DRD_VELOCITY_MAX;
DRG_LV2_Base.Samples[Sample_Id].Data_Offset = Offset;
DRG_LV2_Base.Samples[Sample_Id].Sustained = false;
if( DRG_LV2_Base.Samples[Sample_Id].Instrument_Ptr->Layer_DS_Ptr->Index_Tab[NDD_INDEX_PRIMARY].Node_Number > 0)
{
// drmr currently has 32 hard-coded gains so just use the last gain
// to prevent a segfault
int gain_idx = Sample_Id < 32 ? Sample_Id : 31;
// DR_Layer_To_Sample( &(DRG_LV2_Base.Samples[Sample_Id]), *( DRG_LV2_Base.Gains[ gain_idx]));
DR_Layer_To_Sample( &(DRG_LV2_Base.Samples[Sample_Id]), DRG_LV2_Base.Samples[Sample_Id].Velocity);
if( DRG_LV2_Base.Samples[Sample_Id].Limit == 0)
fprintf(stderr,"Failed to find layer at: %i for %f\n", Sample_Id, *( DRG_LV2_Base.Gains[ gain_idx]));
}
}
pthread_mutex_unlock( &( DRG_LV2_Base.Load_Mutex));
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static inline void DR_Sample_Untrigger( int Sample_Id, uint32_t Offset)
{
pthread_mutex_lock( &( DRG_LV2_Base.Load_Mutex));
if( DRG_LV2_Base.Sustain == true)
{
DR_LOG_INFO_2( "Sustains Sample: Id: (%d) Offset: (%d)", Sample_Id, Offset);
DRG_LV2_Base.Samples[Sample_Id].Sustained = true;
}
else
{
DR_LOG_INFO_2( "UnTrigger Sample: Id: (%d) Offset: (%d)", Sample_Id, Offset);
/*
if (nn >= 0 && nn < drmr->num_samples) {
if (drmr->samples[nn].layer_count > 0) {
layer_to_sample(drmr->samples+nn,*(drmr->gains[nn]));
if (drmr->samples[nn].limit == 0)
fprintf(stderr,"Failed to find layer at: %i for %f\n",nn,*drmr->gains[nn]);
}
drmr->samples[nn].active = 0;
drmr->samples[nn].dataoffset = offset;
}
*/
DRG_LV2_Base.Samples[Sample_Id].Active = 0;
DRG_LV2_Base.Samples[Sample_Id].Data_Offset = Offset;
DRG_LV2_Base.Samples[Sample_Id].Sustained = false;
}
pthread_mutex_unlock( &( DRG_LV2_Base.Load_Mutex));
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static inline void DR_Sample_UnSustain( uint32_t Offset)
{
int sample_id;
for( sample_id =0; sample_id < DRD_PORT_NUMBER_MAX; sample_id++)
{
if( DRG_LV2_Base.Samples[sample_id].Sustained)
{
DR_Sample_Untrigger( sample_id, Offset);
}
}
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static LV2_Handle DR_LV2_Instantiate( const LV2_Descriptor *LV2_Descriptor_Ptr,
double SampleRate,
const char *Bundle_Path,
const LV2_Feature * const *LV2_Features_Ptr)
{
DRT_Status status;
int i;
// DRT_LV2_Base *lv2_base_ptr;
fprintf( stderr, "LV2 Instantiate\n");
/*
if( ( lv2_base_ptr = malloc( sizeof( DRT_LV2_Base))) == NULL)
{
fprintf( stderr, "Can't allocate LV2 Base!\n");
return( (LV2_Handle)NULL);
}
*/
DRG_LV2_Base.Map_Ptr = NULL;
DRG_LV2_Base.Logger.log = NULL;
DRG_LV2_Base.Kit_Ptr = NULL;
DRG_LV2_Base.Bank_Id_LSB = -1;
DRG_LV2_Base.Bank_Id_LSB = -1;
DRG_LV2_Base.Program_Id = -1;
DRG_LV2_Base.Bank_Id_LSB_New = 0;
DRG_LV2_Base.Bank_Id_MSB_New = 0;
DRG_LV2_Base.Program_Id_New = 0;
DRG_LV2_Base.Kit_Id = DRD_ID_UNKNOWN;
DRG_LV2_Base.Kit_Id_New = DRD_ID_UNKNOWN;
DRG_LV2_Base.Current_Path = NULL;
DRG_LV2_Base.CurReq = -1;
// DRG_LV2_Base.Channel_Id = 0;
DRG_LV2_Base.Zero_Position = 0;
DRG_LV2_Base.Sustain = false;
DRG_LV2_Base.Sample_Number = 0;
while( *LV2_Features_Ptr != NULL)
{
fprintf( stderr, "Feature URI: [%s]\n", (*LV2_Features_Ptr)->URI);
if( !strcmp( ( *LV2_Features_Ptr)->URI, LV2_URID_URI "#map"))
{
DRG_LV2_Base.Map_Ptr = (LV2_URID_Map *)( ( *LV2_Features_Ptr)->data);
}
else
{
if( !strcmp( ( *LV2_Features_Ptr)->URI, LV2_LOG__log))
{
DRG_LV2_Base.Logger.log = (LV2_Log_Log *)( ( *LV2_Features_Ptr)->data);
}
}
LV2_Features_Ptr++;
}
if( ( DRG_LV2_Base.Map_Ptr == NULL) || ( DRG_LV2_Base.Logger.log == NULL))
{
if( DRG_LV2_Base.Map_Ptr == NULL)
{
fprintf( stderr, "LV2 host does not support urid#map!\n");
}
if( DRG_LV2_Base.Logger.log == NULL)
{
fprintf( stderr, "LV2 host does not support log#log!\n");
}
}
else
{
// lv2_log_logger_init( &(DRG_LV2_Base.Logger), DRG_LV2_Base.Map_Ptr, DRG_LV2_Base.Logger.log);
lv2_log_logger_set_map( &(DRG_LV2_Base.Logger), DRG_LV2_Base.Map_Ptr);
// if( ( status = DR_DataStruct_Init( DR_LV2_Log_Write, (DRT_SampleRate)SampleRate, DRD_THREAD_NUMBER_DEFAULT)) != DRS_OK)
if( ( status = DR_DataStruct_Init( DRD_LOG_WRITER_DEFAULT, (DRT_SampleRate)SampleRate, DRD_THREAD_NUMBER_DEFAULT)) != DRS_OK)
{
fprintf( stderr, "Can't init data structures (%d)!\n", status);
}
else
{
lv2_log_error( &(DRG_LV2_Base.Logger), "Test error log <%s>!\n", "Krash!");
DR_LOG_ERROR_1( "Test error log <%s>!", "Krash!");
if( pthread_mutex_init( &( DRG_LV2_Base.Load_Mutex), 0))
{
fprintf( stderr, "Could not initialize load_mutex!\n");
}
else if( pthread_cond_init( &( DRG_LV2_Base.Load_Cond), 0))
{
fprintf( stderr, "Could not initialize load_cond!\n");
}
else
{
DR_LV2_Map_URIS( DRG_LV2_Base.Map_Ptr, &( DRG_LV2_Base.URIS));
lv2_atom_forge_init( &(DRG_LV2_Base.Forge), DRG_LV2_Base.Map_Ptr);
if( pthread_create( &DRG_LV2_Base.Load_Thread, 0, (void * (*)(void *))DR_LV2_Load_Thread, NULL))
{
fprintf( stderr, "Could not initialize loading thread!\n");
}
else
{
if( ( DRG_LV2_Base.Request_Buf = malloc( DRD_REQ_BUF_SIZE * sizeof(char *))) == NULL)
{
fprintf( stderr, "Cant'allocate Request buffer!\n");
}
else
{
memset( DRG_LV2_Base.Request_Buf, 0, DRD_REQ_BUF_SIZE * sizeof(char *));
if( ( DRG_LV2_Base.Left = malloc( DRD_PORT_NUMBER_MAX * sizeof(float *))) == NULL)
{
fprintf( stderr, "Cant'allocate Left buffer!\n");
// free( lv2_base_ptr);
return( NULL);
}
else
{
if( ( DRG_LV2_Base.Right = malloc( DRD_PORT_NUMBER_MAX * sizeof(float *))) == NULL)
{
fprintf( stderr, "Cant'allocate Right buffer!\n");
}
else
{
if( ( DRG_LV2_Base.Gains = malloc( DRD_PORT_NUMBER_MAX * sizeof(float *))) == NULL)
{
fprintf( stderr, "Cant'allocate Gains buffer!\n");
}
else
{
if( ( DRG_LV2_Base.Pans = malloc( DRD_PORT_NUMBER_MAX * sizeof(float *))) == NULL)
{
fprintf( stderr, "Cant'allocate Pans buffer!\n");
}
else
{
for( i = 0; i < 32; i++)
{
DRG_LV2_Base.Gains[i] = NULL;
DRG_LV2_Base.Pans[i] = NULL;
}
if( ( status = DR_Kits_Load()) != DRS_OK)
{
fprintf( stderr, "Can't load kits (%d)!\n", status);
}
else
{
if( ( status = DR_LV2_CurKit_Sample_Load()) != DRS_OK)
{
fprintf( stderr, "Can't load kit sample (%d)!\n", status);
}
else
{
DR_LOG_INFO_1( "DRG_Base_Ptr: (%lx)!", (char *)( &DRG_Base));
return( (LV2_Handle)&DRG_LV2_Base);
}
}
}
free( DRG_LV2_Base.Gains);
}
free( DRG_LV2_Base.Right);
}
free( DRG_LV2_Base.Left);
}
free( DRG_LV2_Base.Request_Buf);
}
}
}
DR_DataStruct_DeInit();
}
}
return( (LV2_Handle)NULL);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void DR_LV2_Connect_Port( LV2_Handle Instance_Ptr, uint32_t Port_Id, void *Data_Ptr)
{
DRT_LV2_Base *lv2_base_ptr = (DRT_LV2_Base *)Instance_Ptr;
DRT_Port_Index port_index = (DRT_Port_Index)Port_Id;
// DR_LOG_INFO_1( "LV2 Connect Port (%d)!", Port_Id);
switch( port_index)
{
case DRD_LV2_CONTROL:
{
lv2_base_ptr->Control_Port = (LV2_Atom_Sequence *)Data_Ptr;
break;
}
case DRD_LV2_CORE_EVENT:
{
lv2_base_ptr->Core_Event_Port = (LV2_Atom_Sequence *)Data_Ptr;
break;
}
case DRD_LV2_CHANNEL_ID:
{
if( Data_Ptr) DRG_Base.Channel_Id_Ptr = (float *)Data_Ptr;
break;
}
case DRD_LV2_BASE_NOTE:
{
if( Data_Ptr) DRG_Base.Base_Note_Ptr = (float *)Data_Ptr;
break;
}
case DRD_LV2_VELOCITY_IGNORE_NOTE:
{
if( Data_Ptr) DRG_Base.Velocity_Ignore_Note_Ptr = (float *)Data_Ptr;
break;
}
case DRD_LV2_NOTE_OFF_IGNORE_NOTE:
{
if( Data_Ptr) DRG_Base.Note_Off_Ignore_Note_Ptr = (float *)Data_Ptr;
break;
}
case DRD_LV2_VELOCITY_IGNORE_FLAG:
{
if( Data_Ptr) DRG_Base.Velocity_Ignore_Flag_Ptr = (float *)Data_Ptr;
break;
}
case DRD_LV2_NOTE_OFF_IGNORE_FLAG:
{
if( Data_Ptr) DRG_Base.Note_Off_Ignore_Flag_Ptr = (float *)Data_Ptr;
break;
}
default:
{
if( port_index == DRD_LV2_MASTER_LEFT)
{
lv2_base_ptr->Master_Left = (float *)Data_Ptr;
}
else if( port_index == DRD_LV2_MASTER_RIGHT)
{
lv2_base_ptr->Master_Right = (float *)Data_Ptr;
}
else if( port_index >= DRD_LV2_LEFT_00 && port_index <= DRD_LV2_RIGHT_31)
{
int outoff = (port_index - DRD_LV2_LEFT_00) / 2;
if( ( port_index - DRD_LV2_LEFT_00) % 2)
{
lv2_base_ptr->Right[outoff] = (float *)Data_Ptr;
}
else
{
lv2_base_ptr->Left[outoff] = (float *)Data_Ptr;
}
}
else if( port_index >= DRD_LV2_GAIN_00 && port_index <= DRD_LV2_GAIN_31)
{
int goff = port_index - DRD_LV2_GAIN_00;
lv2_base_ptr->Gains[goff] = (float *)Data_Ptr;
}
else if( port_index >= DRD_LV2_PAN_00 && port_index <= DRD_LV2_PAN_31)
{
int poff = port_index - DRD_LV2_PAN_00;
lv2_base_ptr->Pans[poff] = (float *)Data_Ptr;
}
else
{
fprintf( stderr, "LV2 Connect Port: unknown port: (%d)!\n", Port_Id);
}
break;
}
}
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void DR_LV2_Activate( LV2_Handle instance)
{
DR_LOG_INFO_0( "LV2 Activate!");
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void DR_LV2_Run( LV2_Handle Instance_Ptr, uint32_t N_Samples)
{
DRT_Status status;
int i, j, base_note;
DRT_LV2_Base *lv2_base_ptr = (DRT_LV2_Base *)Instance_Ptr;
// fprintf( stderr, "LV2 Run!\n");
base_note = (int)floorf( *( DRG_Base.Base_Note_Ptr));
const uint32_t event_capacity = lv2_base_ptr->Core_Event_Port->atom.size;
lv2_atom_forge_set_buffer( &lv2_base_ptr->Forge, (uint8_t *)lv2_base_ptr->Core_Event_Port, event_capacity);
LV2_Atom_Forge_Frame seq_frame;
lv2_atom_forge_sequence_head( &(lv2_base_ptr->Forge), &seq_frame, 0);
LV2_ATOM_SEQUENCE_FOREACH( lv2_base_ptr->Control_Port, ev_ptr)
{
DR_LOG_INFO_0( "LV2 Event!");
if( ev_ptr->body.type == lv2_base_ptr->URIS.Midi_Event)
{
uint8_t nn;
uint8_t *const data = (uint8_t *const)(ev_ptr + 1);
uint32_t offset = ( ev_ptr->time.frames > 0 && ev_ptr->time.frames < N_Samples) ? ev_ptr->time.frames : 0;
uint8_t channel = *data & 15;
uint8_t controler;
uint8_t value;
// fprintf( stderr, " Midi Event!\n");
if( ( *( DRG_Base.Channel_Id_Ptr) == 0) || ( channel == ( *( DRG_Base.Channel_Id_Ptr) - 1)))
{
switch( ( *data) >> 4)
{
case 8: // Note Off
{
if( !*( DRG_Base.Note_Off_Ignore_Flag_Ptr))
{
nn = data[1];
nn -= base_note;
DR_Sample_Untrigger( nn, offset);
}
break;
}
case 9: // Note On
{
nn = data[1];
if( nn == *( DRG_Base.Velocity_Ignore_Note_Ptr))
{
*( DRG_Base.Velocity_Ignore_Flag_Ptr) = (float)( (int)*( DRG_Base.Velocity_Ignore_Flag_Ptr) ^ true);
DR_LOG_INFO_2( "Velocity Ignore: [%f] - [%f]", *( DRG_Base.Velocity_Ignore_Flag_Ptr), *( DRG_Base.Velocity_Ignore_Note_Ptr));
DR_UI_Port_Notify( DRG_LV2_Base.URIS.Velocity_Ignore_Flag_Toggle, *( DRG_Base.Velocity_Ignore_Flag_Ptr));
}
else
{
if( nn == *( DRG_Base.Note_Off_Ignore_Note_Ptr))
{
*( DRG_Base.Note_Off_Ignore_Flag_Ptr) = (float)( (int)*( DRG_Base.Note_Off_Ignore_Flag_Ptr) ^ true);
DR_LOG_INFO_2( "Note Off Ignore: [%f] - [%f]", *( DRG_Base.Note_Off_Ignore_Flag_Ptr), *( DRG_Base.Note_Off_Ignore_Note_Ptr));
DR_UI_Port_Notify( DRG_LV2_Base.URIS.Note_Off_Ignore_Flag_Toggle, *( DRG_Base.Note_Off_Ignore_Flag_Ptr));
}
else
{
if( nn == 26)
{
LV2_Atom_Forge_Frame set_frame;
DR_LOG_INFO_1( "Kit Update Reply: Kit_Id: (%d)", lv2_base_ptr->Kit_Id);
lv2_atom_forge_frame_time( &( DRG_LV2_Base.Forge), 0);
lv2_atom_forge_object( &( DRG_LV2_Base.Forge), &set_frame, 1, DRG_LV2_Base.URIS.UI_Msg);
lv2_atom_forge_property_head( &( DRG_LV2_Base.Forge), DRG_LV2_Base.URIS.Kit_Update_Reply, 0);
lv2_atom_forge_long( &( DRG_LV2_Base.Forge), lv2_base_ptr->Kit_Id);
lv2_atom_forge_pop( &( DRG_LV2_Base.Forge), &set_frame);
}
else
{
// DR_LOG_INFO_1( "ZZZ Update Kit Name Tab: [%d]", nn);
nn -= base_note;
DR_Sample_Trigger( nn, data, offset);
}
}
}
break;
}
case 11: // Control Change
{
controler = data[1];
value = data[2];
switch( controler)
{
case 0: // Bank MSB Select
{
DR_LOG_INFO_1( "Bank MSB select: (%d)!", value);
lv2_base_ptr->Bank_Id_MSB_New = value;
break;
}
case 32: // Bank LSB Select
{
DR_LOG_INFO_1( "Bank LSB select: (%d)!", value);
lv2_base_ptr->Bank_Id_LSB_New = value;
break;
}
case 64: // Sustain
{
DR_LOG_INFO_1( "Sustain: (%d)!", value);
if( value == 127)
{
lv2_base_ptr->Sustain = true;
}
else
{
lv2_base_ptr->Sustain = false;
}
if( !( lv2_base_ptr->Sustain))
{
DR_Sample_UnSustain( offset);
}
break;
}
default:
{
DR_LOG_WARNING_2( "Unhandled controler: (%d) value: (%d)!", controler, value);
break;
}
}
break;
}
case 12: // Program Change
{
value = data[1];
DR_LOG_INFO_1( "Program change: (%d)!", value);
lv2_base_ptr->Program_Id_New = value;
pthread_cond_signal( &( lv2_base_ptr->Load_Cond));
break;
}
default:
{
// fprintf( stderr, "Unhandeled status: (%i) Data 1: (%i) Data 2: (%d)\n", ( *data) >> 4, data[1], data[2]);
break;
}
}
}
}
else if( ev_ptr->body.type == lv2_base_ptr->URIS.Atom_Object)
{
DR_LOG_INFO_0( "LV2 AO...");
const LV2_Atom_Object *obj_ptr = (LV2_Atom_Object *)&( ev_ptr->body);
if( obj_ptr->body.otype == lv2_base_ptr->URIS.UI_Msg)
{
const LV2_Atom *ui_enable_ptr = NULL;
const LV2_Atom *ui_disable_ptr = NULL;
const LV2_Atom *kit_update_request_ptr = NULL;
const LV2_Atom *kit_update_reply_ptr = NULL;
lv2_atom_object_get( obj_ptr,
lv2_base_ptr->URIS.UI_Enable, &ui_enable_ptr,
lv2_base_ptr->URIS.UI_Disable, &ui_disable_ptr,
lv2_base_ptr->URIS.Kit_Update_Request, &kit_update_request_ptr,
lv2_base_ptr->URIS.Kit_Update_Reply, &kit_update_reply_ptr,
0);
if( ui_enable_ptr)
{
LV2_Atom_Forge_Frame obj_frame;
DR_LOG_INFO_0( "UI Enable!");
lv2_atom_forge_frame_time( &( DRG_LV2_Base.Forge), 0);
lv2_atom_forge_object( &( DRG_LV2_Base.Forge), &obj_frame, 1, DRG_LV2_Base.URIS.UI_Msg);
lv2_atom_forge_property_head( &( DRG_LV2_Base.Forge), DRG_LV2_Base.URIS.Kit_Update_Reply, 0);
lv2_atom_forge_long( &( DRG_LV2_Base.Forge), DRG_LV2_Base.Kit_Id); // Cur kit Id
lv2_atom_forge_pop( &( DRG_LV2_Base.Forge), &obj_frame);
DR_LOG_INFO_2( "Kit Update Reply: Kit_Id: (%ld) Kit_Name: [%s]", DRG_LV2_Base.Kit_Id, DRG_LV2_Base.Kit_Ptr->Name);
/*
DRT_Kit_Name *kit_name_tab;
long kit_number;
if( ( status = DR_Kits_Name_Get( &kit_name_tab, &kit_number)) != DRS_OK)
{
DR_LOG_ERROR_1( "Can't get kit names: (%d)", status);
}
else
{
LV2_Atom_Forge_Frame obj_frame, tup_frame;
LV2_Atom_Forge_Ref ref;
DR_LOG_INFO_3( "Update Kit Name: Nb: (%d) First: [%s] Size: (%ld)", kit_number, kit_name_tab[0].Name, sizeof( DRT_Kit_Name) * kit_number);
/*
lv2_atom_forge_frame_time( &( DRG_LV2_Base.Forge), 0);
lv2_atom_forge_object( &( DRG_LV2_Base.Forge), &obj_frame, 1, DRG_LV2_Base.URIS.UI_Msg);
lv2_atom_forge_property_head( &( DRG_LV2_Base.Forge), DRG_LV2_Base.URIS.Kit_Name_Update, 0);
lv2_atom_forge_tuple( &( DRG_LV2_Base.Forge), &tup_frame);
lv2_atom_forge_long( &( DRG_LV2_Base.Forge), kit_number); // Max number of kit
lv2_atom_forge_long( &( DRG_LV2_Base.Forge), DRG_LV2_Base.Kit_Ptr->Id); // Cur kit Id
// ref = lv2_atom_forge_write( &( DRG_LV2_Base.Forge), &( kit_name_tab[i]), sizeof( DRT_Kit_Name) * kit_number);
// DR_LOG_INFO_1( "Forge: KNT Ref: (%lx)", ref);
lv2_atom_forge_pop( &( DRG_LV2_Base.Forge), &tup_frame);
lv2_atom_forge_pop( &( DRG_LV2_Base.Forge), &obj_frame);
DR_LOG_INFO_3( "Kit Name Update: Kit_Number: (%ld) Kit_Id: (%ld) Kit_Name: [%s]", kit_number, DRG_LV2_Base.Kit_Ptr->Id, DRG_LV2_Base.Kit_Ptr->Name);
}
*/
}
if( ui_disable_ptr)
{
DR_LOG_INFO_0( "UI Disable!");
}
if( kit_update_request_ptr)
{
lv2_base_ptr->Kit_Id_New = ( (const LV2_Atom_Long *)kit_update_request_ptr)->body;
DR_LOG_INFO_1( "Kit Update Request: Kit_Id: (%ld)!", lv2_base_ptr->Kit_Id_New);
pthread_cond_signal( &( lv2_base_ptr->Load_Cond));
}
if( kit_update_reply_ptr)
{
DR_LOG_ERROR_0( "Kit Update Reply: This shouldn't be received by me!");
}
/*
if( obj_ptr->body.otype == lv2_base_ptr->URIS.ui_msg)
{
const LV2_Atom *path = NULL;
const LV2_Atom *trigger = NULL;
const LV2_Atom *ignvel = NULL;
const LV2_Atom *ignno = NULL;
const LV2_Atom *channel_id = NULL;
const LV2_Atom *zerop = NULL;
const LV2_Atom *sample_add = NULL;
const LV2_Atom *sample_remove = NULL;
lv2_atom_object_get( obj_ptr,
lv2_base_ptr->URIS.kit_path, &path,
lv2_base_ptr->URIS.sample_trigger, &trigger,
lv2_base_ptr->URIS.velocity_toggle, &ignvel,
lv2_base_ptr->URIS.note_off_toggle, &ignno,
lv2_base_ptr->URIS.channel_id, &channel_id,
lv2_base_ptr->URIS.zero_position, &zerop,
lv2_base_ptr->URIS.sample_add, &sample_add,
lv2_base_ptr->URIS.sample_remove, &sample_remove,
0);
if( path)
{
int reqpos = ( lv2_base_ptr->CurReq + 1) % DRD_REQ_BUF_SIZE;
char *tmp = NULL;
if( reqpos >= 0 && lv2_base_ptr->Request_Buf[reqpos])
tmp = lv2_base_ptr->Request_Buf[reqpos];
lv2_base_ptr->Request_Buf[reqpos] = strdup( LV2_ATOM_BODY( path));
lv2_base_ptr->CurReq = reqpos;
if( tmp) free(tmp);
fprintf( stderr, "Path!\n");
}
if( trigger)
{
int32_t si = ( ( const LV2_Atom_Int *)trigger)->body;
uint8_t mdata[3];
uint32_t offset = ( ev_ptr->time.frames > 0 && ev_ptr->time.frames < N_Samples) ? ev_ptr->time.frames : 0;
fprintf(stderr, "Trigger event!\n");
mdata[0] = 0x90; // note on
mdata[1] = si + base_note;
mdata[2] = 0x7f;
DR_Sample_Trigger( lv2_base_ptr, si, mdata, offset);
}
if( ignvel)
DRG_Base.Velocity_Ignore_Flag = ((const LV2_Atom_Bool*)ignvel)->body;
if( ignno)
{
fprintf( stderr, "Change Note Off Ignore Flag!\n");
// DRG_Base.Note_Off_Ignore_Flag = ((const LV2_Atom_Bool*)ignno)->body;
}
if( channel_id)
DRG_Base.Channel_Id_Ptr = ((const LV2_Atom_Int*)channel_id)->body;
if( zerop)
lv2_base_ptr->Zero_Position = ((const LV2_Atom_Int*)zerop)->body;
if( sample_add)
{
fprintf(stderr, "Sample Add event!\n");
lv2_atom_forge_frame_time( &lv2_base_ptr->Forge, 0);
// build_update_message( lv2_base_ptr);
}
if( sample_remove)
{
fprintf(stderr, "Sample Remove event (%d)\n", ( ( const LV2_Atom_Int *)sample_remove)->body);
lv2_atom_forge_frame_time( &(lv2_base_ptr->Forge), 0);
// build_update_message( lv2_base_ptr);
}
fprintf( stderr, "LV2 AO End!\n");
}
else if( obj_ptr->body.otype == lv2_base_ptr->URIS.get_state)
{
fprintf( stderr, "Get state!\n");
lv2_atom_forge_frame_time( &(lv2_base_ptr->Forge), 0);
// build_state_message( lv2_base_ptr);
}
*/
}
}
else
{
DR_LOG_WARNING_2( "Unrecognized event (%d) != (%d)", ev_ptr->body.type, lv2_base_ptr->URIS.Atom_Object);
}
}
/*
if( ( lv2_base_ptr->curReq >= 0) &&
lv2_base_ptr->request_buf[lv2_base_ptr->curReq] &&
( !lv2_base_ptr->Current_Path || strcmp( lv2_base_ptr->Current_Path, lv2_base_ptr->Request_Buf[lv2_base_ptr->Cur_Req])))
{
pthread_cond_signal( &( lv2_base_ptr->Load_Cond));
}
*/
/*
if( current_kit_changed)
{
current_kit_changed = 0;
lv2_atom_forge_frame_time( &drmr->forge, 0);
build_update_message( drmr);
fprintf(stderr, "Kit Changes!\n");
}
*/
lv2_atom_forge_pop( &( lv2_base_ptr->Forge), &seq_frame);
pthread_mutex_lock( &( lv2_base_ptr->Load_Mutex));
for( j = 0; j < N_Samples; j++)
{
lv2_base_ptr->Master_Left[j] = 0.0f;
lv2_base_ptr->Master_Right[j] = 0.0f;
}
for( i = 0; i < DR_MIN( lv2_base_ptr->Sample_Number, 32); i++)
{
int pos,lim;
DRT_Sample *cur_sample = lv2_base_ptr->Samples + i;
if( ( cur_sample->Active || cur_sample->Data_Offset) && ( cur_sample->Limit > 0))
{
float coef_right, coef_left;
// fprintf( stderr, ".");
if( i < 32)
{
float gain = DRD_DB_CO( *( lv2_base_ptr->Gains[i]));
float pan_right = ( ( *( lv2_base_ptr->Pans[i])) + 1 ) / 2.0f;
float pan_left = 1 - pan_right;
coef_right = ( pan_right * ( DRD_DB3SCALE * pan_right + DRD_DB3SCALEPO)) * gain * cur_sample->Velocity;
coef_left = ( pan_left * ( DRD_DB3SCALE * pan_left + DRD_DB3SCALEPO)) * gain * cur_sample->Velocity;
}
else
{
coef_right = coef_left = 1.0f;
}
int data_start, data_end;
if( cur_sample->Active)
{
data_start = cur_sample->Data_Offset;
data_end = N_Samples;
}
else
{
data_start = 0;
data_end = cur_sample->Data_Offset;
}
cur_sample->Data_Offset = 0;
for( j = 0; j < N_Samples; j++)
{
lv2_base_ptr->Left[i][j] = 0.0f;
lv2_base_ptr->Right[i][j] = 0.0f;
}
if( cur_sample->SF_Info_Ptr->channels == 1)
{ // play mono sample
lim = ( N_Samples < ( cur_sample->Limit - cur_sample->Offset) ? N_Samples : ( cur_sample->Limit - cur_sample->Offset));
for( pos = data_start; ( pos < lim) && ( pos < data_end); pos++)
{
lv2_base_ptr->Master_Left[pos] += cur_sample->Data_Ptr[ cur_sample->Offset] * coef_left;
lv2_base_ptr->Left[i][pos] += cur_sample->Data_Ptr[ cur_sample->Offset] * coef_left;
lv2_base_ptr->Master_Right[pos] += cur_sample->Data_Ptr[ cur_sample->Offset] * coef_right;
lv2_base_ptr->Right[i][pos] += cur_sample->Data_Ptr[ cur_sample->Offset] * coef_right;
cur_sample->Offset++;
}
}
else
{ // play stereo sample
lim = ( cur_sample->Limit - cur_sample->Offset) / cur_sample->SF_Info_Ptr->channels;
if( lim > N_Samples) lim = N_Samples;
for( pos = data_start; ( pos < lim) && ( pos < data_end); pos++)
{
lv2_base_ptr->Master_Left[pos] += cur_sample->Data_Ptr[ cur_sample->Offset] * coef_left;
lv2_base_ptr->Left[i][pos] += cur_sample->Data_Ptr[ cur_sample->Offset++] * coef_left;
lv2_base_ptr->Master_Right[pos] += cur_sample->Data_Ptr[ cur_sample->Offset] * coef_right;
lv2_base_ptr->Right[i][pos] += cur_sample->Data_Ptr[ cur_sample->Offset++] * coef_right;
}
}
if( cur_sample->Offset >= cur_sample->Limit) cur_sample->Active = 0;
}
}
pthread_mutex_unlock( &( lv2_base_ptr->Load_Mutex));
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void DR_LV2_DeActivate( LV2_Handle instance)
{
DR_LOG_INFO_0( "LV2 DeActivate!");
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static void DR_LV2_Cleanup( LV2_Handle Instance_Ptr)
{
DRT_Status status;
DRT_LV2_Base *lv2_base_ptr = (DRT_LV2_Base *)Instance_Ptr;
DR_LOG_INFO_0( "LV2 Cleanup!");
DR_Tasks_Dump();
DR_Kits_Stats_Dump();
if( ( status = DR_DataStruct_DeInit()) != DRS_OK)
{
printf( "Can't deinit data structures (%d)!\n", status);
}
free( lv2_base_ptr->Gains);
free( lv2_base_ptr->Right);
free( lv2_base_ptr->Left);
free( lv2_base_ptr->Request_Buf);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static LV2_State_Status DR_LV2_Save_State( LV2_Handle instance,
LV2_State_Store_Function store,
void *handle,
uint32_t flags,
const LV2_Feature *const *features)
{
LV2_State_Status lv2_status = LV2_STATE_SUCCESS;
DR_LOG_INFO_0( "LV2 Save State!");
return( lv2_status);
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
static LV2_State_Status DR_LV2_Restore_State( LV2_Handle instance,
LV2_State_Retrieve_Function retrieve,
void *handle,
uint32_t flags,
const LV2_Feature *const *features)
{
LV2_State_Status lv2_status = LV2_STATE_SUCCESS;
DR_LOG_INFO_0( "LV2 Restore State!");
return( lv2_status);
}
/*----------------------------------------------------------------------------*/
/* LV2_State_Interface */
/*----------------------------------------------------------------------------*/
static const LV2_State_Interface DRG_LV2_State_Interface =
{
DR_LV2_Save_State,
DR_LV2_Restore_State
};
/*----------------------------------------------------------------------------*/
/* LV2_Extension_Data */
/*----------------------------------------------------------------------------*/
static const void *DR_LV2_Extension_Data( const char *uri)
{
if( !strcmp( uri, LV2_STATE__interface))
{
return &DRG_LV2_State_Interface;
}
return NULL;
}
/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
LV2_SYMBOL_EXPORT const LV2_Descriptor *lv2_descriptor( uint32_t Index)
{
switch( Index)
{
case 0:
{
return &DRG_LV2_Descriptor;
}
default:
{
return NULL;
}
}
}