<commit_before>/* FluidSynth - A Software Synthesizer
 *
 * Copyright (C) 2003  <NAME> and others.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

/* fluid_alsa.c
 *
 * Driver for the Advanced Linux Sound Architecture
 *
 */

#include "fluid_synth.h"
#include "fluid_midi.h"
#include "fluid_adriver.h"
#include "fluid_mdriver.h"
#include "fluid_settings.h"

#if ALSA_SUPPORT

#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/poll.h>
#include <glib.h>

#include "config.h"

#include "fluid_lash.h"

#define FLUID_ALSA_DEFAULT_MIDI_DEVICE  "default"
#define FLUID_ALSA_DEFAULT_SEQ_DEVICE   "default"

#define BUFFER_LENGTH 512

/** fluid_alsa_audio_driver_t
 *
 * This structure should not be accessed directly. Use audio port
 * functions instead.
 */
typedef struct {
  fluid_audio_driver_t driver;
  snd_pcm_t* pcm;
  fluid_audio_func_t callback;
  void* data;
  int buffer_size;
  fluid_thread_t *thread;
  int cont;
} fluid_alsa_audio_driver_t;


fluid_audio_driver_t* new_fluid_alsa_audio_driver(fluid_settings_t* settings,
						  fluid_synth_t* synth);
fluid_audio_driver_t* new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
						   fluid_audio_func_t func, void* data);

int delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p);
void fluid_alsa_audio_driver_settings(fluid_settings_t* settings);
static void fluid_alsa_audio_run_float(void* d);
static void fluid_alsa_audio_run_s16(void* d);


struct fluid_alsa_formats_t {
  char* name;
  snd_pcm_format_t format;
  snd_pcm_access_t access;
  fluid_thread_func_t run;
};

struct fluid_alsa_formats_t fluid_alsa_formats[] = {
  { "s16, rw, interleaved",
    SND_PCM_FORMAT_S16,
    SND_PCM_ACCESS_RW_INTERLEAVED,
    fluid_alsa_audio_run_s16 },
  { "float, rw, non interleaved",
    SND_PCM_FORMAT_FLOAT,
    SND_PCM_ACCESS_RW_NONINTERLEAVED,
    fluid_alsa_audio_run_float },
  { NULL, 0, 0, NULL }
};



/*
 * fluid_alsa_rawmidi_driver_t
 *
 */
typedef struct {
  fluid_midi_driver_t driver;
  snd_rawmidi_t *rawmidi_in;
  struct pollfd *pfd;
  int npfd;
  fluid_thread_t *thread;
  gint should_quit;
  unsigned char buffer[BUFFER_LENGTH];
  fluid_midi_parser_t* parser;
} fluid_alsa_rawmidi_driver_t;


fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
						   handle_midi_event_func_t handler,
						   void* event_handler_data);

int delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p);
static void fluid_alsa_midi_run(void* d);


/*
 * fluid_alsa_seq_driver_t
 *
 */
typedef struct {
  fluid_midi_driver_t driver;
  snd_seq_t *seq_handle;
  struct pollfd *pfd;
  int npfd;
  fluid_thread_t *thread;
  gint should_quit;
  int port_count;
} fluid_alsa_seq_driver_t;

fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings,
					     handle_midi_event_func_t handler,
					     void* data);
int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p);
static void fluid_alsa_seq_run(void* d);

/**************************************************************
 *
 *        Alsa audio driver
 *
 */

