Subversion Repositories svn.mios32

Rev

Rev 2618 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1052 tk 1
// $Id: seq_file_gc.c 2628 2018-12-30 21:14:09Z tk $
2
/*
3
 * Global Config File access functions
4
 *
5
 * NOTE: before accessing the SD Card, the upper level function should
6
 * synchronize with the SD Card semaphore!
7
 *   MUTEX_SDCARD_TAKE; // to take the semaphore
8
 *   MUTEX_SDCARD_GIVE; // to release the semaphore
9
 *
10
 * ==========================================================================
11
 *
12
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
13
 *  Licensed for personal non-commercial use only.
14
 *  All other rights reserved.
15
 *
16
 * ==========================================================================
17
 */
18
 
19
/////////////////////////////////////////////////////////////////////////////
20
// Include files
21
/////////////////////////////////////////////////////////////////////////////
22
 
23
#include <mios32.h>
24
#include "tasks.h"
25
 
26
#include <string.h>
27
 
1311 tk 28
#include <osc_client.h>
2263 tk 29
#include <blm_scalar_master.h>
1311 tk 30
 
1261 tk 31
#include "file.h"
1052 tk 32
#include "seq_file.h"
33
#include "seq_file_gc.h"
34
#include "seq_file_b.h"
35
 
36
 
37
#include "seq_ui.h"
38
#include "seq_bpm.h"
39
#include "seq_song.h"
40
#include "seq_mixer.h"
41
#include "seq_midi_in.h"
1323 tk 42
#include "seq_midi_port.h"
1052 tk 43
#include "seq_midi_router.h"
1316 tk 44
#include "seq_midi_sysex.h"
1052 tk 45
#include "seq_pattern.h"
1754 tk 46
#include "seq_record.h"
1052 tk 47
#include "seq_core.h"
1083 tk 48
#include "seq_cv.h"
1316 tk 49
#include "seq_blm.h"
1864 tk 50
#include "seq_tpd.h"
2130 tk 51
#include "seq_lcd_logo.h"
1316 tk 52
 
1052 tk 53
#if !defined(MIOS32_FAMILY_EMULATION)
54
#include "uip.h"
55
#include "uip_task.h"
56
#include "osc_server.h"
57
#endif
58
 
59
 
60
/////////////////////////////////////////////////////////////////////////////
61
// for optional debugging messages via DEBUG_MSG (defined in mios32_config.h)
62
/////////////////////////////////////////////////////////////////////////////
63
 
64
// Note: verbose level 1 is default - it prints error messages!
65
#define DEBUG_VERBOSE_LEVEL 1
66
 
67
 
68
/////////////////////////////////////////////////////////////////////////////
69
// Local definitions
70
/////////////////////////////////////////////////////////////////////////////
71
 
72
// in which subdirectory of the SD card are the MBSEQ files located?
73
// use "/" for root
74
// use "/<dir>/" for a subdirectory in root
75
// use "/<dir>/<subdir>/" to reach a subdirectory in <dir>, etc..
76
 
77
#define SEQ_FILES_PATH "/"
78
//#define SEQ_FILES_PATH "/MySongs/"
79
 
80
 
81
/////////////////////////////////////////////////////////////////////////////
82
// Local types
83
/////////////////////////////////////////////////////////////////////////////
84
 
85
// file informations stored in RAM
86
typedef struct {
87
  unsigned valid: 1;   // file is accessible
88
} seq_file_gc_info_t;
89
 
90
 
91
/////////////////////////////////////////////////////////////////////////////
92
// Local prototypes
93
/////////////////////////////////////////////////////////////////////////////
94
 
95
 
96
/////////////////////////////////////////////////////////////////////////////
97
// Local variables
98
/////////////////////////////////////////////////////////////////////////////
99
 
100
static seq_file_gc_info_t seq_file_gc_info;
101
 
102
 
103
/////////////////////////////////////////////////////////////////////////////
104
// Initialisation
105
/////////////////////////////////////////////////////////////////////////////
106
s32 SEQ_FILE_GC_Init(u32 mode)
107
{
108
  // invalidate file info
109
  SEQ_FILE_GC_Unload();
110
 
111
  return 0; // no error
112
}
113
 
114
 
115
/////////////////////////////////////////////////////////////////////////////
116
// Loads global config file
117
// Called from SEQ_FILE_GCheckSDCard() when the SD card has been connected
118
// returns < 0 on errors
119
/////////////////////////////////////////////////////////////////////////////
120
s32 SEQ_FILE_GC_Load(void)
121
{
122
  s32 error;
123
  error = SEQ_FILE_GC_Read();
124
#if DEBUG_VERBOSE_LEVEL >= 2
125
  DEBUG_MSG("[SEQ_FILE_GC] Tried to open global config file, status: %d\n", error);
126
#endif
127
 
128
  return error;
129
}
130
 
131
 
132
/////////////////////////////////////////////////////////////////////////////
133
// Unloads global config file
134
// Called from SEQ_FILE_GCheckSDCard() when the SD card has been disconnected
135
// returns < 0 on errors
136
/////////////////////////////////////////////////////////////////////////////
137
s32 SEQ_FILE_GC_Unload(void)
138
{
139
  seq_file_gc_info.valid = 0;
140
 
141
  return 0; // no error
142
}
143
 
144
 
145
 
146
/////////////////////////////////////////////////////////////////////////////
147
// Returns 1 if global config file valid
148
// Returns 0 if global config file not valid
149
/////////////////////////////////////////////////////////////////////////////
150
s32 SEQ_FILE_GC_Valid(void)
151
{
152
  return seq_file_gc_info.valid;
153
}
154
 
