Mercurial > audlegacy
diff Plugins/Input/amidi-plug/backend-dummy/b-dummy.c @ 1387:b0590e16329f trunk
[svn] import amidi-plug 0.5
author | giacomo |
---|---|
date | Mon, 10 Jul 2006 04:52:51 -0700 |
parents | |
children | f12d7e208b43 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-dummy/b-dummy.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,392 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program 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 +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include "b-dummy.h" +#include "b-dummy-config.h" + +/* dummy sequencer instance */ +static sequencer_client_t sc; +/* options */ +static amidiplug_cfg_dumm_t amidiplug_cfg_dumm; + + +gint backend_info_get( gchar ** name , gchar ** longname , gchar ** desc , gint * ppos ) +{ + if ( name != NULL ) + *name = g_strdup( "dummy" ); + if ( longname != NULL ) + *longname = g_strdup( "Dummy Backend " AMIDIPLUG_VERSION ); + if ( desc != NULL ) + *desc = g_strdup( _("This backend does not produce audio at all. It is mostly " + "useful for analysis and testing purposes, as it can log " + "all MIDI events to standard output, standard error or file.\n" + "Backend written by Giacomo Lozito.") ); + if ( ppos != NULL ) + *ppos = 3; /* preferred position in backend list */ + return 1; +} + + +gint backend_init( void ) +{ + i_cfg_read(); /* read configuration options */ + + return 1; +} + + +gint backend_cleanup( void ) +{ + i_cfg_free(); /* free configuration options */ + + return 1; +} + + +gint sequencer_get_port_count( void ) +{ + return 1; /* always return a single port here */ +} + + +gint sequencer_start( gchar * midi_fname ) +{ + switch( amidiplug_cfg_dumm.dumm_logger_enable ) + { + case 1: + { + sc.file = stdout; /* log to standard output */ + break; + } + case 2: + { + sc.file = stderr; /* log to standard error */ + break; + } + case 3: + { + switch ( amidiplug_cfg_dumm.dumm_logger_lfstyle ) + { + case 0: + { + sc.file = fopen( amidiplug_cfg_dumm.dumm_logger_logfile , "w" ); + break; + } + case 1: + { + sc.file = fopen( amidiplug_cfg_dumm.dumm_logger_logfile , "a" ); + break; + } + case 2: + { + gchar *midi_basefname = G_PATH_GET_BASENAME( midi_fname ); + gchar *logfile = g_strjoin( "" , amidiplug_cfg_dumm.dumm_logger_logdir , + "/" , midi_basefname , ".log" , NULL ); + sc.file = fopen( logfile , "w" ); + g_free( logfile ); + g_free( midi_basefname ); + break; + } + default: /* shouldn't happen, let's handle this anyway */ + { + sc.file = NULL; + break; + } + } + break; + } + case 0: + default: + { + sc.file = NULL; + break; + } + } + + if (( sc.file == NULL ) && ( amidiplug_cfg_dumm.dumm_logger_enable != 0 )) + { + DEBUGMSG( "Unable to get a FILE pointer\n" ); + return 0; + } + else + return 1; /* success */ +} + + +gint sequencer_stop( void ) +{ + if (( sc.file != NULL ) && ( amidiplug_cfg_dumm.dumm_logger_enable == 3 )) + fclose( sc.file ); + + return 1; /* success */ +} + + +/* activate sequencer client */ +gint sequencer_on( void ) +{ + sc.tick_offset = 0; + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + sc.timer_seq = g_timer_new(); /* create the sequencer timer */ + return 1; /* success */ +} + + +/* shutdown sequencer client */ +gint sequencer_off( void ) +{ + if (( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) && ( sc.timer_seq != NULL )) + { + g_timer_destroy( sc.timer_seq ); /* destroy the sequencer timer */ + sc.timer_seq = NULL; + } + return 1; /* success */ +} + + +/* queue set tempo */ +gint sequencer_queue_tempo( gint tempo , gint ppq ) +{ + sc.ppq = ppq; + sc.usec_per_tick = (gdouble)tempo / (gdouble)ppq; + return 1; +} + + +gint sequencer_queue_start( void ) +{ + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + g_timer_start( sc.timer_seq ); /* reset the sequencer timer */ + return 1; +} + + +gint sequencer_event_init( void ) +{ + /* common settings for all our events */ + return 1; +} + + +gint sequencer_event_noteon( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "NOTEON : ti %i : ch %i : no %i : ve %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_noteoff( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "NOTEOFF : ti %i : ch %i : no %i : ve %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_keypress( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "KEYPRESS : ti %i : ch %i : no %i : ve %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_controller( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "CONTROLLER : ti %i : ch %i : pa %i : va %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_pgmchange( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "PGMCHANGE : ti %i : ch %i : va %i\n" , + event->tick , event->data.d[0] , event->data.d[1] ); + return 1; +} + + +gint sequencer_event_chanpress( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "CHANPRESS : ti %i : ch %i : va %i\n" , + event->tick , event->data.d[0] , event->data.d[1] ); + return 1; +} + + +gint sequencer_event_pitchbend( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "PITCHBEND : ti %i : ch %i : va %i\n" , + event->tick , event->data.d[0] , + ((((event->data.d[2]) & 0x7f) << 7) | ((event->data.d[1]) & 0x7f)) ); + return 1; +} + + +gint sequencer_event_sysex( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "SYSEX : ti %i\n" , + event->tick ); + return 1; +} + + +gint sequencer_event_tempo( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "TEMPOCHANGE : ti %i : va %i\n" , + event->tick , event->data.tempo ); + sc.usec_per_tick = (gdouble)event->data.tempo / (gdouble)sc.ppq; + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + g_timer_start( sc.timer_seq ); /* reset the sequencer timer */ + sc.tick_offset = event->tick_real; + return 1; +} + + +gint sequencer_event_other( midievent_t * event ) +{ + return 1; +} + + +gint sequencer_output( gpointer * buffer , gint * len ) +{ + return 0; +} + + +gint sequencer_output_shut( guint max_tick , gint skip_offset ) +{ + return 1; +} + + +/* unimplemented (useless for dummy backend) */ +gint audio_volume_get( gint * left_volume , gint * right_volume ) +{ + return 0; +} +gint audio_volume_set( gint left_volume , gint right_volume ) +{ + return 0; +} + + +gint audio_info_get( gint * channels , gint * bitdepth , gint * samplerate ) +{ + /* not applicable for dummy backend */ + *channels = -1; + *bitdepth = -1; + *samplerate = -1; + return 0; /* not valid information */ +} + + +gboolean audio_check_autonomous( void ) +{ + return TRUE; /* Dummy deals itself with audio (well, it doesn't produce any at all :)) */ +} + + + +/* ****************************************************************** + *** INTERNALS **************************************************** + ****************************************************************** */ + + +void i_sleep( guint tick ) +{ + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + { + gdouble elapsed_tick_usecs = (gdouble)(tick - sc.tick_offset) * sc.usec_per_tick; + gdouble elapsed_seq_usecs = g_timer_elapsed( sc.timer_seq , NULL ) * 1000000; + if ( elapsed_seq_usecs < elapsed_tick_usecs ) + { + G_USLEEP( elapsed_tick_usecs - elapsed_seq_usecs ); + } + } +} + + +void i_printf( FILE * fp , const gchar * format , ... ) +{ + va_list args; + va_start( args , format ); + if ( fp != NULL ) + G_VFPRINTF( fp , format , args ); + va_end( args ); +} + + +void i_cfg_read( void ) +{ + pcfg_t *cfgfile; + gchar * def_logfile = g_strjoin( "" , g_get_home_dir() , "/amidi-plug.log" , NULL ); + gchar * def_logdir = (gchar*)g_get_home_dir(); + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); + + if ( !cfgfile ) + { + /* fluidsynth backend defaults */ + amidiplug_cfg_dumm.dumm_logger_enable = 0; + amidiplug_cfg_dumm.dumm_logger_lfstyle = 0; + amidiplug_cfg_dumm.dumm_playback_speed = 0; + amidiplug_cfg_dumm.dumm_logger_logfile = g_strdup( def_logfile ); + amidiplug_cfg_dumm.dumm_logger_logdir = g_strdup( def_logdir ); + } + else + { + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_enable" , + &amidiplug_cfg_dumm.dumm_logger_enable , 0 ); + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_lfstyle" , + &amidiplug_cfg_dumm.dumm_logger_lfstyle , 0 ); + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_playback_speed" , + &amidiplug_cfg_dumm.dumm_playback_speed , 0 ); + i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logfile" , + &amidiplug_cfg_dumm.dumm_logger_logfile , def_logfile ); + i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logdir" , + &amidiplug_cfg_dumm.dumm_logger_logdir , def_logdir ); + + i_pcfg_free( cfgfile ); + } + + g_free( config_pathfilename ); + g_free( def_logfile ); +} + + +void i_cfg_free( void ) +{ + g_free( amidiplug_cfg_dumm.dumm_logger_logfile ); + g_free( amidiplug_cfg_dumm.dumm_logger_logdir ); +}