コード例 #1
0
ファイル: midimap.c プロジェクト: x42/midimap.lv2
/** non-realtime function to read config,
 * called from state-restore or worker-thread
 */
static void
parse_config_file (MidiMap* self, const char* fn)
{
	assert (self->state == NULL);
	FILE *f;
	if (!fn) {
		lv2_log_error (&self->logger, "MidiMap.lv2: invalid config file handle\n");
	}
	if (!(f = fopen (fn, "r"))) {
		lv2_log_error (&self->logger, "MidiMap.lv2: cannot open config file '%s'\n", fn);
		return;
	}
	lv2_log_note (&self->logger, "MidiMap.lv2: parsing config file '%s'\n", fn);

	self->state = calloc (1, sizeof (RuleSet));

	char line[MAX_CFG_LINE_LEN];
	unsigned int lineno = 0;
	unsigned int cfg_version = 0;
	while (fgets (line, MAX_CFG_LINE_LEN - 1, f) != NULL ) {
		++lineno;
		if (strlen (line) == MAX_CFG_LINE_LEN - 1) {
			lv2_log_error (&self->logger, "MidiMap.lv2: Too long config line %d\n", lineno);
			continue;
		}
		// strip trailing whitespace
		while (strlen (line) > 0 && (line[strlen (line) - 1] == '\n' || line[strlen (line) - 1] == '\r' || line[strlen (line) - 1] == ' ' || line[strlen (line) - 1] == '\t')) {
			line[strlen (line) - 1] = '\0';
		}
		// ignore comments and empty lines
		if (strlen (line) == 0 || line[0] == '#') {
			continue;
		}

		parse_config_line (self, line, &cfg_version, lineno);
	}

	fclose (f);
	if (cfg_version > 0) {
		/* remember config file - for state */
		free (self->cfg_file_path);
		self->cfg_file_path = strdup (fn);
#ifndef NDEBUG
		char* dump = serialize_ruleset (self->state);
		printf ("----\n%s\n----\n", dump);
		free (dump);
#endif
	} else {
		lv2_log_error (&self->logger, "MidiMap.lv2: error parsing config file\n");
		free (self->state);
		self->state = NULL;
	}
}
コード例 #2
0
ファイル: examploscope.c プロジェクト: drobilla/lv2
/** ==== Instantiate Method ==== */
static LV2_Handle
instantiate(const LV2_Descriptor*     descriptor,
            double                    rate,
            const char*               bundle_path,
            const LV2_Feature* const* features)
{
	(void)descriptor;   // Unused variable
	(void)bundle_path;  // Unused variable

	// Allocate and initialise instance structure.
	EgScope* self = (EgScope*)calloc(1, sizeof(EgScope));
	if (!self) {
		return NULL;
	}

	// Get host features
	const char* missing = lv2_features_query(
		features,
		LV2_LOG__log,  &self->logger.log, false,
		LV2_URID__map, &self->map,        true,
		NULL);
	lv2_log_logger_set_map(&self->logger, self->map);
	if (missing) {
		lv2_log_error(&self->logger, "Missing feature <%s>\n", missing);
		free(self);
		return NULL;
	}

	// Decide which variant to use depending on the plugin URI
	if (!strcmp(descriptor->URI, SCO_URI "#Stereo")) {
		self->n_channels = 2;
	} else if (!strcmp(descriptor->URI, SCO_URI "#Mono")) {
		self->n_channels = 1;
	} else {
		free(self);
		return NULL;
	}

	// Initialise local variables
	self->ui_active           = false;
	self->send_settings_to_ui = false;
	self->rate                = rate;

	// Set default UI settings
	self->ui_spp = 50;
	self->ui_amp = 1.0;

	// Map URIs and initialise forge/logger
	map_sco_uris(self->map, &self->uris);
	lv2_atom_forge_init(&self->forge, self->map);

	return (LV2_Handle)self;
}
コード例 #3
0
ファイル: midimap.c プロジェクト: x42/midimap.lv2
static void
parse_config_line (MidiMap*      self,
                   const char*   line,
                   unsigned int* cfg_version,
                   unsigned int  lineno)
{
	if (0 == strncmp (line, "midimap v", 9) && strlen (line) > 9) {
		*cfg_version = atoi (&line[9]);
		return;
	}

	switch (*cfg_version) {
		case 1:
			if (!parse_line_v1 (self->state, line)) {
				lv2_log_error (&self->logger, "MidiMap.lv2: Parser error on line %d\n", lineno);
			}
			break;
		default:
			lv2_log_error (&self->logger, "MidiMap.lv2: invalid version '%d' on config line %d\n",
					*cfg_version, lineno);
			break;
	}
}
コード例 #4
0
ファイル: midimap.c プロジェクト: x42/midimap.lv2
static LV2_Handle
instantiate (const LV2_Descriptor*     descriptor,
             double                    rate,
             const char*               bundle_path,
             const LV2_Feature* const* features)
{
	MidiMap* self = (MidiMap*)calloc (1, sizeof (MidiMap));

	int i;
	for (i=0; features[i]; ++i) {
		if (!strcmp (features[i]->URI, LV2_URID__map)) {
			self->map = (LV2_URID_Map*)features[i]->data;
		} else if (!strcmp (features[i]->URI, LV2_WORKER__schedule)) {
			self->schedule = (LV2_Worker_Schedule*)features[i]->data;
		} else if (!strcmp (features[i]->URI, LV2_LOG__log)) {
			self->log = (LV2_Log_Log*)features[i]->data;
		}
	}

	lv2_log_logger_init (&self->logger, self->map, self->log);

	if (!self->map) {
		lv2_log_error (&self->logger, "MidiMap.lv2 error: Host does not support urid:map\n");
		free (self);
		return NULL;
	}
	if (!self->schedule) {
		lv2_log_error (&self->logger, "MidiMap.lv2 error: Host does not support worker:schedule\n");
		free (self);
		return NULL;
	}

	self->sample_rate = rate;
	lv2_atom_forge_init (&self->forge, self->map);
	map_mem_uris (self->map, &self->uris);
	return (LV2_Handle)self;
}
コード例 #5
0
ファイル: examploscope.c プロジェクト: AkiraShirase/audacity
/** ==== Run Method ==== */
static void
run(LV2_Handle handle, uint32_t n_samples)
{
	EgScope* self = (EgScope*)handle;

	/* Ensure notify port buffer is large enough to hold all audio-samples and
	   configuration settings.  A minimum size was requested in the .ttl file,
	   but check here just to be sure.

	   TODO: Explain these magic numbers.
	*/
	const size_t   size  = (sizeof(float) * n_samples + 64) * self->n_channels;
	const uint32_t space = self->notify->atom.size;
	if (space < size + 128) {
		/* Insufficient space, report error and do nothing.  Note that a
		   real-time production plugin mustn't call log functions in run(), but
		   this can be useful for debugging and example purposes.
		*/
		lv2_log_error(&self->logger, "Buffer size is insufficient\n");
		return;
	}

	// Prepare forge buffer and initialize atom-sequence
	lv2_atom_forge_set_buffer(&self->forge, (uint8_t*)self->notify, space);
	lv2_atom_forge_sequence_head(&self->forge, &self->frame, 0);

	/* Send settings to UI

	   The plugin can continue to run while the UI is closed and re-opened.
	   The state and settings of the UI are kept here and transmitted to the UI
	   every time it asks for them or if the user initializes a 'load preset'.
	*/
	if (self->send_settings_to_ui && self->ui_active) {
		self->send_settings_to_ui = false;
		// Forge container object of type 'ui_state'
		LV2_Atom_Forge_Frame frame;
		lv2_atom_forge_frame_time(&self->forge, 0);
		lv2_atom_forge_object(&self->forge, &frame, 0, self->uris.ui_State);

		// Add UI state as properties
		lv2_atom_forge_key(&self->forge, self->uris.ui_spp);
		lv2_atom_forge_int(&self->forge, self->ui_spp);
		lv2_atom_forge_key(&self->forge, self->uris.ui_amp);
		lv2_atom_forge_float(&self->forge, self->ui_amp);
		lv2_atom_forge_key(&self->forge, self->uris.param_sampleRate);
		lv2_atom_forge_float(&self->forge, self->rate);
		lv2_atom_forge_pop(&self->forge, &frame);
	}

	// Process incoming events from GUI
	if (self->control) {
		const LV2_Atom_Event* ev = lv2_atom_sequence_begin(
			&(self->control)->body);
		// For each incoming message...
		while (!lv2_atom_sequence_is_end(
			       &self->control->body, self->control->atom.size, ev)) {
			// If the event is an atom:Blank object
			if (ev->body.type == self->uris.atom_Blank) {
				const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body;
				if (obj->body.otype == self->uris.ui_On) {
					// If the object is a ui-on, the UI was activated
					self->ui_active           = true;
					self->send_settings_to_ui = true;
				} else if (obj->body.otype == self->uris.ui_Off) {
					// If the object is a ui-off, the UI was closed
					self->ui_active = false;
				} else if (obj->body.otype == self->uris.ui_State) {
					// If the object is a ui-state, it's the current UI settings
					const LV2_Atom* spp = NULL;
					const LV2_Atom* amp = NULL;
					lv2_atom_object_get(obj, self->uris.ui_spp, &spp,
					                    self->uris.ui_amp, &amp,
					                    0);
					if (spp) {
						self->ui_spp = ((const LV2_Atom_Int*)spp)->body;
					}
					if (amp) {
						self->ui_amp = ((const LV2_Atom_Float*)amp)->body;
					}
				}
			}
			ev = lv2_atom_sequence_next(ev);
		}
	}

	// Process audio data
	for (uint32_t c = 0; c < self->n_channels; ++c) {
		if (self->ui_active) {
			// If UI is active, send raw audio data to UI
			tx_rawaudio(&self->forge, &self->uris, c, n_samples, self->input[c]);
		}
		// If not processing audio in-place, forward audio
		if (self->input[c] != self->output[c]) {
			memcpy(self->output[c], self->input[c], sizeof(float) * n_samples);
		}
	}

	// Close off sequence
	lv2_atom_forge_pop(&self->forge, &self->frame);
}