155
 
156
/////////////////////////////////////////////////////////////////////////////
157
// help function which parses a decimal or hex value
158
// returns >= 0 if value is valid
159
// returns -1 if value is invalid
160
/////////////////////////////////////////////////////////////////////////////
161
static s32 get_dec(char *word)
162
{
163
  if( word == NULL )
164
    return -1;
165
 
166
  char *next;
167
  long l = strtol(word, &next, 0);
168
 
169
  if( word == next )
170
    return -1;
171
 
172
  return l; // value is valid
173
}
174
 
175
/////////////////////////////////////////////////////////////////////////////
176
// help function which parses an IP value
177
// returns > 0 if value is valid
178
// returns 0 if value is invalid
179
/////////////////////////////////////////////////////////////////////////////
180
static u32 get_ip(char *brkt)
181
{
182
  u8 ip[4];
183
  char *word;
184
 
185
  int i;
186
  for(i=0; i<4; ++i) {
1117 tk 187
    if( (word=strtok_r(NULL, ".", &brkt)) ) {
1052 tk 188
      s32 value = get_dec(word);
189
      if( value >= 0 && value <= 255 )
190
    ip[i] = value;
191
      else
192
    return 0;
193
    }
194
  }
195
 
196
  if( i == 4 )
197
    return (ip[0]<<24)|(ip[1]<<16)|(ip[2]<<8)|(ip[3]<<0);
198
  else
199
    return 0; // invalid IP
200
}
201
 
202
 