// Connect ALSA MIDI inputs to port_info
static void fluid_alsa_autoconnect_inputs(fluid_alsa_seq_driver_t* dev, const snd_seq_port_info_t *port_info)
{
  snd_seq_t *seq = dev->seq_handle;
  snd_seq_port_subscribe_t *subs;
  snd_seq_client_info_t *cinfo;
  snd_seq_port_info_t *pinfo;

  snd_seq_port_subscribe_alloca(&subs);
  snd_seq_client_info_alloca(&cinfo);
  snd_seq_port_info_alloca(&pinfo);

  snd_seq_client_info_set_client(cinfo, -1);
  while (snd_seq_query_next_client(seq, cinfo) >= 0) {
    const snd_seq_addr_t *dest = snd_seq_port_info_get_addr(port_info);

    snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
    snd_seq_port_info_set_port(pinfo, -1);
    while (snd_seq_query_next_port(seq, pinfo) >= 0) {
      unsigned int needed_type = SND_SEQ_PORT_TYPE_MIDI_GENERIC;
      unsigned int needed_cap = SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ;
      const snd_seq_addr_t *sender = snd_seq_port_info_get_addr(pinfo);
      const char *pname = snd_seq_port_info_get_name(pinfo);
      if ((snd_seq_port_info_get_type(pinfo) & needed_type) != needed_type)
	continue;
      if ((snd_seq_port_info_get_capability(pinfo) & needed_cap) != needed_cap)
	continue;

      snd_seq_port_subscribe_set_sender(subs, sender);
      snd_seq_port_subscribe_set_dest(subs, dest);

      if (snd_seq_get_port_subscription(seq, subs) == 0) {
	FLUID_LOG(FLUID_ERR, "Connection %s is already subscribed\n", pname);
	continue;
      }
      if (snd_seq_subscribe_port(seq, subs) < 0) {
	FLUID_LOG(FLUID_ERR, "Connection of %s failed (%s)\n", pname, snd_strerror(errno));
	continue;
      }
      FLUID_LOG(FLUID_ERR, "Connection of %s succeeded\n", pname);
    }
  }
}

void fluid_alsa_audio_driver_settings(fluid_settings_t* settings)
{
  fluid_settings_register_str(settings, "audio.alsa.device", "default", 0, NULL, NULL);
  fluid_settings_register_int(settings, "audio.alsa.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED, NULL, NULL);
}<commit_msg>make vars const correct<commit_after>/* FluidSynth - A Software Synthesizer
 *
 * Copyright (C) 2003  <NAME> and others.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

/* fluid_alsa.c
 *
 * Driver for the Advanced Linux Sound Architecture
 *
 */

#include "fluid_synth.h"
#include "fluid_midi.h"
#include "fluid_adriver.h"
#include "fluid_mdriver.h"
#include "fluid_settings.h"

#if ALSA_SUPPORT

#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/poll.h>
#include <glib.h>

#include "config.h"

#include "fluid_lash.h"

#define FLUID_ALSA_DEFAULT_MIDI_DEVICE  "default"
#define FLUID_ALSA_DEFAULT_SEQ_DEVICE   "default"

#define BUFFER_LENGTH 512

/** fluid_alsa_audio_driver_t
 *
 * This structure should not be accessed directly. Use audio port
 * functions instead.
 */
typedef struct {
  fluid_audio_driver_t driver;
  snd_pcm_t* pcm;
  fluid_audio_func_t callback;
  void* data;
  int buffer_size;
  fluid_thread_t *thread;
  int cont;
} fluid_alsa_audio_driver_t;


fluid_audio_driver_t* new_fluid_alsa_audio_driver(fluid_settings_t* settings,
						  fluid_synth_t* synth);
fluid_audio_driver_t* new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
						   fluid_audio_func_t func, void* data);

int delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p);
void fluid_alsa_audio_driver_settings(fluid_settings_t* settings);
static void fluid_alsa_audio_run_float(void* d);
static void fluid_alsa_audio_run_s16(void* d);


struct fluid_alsa_formats_t {
  char* name;
  snd_pcm_format_t format;
  snd_pcm_access_t access;
  fluid_thread_func_t run;
};

struct fluid_alsa_formats_t fluid_alsa_formats[] = {
  { "s16, rw, interleaved",
    SND_PCM_FORMAT_S16,
    SND_PCM_ACCESS_RW_INTERLEAVED,
    fluid_alsa_audio_run_s16 },
  { "float, rw, non interleaved",
    SND_PCM_FORMAT_FLOAT,
    SND_PCM_ACCESS_RW_NONINTERLEAVED,
    fluid_alsa_audio_run_float },
  { NULL, 0, 0, NULL }
};