203
/////////////////////////////////////////////////////////////////////////////
204
// reads the global config file content (again)
205
// returns < 0 on errors (error codes are documented in seq_file.h)
206
/////////////////////////////////////////////////////////////////////////////
207
s32 SEQ_FILE_GC_Read(void)
208
{
209
  s32 status = 0;
210
  seq_file_gc_info_t *info = &seq_file_gc_info;
1261 tk 211
  file_t file;
1052 tk 212
 
213
  info->valid = 0; // will be set to valid if file content has been read successfully
214
 
215
  char filepath[MAX_PATH];
216
  sprintf(filepath, "%sMBSEQ_GC.V4", SEQ_FILES_PATH);
217
 
218
#if DEBUG_VERBOSE_LEVEL >= 2
219
  DEBUG_MSG("[SEQ_FILE_GC] Open global config file '%s'\n", filepath);
220
#endif
221
 
1261 tk 222
  if( (status=FILE_ReadOpen(&file, filepath)) < 0 ) {
1052 tk 223
#if DEBUG_VERBOSE_LEVEL >= 2
224
    DEBUG_MSG("[SEQ_FILE_GC] failed to open file, status: %d\n", status);
225
#endif
226
    return status;
227
  }
228
 
229
  // read global config values
230
  char line_buffer[128];
231
  do {
1261 tk 232
    status=FILE_ReadLine((u8 *)line_buffer, 128);
1052 tk 233
 
234
    if( status > 1 ) {
235
#if DEBUG_VERBOSE_LEVEL >= 3
236
      DEBUG_MSG("[SEQ_FILE_GC] read: %s", line_buffer);
237
#endif
238
 
239
      // sscanf consumes too much memory, therefore we parse directly
240
      char *separators = " \t";
241
      char *brkt;
242
      char *parameter;
243
 
244
      if( (parameter = strtok_r(line_buffer, separators, &brkt)) ) {
245
 
246
    if( *parameter == '#' ) {
247
      // ignore comments
248
#if !defined(MIOS32_FAMILY_EMULATION)
249
    } else if( strcmp(parameter, "ETH_LocalIp") == 0 ) {
250
      u32 value;
251
      if( !(value=get_ip(brkt)) ) {
252
#if DEBUG_VERBOSE_LEVEL >= 1
253
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid IP format for parameter '%s'\n", parameter);
254
#endif
255
      } else {
256
        UIP_TASK_IP_AddressSet(value);
257
      }
258
    } else if( strcmp(parameter, "ETH_Netmask") == 0 ) {
259
      u32 value;
260
      if( !(value=get_ip(brkt)) ) {
261
#if DEBUG_VERBOSE_LEVEL >= 1
262
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid IP format for parameter '%s'\n", parameter);
263
#endif
264
      } else {
265
        UIP_TASK_NetmaskSet(value);
266
      }
267
    } else if( strcmp(parameter, "ETH_Gateway") == 0 ) {
268
      u32 value;
269
      if( !(value=get_ip(brkt)) ) {
270
#if DEBUG_VERBOSE_LEVEL >= 1
271
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid IP format for parameter '%s'\n", parameter);
272
#endif
273
      } else {
274
        UIP_TASK_GatewaySet(value);
275
      }
1083 tk 276
#endif /* !defined(MIOS32_FAMILY_EMULATION) */
1052 tk 277
    } else {
278
      char *word = strtok_r(NULL, separators, &brkt);
279
      s32 value = get_dec(word);
280
 
281
      if( value < 0 ) {
282
#if DEBUG_VERBOSE_LEVEL >= 1
283
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid value for parameter '%s'\n", parameter);
284
#endif
285
      } else if( strcmp(parameter, "MetronomePort") == 0 ) {
286
        seq_core_metronome_port = (mios32_midi_port_t)value;
287
      } else if( strcmp(parameter, "MetronomeChannel") == 0 ) {
288
        seq_core_metronome_chn = value;
289
      } else if( strcmp(parameter, "MetronomeNoteM") == 0 ) {
290
        seq_core_metronome_note_m = value;
291
      } else if( strcmp(parameter, "MetronomeNoteB") == 0 ) {
292
        seq_core_metronome_note_b = value;
2545 tk 293
      } else if( strcmp(parameter, "ShadowOutPort") == 0 ) {
294
        seq_core_shadow_out_port = (mios32_midi_port_t)value;
295
      } else if( strcmp(parameter, "ShadowOutChannel") == 0 ) {
296
        seq_core_shadow_out_chn = value;
2542 tk 297
      } else if( strcmp(parameter, "MidiRemoteKey") == 0 ) {
298
        seq_midi_in_remote.value = value;
299
      } else if( strcmp(parameter, "MidiRemoteCCorKey") == 0 ) {
300
        seq_midi_in_remote.cc_or_key = value;
2544 tk 301
#ifndef MBSEQV4L
2542 tk 302
      } else if( strcmp(parameter, "TrackCCMode") == 0 ) {
303
        seq_ui_track_cc.mode = value;
304
      } else if( strcmp(parameter, "TrackCCPort") == 0 ) {
305
        seq_ui_track_cc.port = (mios32_midi_port_t)value;
306
      } else if( strcmp(parameter, "TrackCCChannel") == 0 ) {
307
        seq_ui_track_cc.chn = value;
308
      } else if( strcmp(parameter, "TrackCCNumber") == 0 ) {
309
        seq_ui_track_cc.cc = value;
2544 tk 310
#endif
2542 tk 311
      } else if( strcmp(parameter, "MidiOutRSOpt") == 0 ) {
312
        mios32_midi_port_t port = (mios32_midi_port_t)value;
313
        if( value < UART0 || value > UART3 ) {
314
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid MIDI port 0x%02x (%u) for parameter '%s'\n", value, value, parameter);
315
        } else {
316
          word = strtok_r(NULL, separators, &brkt);
317
          if( (value=get_dec(word)) < 0 ) {
318
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid RS mode for parameter '%s'\n", parameter);
319
          } else {
320
        MIOS32_MIDI_RS_OptimisationSet(port, value);
321
          }
322
        }
2544 tk 323
#ifndef MBSEQV4L
2542 tk 324
      } else if( strcmp(parameter, "MenuShortcuts") == 0 ) {
325
        int i;
326
        for(i=0; i<16; ++i) {
327
          u8 valid = 1;
328
          if( i > 0 ) {
329
        word = strtok_r(NULL, separators, &brkt);
330
        if( (value=get_dec(word)) < 0 ) {
331
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid menu page number for parameter '%s'\n", parameter);
332
          valid = 0;
333
        }
334
          }
335
          if( valid && SEQ_UI_PAGES_MenuShortcutPageSet(i, (seq_ui_page_t)value) < 0 ) {
336
        DEBUG_MSG("[SEQ_FILE_GC] ERROR unsupported menu page number for parameter '%s'\n", parameter);
337
          }
338
        }
339
 
2544 tk 340
#endif
1754 tk 341
      } else if( strcmp(parameter, "RecQuantisation") == 0 ) {
2250 tk 342
        seq_record_quantize = value; // only for legacy reasons - quantisation moved to local configuration file seq_file_c.c
1075 tk 343
      } else if( strcmp(parameter, "PasteClrAll") == 0 ) {
344
        seq_core_options.PASTE_CLR_ALL = value;
2131 tk 345
#ifndef MBSEQV4L
2101 tk 346
      } else if( strcmp(parameter, "DatawheelMode") == 0 ) {
347
        seq_ui_edit_datawheel_mode = value;
2131 tk 348
#endif
2101 tk 349
      } else if( strcmp(parameter, "MixerLiveSend") == 0 ) {
350
        seq_core_options.MIXER_LIVE_SEND = value;
1794 tk 351
      } else if( strcmp(parameter, "InitCC") == 0 ) {
352
        seq_core_options.INIT_CC = value;
2294 tk 353
      } else if( strcmp(parameter, "InitWithTriggers") == 0 ) {
354
        seq_core_options.INIT_WITH_TRIGGERS = value;
1810 tk 355
      } else if( strcmp(parameter, "LiveLayerMuteSteps") == 0 ) {
356
        seq_core_options.LIVE_LAYER_MUTE_STEPS = value;
1794 tk 357
      } else if( strcmp(parameter, "PatternMixerMapCoupling") == 0 ) {
358
        seq_core_options.PATTERN_MIXER_MAP_COUPLING = value;
1323 tk 359
      } else if( strcmp(parameter, "MultiPortEnableFlags") == 0 ) {
360
        seq_midi_port_multi_enable_flags = value;
2250 tk 361
      } else if( strcmp(parameter, "UiRestoreTrackSelections") == 0 ) {
2263 tk 362
#ifndef MBSEQV4L
2250 tk 363
        seq_ui_options.RESTORE_TRACK_SELECTIONS = value;
2263 tk 364
#endif
2545 tk 365
      } else if( strcmp(parameter, "UiModifyPatternBanks") == 0 ) {
366
#ifndef MBSEQV4L
367
        seq_ui_options.MODIFY_PATTERN_BANKS = value;
368
#endif
2564 tk 369
      } else if( strcmp(parameter, "UiPrintAndModifyWithoutGates") == 0 ) {
370
#ifndef MBSEQV4L
371
        seq_ui_options.PRINT_AND_MODIFY_WITHOUT_GATES = value;
372
#endif
2567 tk 373
      } else if( strcmp(parameter, "UiPrintTransposedNotes") == 0 ) {
374
#ifndef MBSEQV4L
375
        seq_ui_options.PRINT_TRANSPOSED_NOTES = value;
376
#endif
2587 tk 377
      } else if( strcmp(parameter, "UiSelectUnmutedTrack") == 0 ) {
378
#ifndef MBSEQV4L
379
        seq_ui_options.SELECT_UNMUTED_TRACK = value;
380
#endif
2609 tk 381
      } else if( strcmp(parameter, "UiSwapGpLedColours") == 0 ) {
382
#ifndef MBSEQV4L
383
        seq_ui_options.SWAP_GP_LED_COLOURS = value;
384
#endif
385
      } else if( strcmp(parameter, "UiSwapSelectLedColours") == 0 ) {
386
#ifndef MBSEQV4L
387
        seq_ui_options.SWAP_SELECT_LED_COLOURS = value;
388
#endif
2618 tk 389
      } else if( strcmp(parameter, "UiGpLedDontXorPos") == 0 ) {
390
#ifndef MBSEQV4L
391
        seq_ui_options.GP_LED_DONT_XOR_POS = value;
392
#endif
2610 tk 393
      } else if( strcmp(parameter, "UiInvertMuteLeds") == 0 ) {
394
#ifndef MBSEQV4L
395
        seq_ui_options.INVERT_MUTE_LEDS = value;
396
#endif
2628 tk 397
      } else if( strcmp(parameter, "UiAllForStepViewOnly") == 0 ) {
398
#ifndef MBSEQV4L
399
        seq_ui_options.ALL_FOR_STEP_VIEW_ONLY = value;
400
#endif
1052 tk 401
      } else if( strcmp(parameter, "RemoteMode") == 0 ) {
1316 tk 402
        seq_midi_sysex_remote_mode = (value > 2) ? 0 : value;
1052 tk 403
      } else if( strcmp(parameter, "RemotePort") == 0 ) {
1316 tk 404
        seq_midi_sysex_remote_port = value;
1052 tk 405
      } else if( strcmp(parameter, "RemoteID") == 0 ) {
1316 tk 406
        seq_midi_sysex_remote_id = (value > 128) ? 0 : value;
2131 tk 407
#ifndef MBSEQV4L
2130 tk 408
      } else if( strcmp(parameter, "ScreenSaverDelay") == 0 ) {
409
        seq_lcd_logo_screensaver_delay = (value > 255) ? 255 : value;
2131 tk 410
#endif
1083 tk 411
      } else if( strcmp(parameter, "CV_AOUT_Type") == 0 ) {
412
        SEQ_CV_IfSet(value);
413
      } else if( strcmp(parameter, "CV_PinMode") == 0 ) {
414
        u32 cv = value;
415
        if( cv >= SEQ_CV_NUM ) {
2542 tk 416
          DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong CV channel %u for parameter '%s'\n", value, parameter);
1083 tk 417
        } else {
418
          word = strtok_r(NULL, separators, &brkt);
419
          u32 curve = get_dec(word);
420
          if( curve >= SEQ_CV_NUM_CURVES ) {
2542 tk 421
        DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong curve %u for parameter '%s', CV channel %u\n", curve, parameter, cv);
1083 tk 422
          } else {
423
        word = strtok_r(NULL, separators, &brkt);
424
        u32 slewrate = get_dec(word);
425
        if( slewrate >= 256 ) // saturate
426
          slewrate = 255;
1052 tk 427
 
1083 tk 428
        word = strtok_r(NULL, separators, &brkt);
429
        u32 range = get_dec(word);
430
        if( range >= 127 ) // saturate
431
          range = 2; // default value
432
 
433
        SEQ_CV_CurveSet(cv, curve);
434
        SEQ_CV_SlewRateSet(cv, slewrate);
435
        SEQ_CV_PitchRangeSet(cv, range);
436
          }
437
        }
2579 tk 438
#if AOUT_NUM_CALI_POINTS_X > 0
439
      } else if( strcmp(parameter, "CV_Cali") == 0 ) {
440
        u32 cv = value;
441
        if( cv >= SEQ_CV_NUM ) {
442
          DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong CV channel %u for parameter '%s'\n", value, parameter);
443
        } else {
444
          int i;
445
          u16 *cali_point = SEQ_CV_CaliPointsPtrGet(cv);
446
          for(i=0; i<AOUT_NUM_CALI_POINTS_X; ++i, ++cali_point) {
447
        word = strtok_r(NULL, separators, &brkt);
448
        u16 cali_value = 0;
449
        if( word == NULL || (cali_value=get_dec(word)) < 0 ) {
450
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid or missing calibration value(s) for CV channel %u for parameter '%s'\n", value, parameter);
451
          break;
452
        }
453
        *cali_point = cali_value;
454
          }
455
        }
456
#endif
1083 tk 457
      } else if( strcmp(parameter, "CV_GateInv") == 0 ) {
458
        SEQ_CV_GateInversionAllSet(value);
2385 tk 459
      } else if( strcmp(parameter, "CV_SusKey") == 0 ) {
460
        SEQ_CV_SusKeyAllSet(value);
1083 tk 461
      } else if( strcmp(parameter, "CV_ClkPulsewidth") == 0 ) {
2098 tk 462
        SEQ_CV_ClkPulseWidthSet(0, value); // Legacy Value - replaced by CV_ExtClk
1083 tk 463
      } else if( strcmp(parameter, "CV_ClkDivider") == 0 ) {
2098 tk 464
        SEQ_CV_ClkDividerSet(0, value); // Legacy Value - replaced by CV_ExtClk
465
      } else if( strcmp(parameter, "CV_ExtClk") == 0 ) {
466
        u32 clkout = value;
467
        if( clkout >= SEQ_CV_NUM_CLKOUT ) {
2542 tk 468
          DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong clock output %u for parameter '%s'\n", value, parameter);
2098 tk 469
        } else {
470
          word = strtok_r(NULL, separators, &brkt);
471
          u32 divider = get_dec(word);
472
          if( divider >= 65536 ) {
2542 tk 473
        DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong divider value %u for parameter '%s', clock output %u\n", divider, parameter, clkout);
2098 tk 474
          } else {
475
        word = strtok_r(NULL, separators, &brkt);
476
        u32 pulsewidth = get_dec(word);
477
        if( pulsewidth >= 256 ) // saturate
478
          pulsewidth = 255;
479
 
480
        SEQ_CV_ClkDividerSet(clkout, divider);
481
        SEQ_CV_ClkPulseWidthSet(clkout, pulsewidth);
482
          }
483
        }
1864 tk 484
      } else if( strcmp(parameter, "TpdMode") == 0 ) {
485
        SEQ_TPD_ModeSet(value);
1052 tk 486
      } else if( strcmp(parameter, "BLM_SCALAR_Port") == 0 ) {
2263 tk 487
        BLM_SCALAR_MASTER_MIDI_PortSet(0, value);
1052 tk 488
 
2263 tk 489
        BLM_SCALAR_MASTER_TimeoutCtrSet(0, 0); // fake timeout (so that "BLM not found" message will be displayed)
490
        BLM_SCALAR_MASTER_SendRequest(0, 0x00); // request layout from BLM_SCALAR
1052 tk 491
 
492
#if !defined(MIOS32_FAMILY_EMULATION)
2020 tk 493
      } else if( strcmp(parameter, "BLM_SCALAR_AlwaysUseFts") == 0 ) {
494
        seq_blm_options.ALWAYS_USE_FTS = value;
1052 tk 495
      } else if( strcmp(parameter, "ETH_Dhcp") == 0 ) {
496
        UIP_TASK_DHCP_EnableSet((value >= 1) ? 1 : 0);
1058 tk 497
      } else if( strcmp(parameter, "OSC_RemoteIp") == 0 ) {
498
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
499
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
500
        } else {
501
          u8 con = value;
502
          u32 ip;
503
          if( !(ip=get_ip(brkt)) ) {
504
#if DEBUG_VERBOSE_LEVEL >= 1
505
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid IP format for parameter '%s'\n", parameter);
506
#endif
507
          } else {
508
        OSC_SERVER_RemoteIP_Set(con, ip);
509
          }
510
        }
1052 tk 511
      } else if( strcmp(parameter, "OSC_RemotePort") == 0 ) {
1058 tk 512
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
513
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
514
        } else {
515
          u8 con = value;
516
          word = strtok_r(NULL, separators, &brkt);
517
          if( (value=get_dec(word)) < 0 ) {
518
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid port number for parameter '%s'\n", parameter);
519
          } else {
520
        OSC_SERVER_RemotePortSet(con, value);
521
          }
522
        }
1052 tk 523
      } else if( strcmp(parameter, "OSC_LocalPort") == 0 ) {
1058 tk 524
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
525
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
526
        } else {
527
          u8 con = value;
528
          word = strtok_r(NULL, separators, &brkt);
529
          if( (value=get_dec(word)) < 0 ) {
530
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid port number for parameter '%s'\n", parameter);
531
          } else {
532
        OSC_SERVER_LocalPortSet(con, value);
533
          }
534
        }
535
      } else if( strcmp(parameter, "OSC_TransferMode") == 0 ) {
536
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
537
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
538
        } else {
539
          u8 con = value;
540
          word = strtok_r(NULL, separators, &brkt);
541
          if( (value=get_dec(word)) < 0 ) {
542
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid transfer mode number for parameter '%s'\n", parameter);
543
          } else {
1311 tk 544
        OSC_CLIENT_TransferModeSet(con, value);
1058 tk 545
          }
546
        }
1052 tk 547
#endif
548
      } else {
549
#if DEBUG_VERBOSE_LEVEL >= 2
550
        // changed error level from 1 to 2 here, since people are sometimes confused about these messages
551
        // on file format changes
552
        DEBUG_MSG("[SEQ_FILE_GC] ERROR: unknown parameter: %s", line_buffer);
553
#endif
554
      }
555
    }