/*
 * fluid_alsa_rawmidi_driver_t
 *
 */
typedef struct {
  fluid_midi_driver_t driver;
  snd_rawmidi_t *rawmidi_in;
  struct pollfd *pfd;
  int npfd;
  fluid_thread_t *thread;
  gint should_quit;
  unsigned char buffer[BUFFER_LENGTH];
  fluid_midi_parser_t* parser;
} fluid_alsa_rawmidi_driver_t;


fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
						   handle_midi_event_func_t handler,
						   void* event_handler_data);

int delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p);
static void fluid_alsa_midi_run(void* d);


/*
 * fluid_alsa_seq_driver_t
 *
 */
typedef struct {
  fluid_midi_driver_t driver;
  snd_seq_t *seq_handle;
  struct pollfd *pfd;
  int npfd;
  fluid_thread_t *thread;
  gint should_quit;
  int port_count;
} fluid_alsa_seq_driver_t;

fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings,
					     handle_midi_event_func_t handler,
					     void* data);
int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p);
static void fluid_alsa_seq_run(void* d);

/**************************************************************
 *
 *        Alsa audio driver
 *
 */

// Connect ALSA MIDI inputs to port_info
static void fluid_alsa_autoconnect_inputs(fluid_alsa_seq_driver_t* dev, const snd_seq_port_info_t *port_info)
{
  snd_seq_t *seq = dev->seq_handle;
  snd_seq_port_subscribe_t *subs;
  snd_seq_client_info_t *cinfo;
  snd_seq_port_info_t *pinfo;

  snd_seq_port_subscribe_alloca(&subs);
  snd_seq_client_info_alloca(&cinfo);
  snd_seq_port_info_alloca(&pinfo);

  snd_seq_client_info_set_client(cinfo, -1);
  while (snd_seq_query_next_client(seq, cinfo) >= 0) {
    const snd_seq_addr_t *dest = snd_seq_port_info_get_addr(port_info);

    snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
    snd_seq_port_info_set_port(pinfo, -1);
    while (snd_seq_query_next_port(seq, pinfo) >= 0) {
      const unsigned int needed_type = SND_SEQ_PORT_TYPE_MIDI_GENERIC;
      const unsigned int needed_cap = SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ;
      const snd_seq_addr_t *sender = snd_seq_port_info_get_addr(pinfo);
      const char *pname = snd_seq_port_info_get_name(pinfo);
      
      if ((snd_seq_port_info_get_type(pinfo) & needed_type) != needed_type)
	continue;
      if ((snd_seq_port_info_get_capability(pinfo) & needed_cap) != needed_cap)
	continue;

      snd_seq_port_subscribe_set_sender(subs, sender);
      snd_seq_port_subscribe_set_dest(subs, dest);

      if (snd_seq_get_port_subscription(seq, subs) == 0) {
	FLUID_LOG(FLUID_ERR, "Connection %s is already subscribed\n", pname);
	continue;
      }
      if (snd_seq_subscribe_port(seq, subs) < 0) {
	FLUID_LOG(FLUID_ERR, "Connection of %s failed (%s)\n", pname, snd_strerror(errno));
	continue;
      }
      FLUID_LOG(FLUID_ERR, "Connection of %s succeeded\n", pname);
    }
  }
}

void fluid_alsa_audio_driver_settings(fluid_settings_t* settings)
{
  fluid_settings_register_str(settings, "audio.alsa.device", "default", 0, NULL, NULL);
  fluid_settings_register_int(settings, "audio.alsa.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED, NULL, NULL);
}
{'fraction_non_alphanumeric': 0.09600965267603206, 'fraction_numerical': 0.007067137809187279, 'mean_word_length': 5.169059011164275, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3274510', 'n_tokens_mistral': 4490, 'n_tokens_neox': 4198, 'n_words': 911}