556
      } else {
557
#if DEBUG_VERBOSE_LEVEL >= 1
558
    DEBUG_MSG("[SEQ_FILE_GC] ERROR no space separator in following line: %s", line_buffer);
559
#endif
560
      }
561
    }
562
 
563
  } while( status >= 1 );
564
 
565
  // close file
1261 tk 566
  status |= FILE_ReadClose(&file);
1052 tk 567
 
1058 tk 568
#if !defined(MIOS32_FAMILY_EMULATION)
569
  // OSC_SERVER_Init(0) has to be called after all settings have been done!
570
  OSC_SERVER_Init(0);
571
#endif
572
 
1052 tk 573
  if( status < 0 ) {
574
#if DEBUG_VERBOSE_LEVEL >= 1
575
    DEBUG_MSG("[SEQ_FILE_GC] ERROR while reading file, status: %d\n", status);
576
#endif
577
    return SEQ_FILE_GC_ERR_READ;
578
  }
579
 
580
  // file is valid! :)
581
  info->valid = 1;
582
 
583
  // change tempo to given preset
584
  SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]);
585
 
586
  return 0; // no error
587
}
588
 
589
 
590
/////////////////////////////////////////////////////////////////////////////
591
// help function to write data into file or send to debug terminal
592
// returns < 0 on errors (error codes are documented in seq_file.h)
593
/////////////////////////////////////////////////////////////////////////////
594
static s32 SEQ_FILE_GC_Write_Hlp(u8 write_to_file)
595
{
596
  s32 status = 0;
597
  char line_buffer[128];
598
 
1261 tk 599
#define FLUSH_BUFFER if( !write_to_file ) { DEBUG_MSG(line_buffer); } else { status |= FILE_WriteBuffer((u8 *)line_buffer, strlen(line_buffer)); }
1052 tk 600
 
601
  // write global config values
2542 tk 602
  sprintf(line_buffer, "MetronomePort 0x%02x\n", (u8)seq_core_metronome_port);
1052 tk 603
  FLUSH_BUFFER;
604
 
605
  sprintf(line_buffer, "MetronomeChannel %d\n", (u8)seq_core_metronome_chn);
606
  FLUSH_BUFFER;
607
 
608
  sprintf(line_buffer, "MetronomeNoteM %d\n", (u8)seq_core_metronome_note_m);
609
  FLUSH_BUFFER;
610
 
611
  sprintf(line_buffer, "MetronomeNoteB %d\n", (u8)seq_core_metronome_note_b);
612
  FLUSH_BUFFER;
613
 
2545 tk 614
  sprintf(line_buffer, "ShadowOutPort 0x%02x\n", (u8)seq_core_shadow_out_port);
615
  FLUSH_BUFFER;
616
 
617
  sprintf(line_buffer, "ShadowOutChannel %d\n", (u8)seq_core_shadow_out_chn);
618
  FLUSH_BUFFER;
619
 
2542 tk 620
  sprintf(line_buffer, "MidiRemoteKey %d\n", (u8)seq_midi_in_remote.value);
621
  FLUSH_BUFFER;
622
 
623
  sprintf(line_buffer, "MidiRemoteCCorKey %d\n", (u8)seq_midi_in_remote.cc_or_key);
624
  FLUSH_BUFFER;
625
 
2544 tk 626
#ifndef MBSEQV4L
2542 tk 627
  sprintf(line_buffer, "TrackCCMode %d\n", (u8)seq_ui_track_cc.mode);
628
  FLUSH_BUFFER;
629
 
630
  sprintf(line_buffer, "TrackCCPort 0x%02x\n", (u8)seq_ui_track_cc.port);
631
  FLUSH_BUFFER;
632
 
633
  sprintf(line_buffer, "TrackCCChannel %d\n", (u8)seq_ui_track_cc.chn);
634
  FLUSH_BUFFER;
635
 
636
  sprintf(line_buffer, "TrackCCNumber %d\n", (u8)seq_ui_track_cc.cc);
637
  FLUSH_BUFFER;
2544 tk 638
#endif
2542 tk 639
 
640
  {
641
    mios32_midi_port_t port;
642
    for(port=UART0; port<=UART3; ++port) {
643
      s32 enabled = MIOS32_MIDI_RS_OptimisationGet(port);
644
      if( enabled >= 0 ) {
645
    sprintf(line_buffer, "MidiOutRSOpt 0x%02x %d\n", (u8)port, enabled);
646
    FLUSH_BUFFER;
647
      }
648
    }
649
  }
650
 
2544 tk 651
#ifndef MBSEQV4L
2542 tk 652
  sprintf(line_buffer, "MenuShortcuts %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
653
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(0),
654
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(1),
655
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(2),
656
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(3),
657
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(4),
658
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(5),
659
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(6),
660
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(7),
661
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(8),
662
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(9),
663
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(10),
664
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(11),
665
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(12),
666
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(13),
667
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(14),
668
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(15)
669
      );
670
  FLUSH_BUFFER;    
2544 tk 671
#endif
2542 tk 672
 
1075 tk 673
  sprintf(line_buffer, "PasteClrAll %d\n", seq_core_options.PASTE_CLR_ALL);
674
  FLUSH_BUFFER;
675
 
2131 tk 676
#ifndef MBSEQV4L
2101 tk 677
  sprintf(line_buffer, "DatawheelMode %d\n", seq_ui_edit_datawheel_mode);
678
  FLUSH_BUFFER;
2131 tk 679
#endif
2101 tk 680
 
681
  sprintf(line_buffer, "MixerLiveSend %d\n", seq_core_options.MIXER_LIVE_SEND);
682
  FLUSH_BUFFER;
683
 
1794 tk 684
  sprintf(line_buffer, "InitCC %d\n", seq_core_options.INIT_CC);
685
  FLUSH_BUFFER;
686
 
2294 tk 687
  sprintf(line_buffer, "InitWithTriggers %d\n", seq_core_options.INIT_WITH_TRIGGERS);
688
  FLUSH_BUFFER;
689
 
1810 tk 690
  sprintf(line_buffer, "LiveLayerMuteSteps %d\n", seq_core_options.LIVE_LAYER_MUTE_STEPS);
691
  FLUSH_BUFFER;
692
 
1794 tk 693
  sprintf(line_buffer, "PatternMixerMapCoupling %d\n", seq_core_options.PATTERN_MIXER_MAP_COUPLING);
694
  FLUSH_BUFFER;
695
 
1323 tk 696
  sprintf(line_buffer, "MultiPortEnableFlags 0x%06x\n", seq_midi_port_multi_enable_flags);
697
  FLUSH_BUFFER;
698
 
2263 tk 699
#ifndef MBSEQV4L
2250 tk 700
  sprintf(line_buffer, "UiRestoreTrackSelections %d\n", seq_ui_options.RESTORE_TRACK_SELECTIONS);
701
  FLUSH_BUFFER;
2263 tk 702
#endif
2250 tk 703
 
2545 tk 704
#ifndef MBSEQV4L
705
  sprintf(line_buffer, "UiModifyPatternBanks %d\n", seq_ui_options.MODIFY_PATTERN_BANKS);
706
  FLUSH_BUFFER;
707
#endif
708
 
2564 tk 709
#ifndef MBSEQV4L
710
  sprintf(line_buffer, "UiPrintAndModifyWithoutGates %d\n", seq_ui_options.PRINT_AND_MODIFY_WITHOUT_GATES);
711
  FLUSH_BUFFER;
712
#endif
713
 
2567 tk 714
#ifndef MBSEQV4L
715
  sprintf(line_buffer, "UiPrintTransposedNotes %d\n", seq_ui_options.PRINT_TRANSPOSED_NOTES);
716
  FLUSH_BUFFER;
717
#endif
718
 
2587 tk 719
#ifndef MBSEQV4L
720
  sprintf(line_buffer, "UiSelectUnmutedTrack %d\n", seq_ui_options.SELECT_UNMUTED_TRACK);
721
  FLUSH_BUFFER;
722
#endif
723
 
2609 tk 724
#ifndef MBSEQV4L
725
  sprintf(line_buffer, "UiSwapGpLedColours %d\n", seq_ui_options.SWAP_GP_LED_COLOURS);
726
  FLUSH_BUFFER;
727
#endif
728
 
729
#ifndef MBSEQV4L
730
  sprintf(line_buffer, "UiSwapSelectLedColours %d\n", seq_ui_options.SWAP_SELECT_LED_COLOURS);
731
  FLUSH_BUFFER;
732
#endif
733
 
2610 tk 734
#ifndef MBSEQV4L
2618 tk 735
  sprintf(line_buffer, "UiGpLedDontXorPos %d\n", seq_ui_options.GP_LED_DONT_XOR_POS);
736
  FLUSH_BUFFER;
737
#endif
738
 
739
#ifndef MBSEQV4L
2610 tk 740
  sprintf(line_buffer, "UiInvertMuteLeds %d\n", seq_ui_options.INVERT_MUTE_LEDS);
741
  FLUSH_BUFFER;
742
#endif
743
 
2628 tk 744
#ifndef MBSEQV4L
745
  sprintf(line_buffer, "UiAllForStepViewOnly %d\n", seq_ui_options.ALL_FOR_STEP_VIEW_ONLY);
746
  FLUSH_BUFFER;
747
#endif
748
 
1316 tk 749
  sprintf(line_buffer, "RemoteMode %d\n", (u8)seq_midi_sysex_remote_mode);
1052 tk 750
  FLUSH_BUFFER;
751
 
2542 tk 752
  sprintf(line_buffer, "RemotePort 0x%02x\n", (u8)seq_midi_sysex_remote_port);
1052 tk 753
  FLUSH_BUFFER;
754
 
1316 tk 755
  sprintf(line_buffer, "RemoteID %d\n", (u8)seq_midi_sysex_remote_id);
1052 tk 756
  FLUSH_BUFFER;
757
 
1083 tk 758
  sprintf(line_buffer, "CV_AOUT_Type %d\n", (u8)SEQ_CV_IfGet());
759
  FLUSH_BUFFER;
760
 
2098 tk 761
  {
762
    int cv;
763
    for(cv=0; cv<SEQ_CV_NUM; ++cv) {
764
      sprintf(line_buffer, "CV_PinMode %d %d %d %d\n", cv, SEQ_CV_CurveGet(cv), (int)SEQ_CV_SlewRateGet(cv), (int)SEQ_CV_PitchRangeGet(cv));
765
      FLUSH_BUFFER;
2579 tk 766
 
767
#if AOUT_NUM_CALI_POINTS_X > 0
768
      sprintf(line_buffer, "CV_Cali %d", cv);
769
      {
770
    int i;
771
    u16 *cali_point = SEQ_CV_CaliPointsPtrGet(cv);
772
    for(i=0; i<AOUT_NUM_CALI_POINTS_X; ++i, ++cali_point) {
773
      sprintf(line_buffer + strlen(line_buffer), " 0x%04x", *cali_point);
774
    }
775
      }
776
      strcat(line_buffer, "\n");
777
      FLUSH_BUFFER;
778
#endif
2098 tk 779
    }
1083 tk 780
  }
781
 
782
  sprintf(line_buffer, "CV_GateInv 0x%02x\n", (u8)SEQ_CV_GateInversionAllGet());
783
  FLUSH_BUFFER;
784
 
2385 tk 785
  sprintf(line_buffer, "CV_SusKey 0x%02x\n", (u8)SEQ_CV_SusKeyAllGet());
786
  FLUSH_BUFFER;
787
 
2098 tk 788
  {
789
    int clkout;
1083 tk 790
 
2098 tk 791
    for(clkout=0; clkout<SEQ_CV_NUM_CLKOUT; ++clkout) {
792
      sprintf(line_buffer, "CV_ExtClk %d %d %d\n", clkout, SEQ_CV_ClkDividerGet(clkout), SEQ_CV_ClkPulseWidthGet(clkout));
793
      FLUSH_BUFFER;
794
    }
795
  }
1083 tk 796
 
1864 tk 797
  sprintf(line_buffer, "TpdMode %d\n", SEQ_TPD_ModeGet());
798
  FLUSH_BUFFER;
799
 
2542 tk 800
  sprintf(line_buffer, "BLM_SCALAR_Port 0x%02x\n", (u8)BLM_SCALAR_MASTER_MIDI_PortGet(0));
1052 tk 801
  FLUSH_BUFFER;
802
 
2020 tk 803
  sprintf(line_buffer, "BLM_SCALAR_AlwaysUseFts %d\n", (u8)seq_blm_options.ALWAYS_USE_FTS);
804
  FLUSH_BUFFER;
805
 
1052 tk 806
#if !defined(MIOS32_FAMILY_EMULATION)
807
  {
808
    u32 value = UIP_TASK_IP_AddressGet();
809
    sprintf(line_buffer, "ETH_LocalIp %d.%d.%d.%d\n",
810
        (value >> 24) & 0xff,
811
        (value >> 16) & 0xff,
812
        (value >>  8) & 0xff,
813
        (value >>  0) & 0xff);
814
    FLUSH_BUFFER;
815
  }
816
 
817
  {
818
    u32 value = UIP_TASK_NetmaskGet();
819
    sprintf(line_buffer, "ETH_Netmask %d.%d.%d.%d\n",
820
        (value >> 24) & 0xff,
821
        (value >> 16) & 0xff,
822
        (value >>  8) & 0xff,
823
        (value >>  0) & 0xff);
824
    FLUSH_BUFFER;
825
  }
826
 
827
  {
828
    u32 value = UIP_TASK_GatewayGet();
829
    sprintf(line_buffer, "ETH_Gateway %d.%d.%d.%d\n",
830
        (value >> 24) & 0xff,
831
        (value >> 16) & 0xff,
832
        (value >>  8) & 0xff,
833
        (value >>  0) & 0xff);
834
    FLUSH_BUFFER;
835
  }
836
 
837
  sprintf(line_buffer, "ETH_Dhcp %d\n", UIP_TASK_DHCP_EnableGet());
838
  FLUSH_BUFFER;
839
 
1058 tk 840
  int con;
841
  for(con=0; con<OSC_SERVER_NUM_CONNECTIONS; ++con) {
842
    u32 value = OSC_SERVER_RemoteIP_Get(con);
843
    sprintf(line_buffer, "OSC_RemoteIp %d %d.%d.%d.%d\n",
844
        con,
1052 tk 845
        (value >> 24) & 0xff,
846
        (value >> 16) & 0xff,
847
        (value >>  8) & 0xff,
848
        (value >>  0) & 0xff);
849
    FLUSH_BUFFER;
850
 
1058 tk 851
    sprintf(line_buffer, "OSC_RemotePort %d %d\n", con, OSC_SERVER_RemotePortGet(con));
852
    FLUSH_BUFFER;
1052 tk 853
 
1058 tk 854
    sprintf(line_buffer, "OSC_LocalPort %d %d\n", con, OSC_SERVER_LocalPortGet(con));
855
    FLUSH_BUFFER;
1052 tk 856
 
1311 tk 857
    sprintf(line_buffer, "OSC_TransferMode %d %d\n", con, OSC_CLIENT_TransferModeGet(con));
1058 tk 858
    FLUSH_BUFFER;
859
  }
1052 tk 860
#endif
861
 
2131 tk 862
#ifndef MBSEQV4L
2130 tk 863
  sprintf(line_buffer, "ScreenSaverDelay %d\n", seq_lcd_logo_screensaver_delay);
864
  FLUSH_BUFFER;
2131 tk 865
#endif
2130 tk 866
 
1052 tk 867
  return status;
868
}
869
 
870
 
871
/////////////////////////////////////////////////////////////////////////////
872
// writes data into global config file
873
// returns < 0 on errors (error codes are documented in seq_file.h)
874
/////////////////////////////////////////////////////////////////////////////
875
s32 SEQ_FILE_GC_Write(void)
876
{
877
  seq_file_gc_info_t *info = &seq_file_gc_info;
878
 
879
  char filepath[MAX_PATH];
880
  sprintf(filepath, "%sMBSEQ_GC.V4", SEQ_FILES_PATH);
881
 
882
#if DEBUG_VERBOSE_LEVEL >= 2
883
  DEBUG_MSG("[SEQ_FILE_GC] Open global config file '%s' for writing\n", filepath);
884
#endif
885
 
886
  s32 status = 0;
1261 tk 887
  if( (status=FILE_WriteOpen(filepath, 1)) < 0 ) {
1052 tk 888
#if DEBUG_VERBOSE_LEVEL >= 1
889
    DEBUG_MSG("[SEQ_FILE_GC] Failed to open/create global config file, status: %d\n", status);
890
#endif
1261 tk 891
    FILE_WriteClose(); // important to free memory given by malloc
1052 tk 892
    info->valid = 0;
893
    return status;
894
  }
895
 
896
  // write file
897
  status |= SEQ_FILE_GC_Write_Hlp(1);
898
 
899
  // close file
1261 tk 900
  status |= FILE_WriteClose();
1052 tk 901
 
902
 
903
  // check if file is valid
904
  if( status >= 0 )
905
    info->valid = 1;
906
 
907
#if DEBUG_VERBOSE_LEVEL >= 2
908
  DEBUG_MSG("[SEQ_FILE_GC] global config file written with status %d\n", status);
909
#endif
910
 
911
  return (status < 0) ? SEQ_FILE_GC_ERR_WRITE : 0;
912
 
913
}
914
 
915
/////////////////////////////////////////////////////////////////////////////
916
// sends global config data to debug terminal
917
// returns < 0 on errors
918
/////////////////////////////////////////////////////////////////////////////
919
s32 SEQ_FILE_GC_Debug(void)
920
{
921
  return SEQ_FILE_GC_Write_Hlp(0); // send to debug terminal
922
}