Subversion Repositories svn.mios32

Rev

Rev 2545 | Rev 2567 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1052 tk 1
// $Id: seq_file_gc.c 2564 2018-03-03 21:31:17Z 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
1052 tk 373
      } else if( strcmp(parameter, "RemoteMode") == 0 ) {
1316 tk 374
        seq_midi_sysex_remote_mode = (value > 2) ? 0 : value;
1052 tk 375
      } else if( strcmp(parameter, "RemotePort") == 0 ) {
1316 tk 376
        seq_midi_sysex_remote_port = value;
1052 tk 377
      } else if( strcmp(parameter, "RemoteID") == 0 ) {
1316 tk 378
        seq_midi_sysex_remote_id = (value > 128) ? 0 : value;
2131 tk 379
#ifndef MBSEQV4L
2130 tk 380
      } else if( strcmp(parameter, "ScreenSaverDelay") == 0 ) {
381
        seq_lcd_logo_screensaver_delay = (value > 255) ? 255 : value;
2131 tk 382
#endif
1083 tk 383
      } else if( strcmp(parameter, "CV_AOUT_Type") == 0 ) {
384
        SEQ_CV_IfSet(value);
385
      } else if( strcmp(parameter, "CV_PinMode") == 0 ) {
386
        u32 cv = value;
387
        if( cv >= SEQ_CV_NUM ) {
2542 tk 388
          DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong CV channel %u for parameter '%s'\n", value, parameter);
1083 tk 389
        } else {
390
          word = strtok_r(NULL, separators, &brkt);
391
          u32 curve = get_dec(word);
392
          if( curve >= SEQ_CV_NUM_CURVES ) {
2542 tk 393
        DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong curve %u for parameter '%s', CV channel %u\n", curve, parameter, cv);
1083 tk 394
          } else {
395
        word = strtok_r(NULL, separators, &brkt);
396
        u32 slewrate = get_dec(word);
397
        if( slewrate >= 256 ) // saturate
398
          slewrate = 255;
1052 tk 399
 
1083 tk 400
        word = strtok_r(NULL, separators, &brkt);
401
        u32 range = get_dec(word);
402
        if( range >= 127 ) // saturate
403
          range = 2; // default value
404
 
405
        SEQ_CV_CurveSet(cv, curve);
406
        SEQ_CV_SlewRateSet(cv, slewrate);
407
        SEQ_CV_PitchRangeSet(cv, range);
408
          }
409
        }
410
      } else if( strcmp(parameter, "CV_GateInv") == 0 ) {
411
        SEQ_CV_GateInversionAllSet(value);
2385 tk 412
      } else if( strcmp(parameter, "CV_SusKey") == 0 ) {
413
        SEQ_CV_SusKeyAllSet(value);
1083 tk 414
      } else if( strcmp(parameter, "CV_ClkPulsewidth") == 0 ) {
2098 tk 415
        SEQ_CV_ClkPulseWidthSet(0, value); // Legacy Value - replaced by CV_ExtClk
1083 tk 416
      } else if( strcmp(parameter, "CV_ClkDivider") == 0 ) {
2098 tk 417
        SEQ_CV_ClkDividerSet(0, value); // Legacy Value - replaced by CV_ExtClk
418
      } else if( strcmp(parameter, "CV_ExtClk") == 0 ) {
419
        u32 clkout = value;
420
        if( clkout >= SEQ_CV_NUM_CLKOUT ) {
2542 tk 421
          DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong clock output %u for parameter '%s'\n", value, parameter);
2098 tk 422
        } else {
423
          word = strtok_r(NULL, separators, &brkt);
424
          u32 divider = get_dec(word);
425
          if( divider >= 65536 ) {
2542 tk 426
        DEBUG_MSG("[SEQ_FILE_GC] ERROR wrong divider value %u for parameter '%s', clock output %u\n", divider, parameter, clkout);
2098 tk 427
          } else {
428
        word = strtok_r(NULL, separators, &brkt);
429
        u32 pulsewidth = get_dec(word);
430
        if( pulsewidth >= 256 ) // saturate
431
          pulsewidth = 255;
432
 
433
        SEQ_CV_ClkDividerSet(clkout, divider);
434
        SEQ_CV_ClkPulseWidthSet(clkout, pulsewidth);
435
          }
436
        }
1864 tk 437
      } else if( strcmp(parameter, "TpdMode") == 0 ) {
438
        SEQ_TPD_ModeSet(value);
1052 tk 439
      } else if( strcmp(parameter, "BLM_SCALAR_Port") == 0 ) {
2263 tk 440
        BLM_SCALAR_MASTER_MIDI_PortSet(0, value);
1052 tk 441
 
2263 tk 442
        BLM_SCALAR_MASTER_TimeoutCtrSet(0, 0); // fake timeout (so that "BLM not found" message will be displayed)
443
        BLM_SCALAR_MASTER_SendRequest(0, 0x00); // request layout from BLM_SCALAR
1052 tk 444
 
445
#if !defined(MIOS32_FAMILY_EMULATION)
2020 tk 446
      } else if( strcmp(parameter, "BLM_SCALAR_AlwaysUseFts") == 0 ) {
447
        seq_blm_options.ALWAYS_USE_FTS = value;
1052 tk 448
      } else if( strcmp(parameter, "ETH_Dhcp") == 0 ) {
449
        UIP_TASK_DHCP_EnableSet((value >= 1) ? 1 : 0);
1058 tk 450
      } else if( strcmp(parameter, "OSC_RemoteIp") == 0 ) {
451
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
452
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
453
        } else {
454
          u8 con = value;
455
          u32 ip;
456
          if( !(ip=get_ip(brkt)) ) {
457
#if DEBUG_VERBOSE_LEVEL >= 1
458
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid IP format for parameter '%s'\n", parameter);
459
#endif
460
          } else {
461
        OSC_SERVER_RemoteIP_Set(con, ip);
462
          }
463
        }
1052 tk 464
      } else if( strcmp(parameter, "OSC_RemotePort") == 0 ) {
1058 tk 465
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
466
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
467
        } else {
468
          u8 con = value;
469
          word = strtok_r(NULL, separators, &brkt);
470
          if( (value=get_dec(word)) < 0 ) {
471
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid port number for parameter '%s'\n", parameter);
472
          } else {
473
        OSC_SERVER_RemotePortSet(con, value);
474
          }
475
        }
1052 tk 476
      } else if( strcmp(parameter, "OSC_LocalPort") == 0 ) {
1058 tk 477
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
478
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
479
        } else {
480
          u8 con = value;
481
          word = strtok_r(NULL, separators, &brkt);
482
          if( (value=get_dec(word)) < 0 ) {
483
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid port number for parameter '%s'\n", parameter);
484
          } else {
485
        OSC_SERVER_LocalPortSet(con, value);
486
          }
487
        }
488
      } else if( strcmp(parameter, "OSC_TransferMode") == 0 ) {
489
        if( value > OSC_SERVER_NUM_CONNECTIONS ) {
490
          DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid connection number for parameter '%s'\n", parameter);
491
        } else {
492
          u8 con = value;
493
          word = strtok_r(NULL, separators, &brkt);
494
          if( (value=get_dec(word)) < 0 ) {
495
        DEBUG_MSG("[SEQ_FILE_GC] ERROR invalid transfer mode number for parameter '%s'\n", parameter);
496
          } else {
1311 tk 497
        OSC_CLIENT_TransferModeSet(con, value);
1058 tk 498
          }
499
        }
1052 tk 500
#endif
501
      } else {
502
#if DEBUG_VERBOSE_LEVEL >= 2
503
        // changed error level from 1 to 2 here, since people are sometimes confused about these messages
504
        // on file format changes
505
        DEBUG_MSG("[SEQ_FILE_GC] ERROR: unknown parameter: %s", line_buffer);
506
#endif
507
      }
508
    }
509
      } else {
510
#if DEBUG_VERBOSE_LEVEL >= 1
511
    DEBUG_MSG("[SEQ_FILE_GC] ERROR no space separator in following line: %s", line_buffer);
512
#endif
513
      }
514
    }
515
 
516
  } while( status >= 1 );
517
 
518
  // close file
1261 tk 519
  status |= FILE_ReadClose(&file);
1052 tk 520
 
1058 tk 521
#if !defined(MIOS32_FAMILY_EMULATION)
522
  // OSC_SERVER_Init(0) has to be called after all settings have been done!
523
  OSC_SERVER_Init(0);
524
#endif
525
 
1052 tk 526
  if( status < 0 ) {
527
#if DEBUG_VERBOSE_LEVEL >= 1
528
    DEBUG_MSG("[SEQ_FILE_GC] ERROR while reading file, status: %d\n", status);
529
#endif
530
    return SEQ_FILE_GC_ERR_READ;
531
  }
532
 
533
  // file is valid! :)
534
  info->valid = 1;
535
 
536
  // change tempo to given preset
537
  SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]);
538
 
539
  return 0; // no error
540
}
541
 
542
 
543
/////////////////////////////////////////////////////////////////////////////
544
// help function to write data into file or send to debug terminal
545
// returns < 0 on errors (error codes are documented in seq_file.h)
546
/////////////////////////////////////////////////////////////////////////////
547
static s32 SEQ_FILE_GC_Write_Hlp(u8 write_to_file)
548
{
549
  s32 status = 0;
550
  char line_buffer[128];
551
 
1261 tk 552
#define FLUSH_BUFFER if( !write_to_file ) { DEBUG_MSG(line_buffer); } else { status |= FILE_WriteBuffer((u8 *)line_buffer, strlen(line_buffer)); }
1052 tk 553
 
554
  // write global config values
2542 tk 555
  sprintf(line_buffer, "MetronomePort 0x%02x\n", (u8)seq_core_metronome_port);
1052 tk 556
  FLUSH_BUFFER;
557
 
558
  sprintf(line_buffer, "MetronomeChannel %d\n", (u8)seq_core_metronome_chn);
559
  FLUSH_BUFFER;
560
 
561
  sprintf(line_buffer, "MetronomeNoteM %d\n", (u8)seq_core_metronome_note_m);
562
  FLUSH_BUFFER;
563
 
564
  sprintf(line_buffer, "MetronomeNoteB %d\n", (u8)seq_core_metronome_note_b);
565
  FLUSH_BUFFER;
566
 
2545 tk 567
  sprintf(line_buffer, "ShadowOutPort 0x%02x\n", (u8)seq_core_shadow_out_port);
568
  FLUSH_BUFFER;
569
 
570
  sprintf(line_buffer, "ShadowOutChannel %d\n", (u8)seq_core_shadow_out_chn);
571
  FLUSH_BUFFER;
572
 
2542 tk 573
  sprintf(line_buffer, "MidiRemoteKey %d\n", (u8)seq_midi_in_remote.value);
574
  FLUSH_BUFFER;
575
 
576
  sprintf(line_buffer, "MidiRemoteCCorKey %d\n", (u8)seq_midi_in_remote.cc_or_key);
577
  FLUSH_BUFFER;
578
 
2544 tk 579
#ifndef MBSEQV4L
2542 tk 580
  sprintf(line_buffer, "TrackCCMode %d\n", (u8)seq_ui_track_cc.mode);
581
  FLUSH_BUFFER;
582
 
583
  sprintf(line_buffer, "TrackCCPort 0x%02x\n", (u8)seq_ui_track_cc.port);
584
  FLUSH_BUFFER;
585
 
586
  sprintf(line_buffer, "TrackCCChannel %d\n", (u8)seq_ui_track_cc.chn);
587
  FLUSH_BUFFER;
588
 
589
  sprintf(line_buffer, "TrackCCNumber %d\n", (u8)seq_ui_track_cc.cc);
590
  FLUSH_BUFFER;
2544 tk 591
#endif
2542 tk 592
 
593
  {
594
    mios32_midi_port_t port;
595
    for(port=UART0; port<=UART3; ++port) {
596
      s32 enabled = MIOS32_MIDI_RS_OptimisationGet(port);
597
      if( enabled >= 0 ) {
598
    sprintf(line_buffer, "MidiOutRSOpt 0x%02x %d\n", (u8)port, enabled);
599
    FLUSH_BUFFER;
600
      }
601
    }
602
  }
603
 
2544 tk 604
#ifndef MBSEQV4L
2542 tk 605
  sprintf(line_buffer, "MenuShortcuts %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
606
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(0),
607
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(1),
608
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(2),
609
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(3),
610
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(4),
611
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(5),
612
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(6),
613
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(7),
614
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(8),
615
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(9),
616
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(10),
617
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(11),
618
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(12),
619
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(13),
620
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(14),
621
      (int)SEQ_UI_PAGES_MenuShortcutPageGet(15)
622
      );
623
  FLUSH_BUFFER;    
2544 tk 624
#endif
2542 tk 625
 
1075 tk 626
  sprintf(line_buffer, "PasteClrAll %d\n", seq_core_options.PASTE_CLR_ALL);
627
  FLUSH_BUFFER;
628
 
2131 tk 629
#ifndef MBSEQV4L
2101 tk 630
  sprintf(line_buffer, "DatawheelMode %d\n", seq_ui_edit_datawheel_mode);
631
  FLUSH_BUFFER;
2131 tk 632
#endif
2101 tk 633
 
634
  sprintf(line_buffer, "MixerLiveSend %d\n", seq_core_options.MIXER_LIVE_SEND);
635
  FLUSH_BUFFER;
636
 
1794 tk 637
  sprintf(line_buffer, "InitCC %d\n", seq_core_options.INIT_CC);
638
  FLUSH_BUFFER;
639
 
2294 tk 640
  sprintf(line_buffer, "InitWithTriggers %d\n", seq_core_options.INIT_WITH_TRIGGERS);
641
  FLUSH_BUFFER;
642
 
1810 tk 643
  sprintf(line_buffer, "LiveLayerMuteSteps %d\n", seq_core_options.LIVE_LAYER_MUTE_STEPS);
644
  FLUSH_BUFFER;
645
 
1794 tk 646
  sprintf(line_buffer, "PatternMixerMapCoupling %d\n", seq_core_options.PATTERN_MIXER_MAP_COUPLING);
647
  FLUSH_BUFFER;
648
 
1323 tk 649
  sprintf(line_buffer, "MultiPortEnableFlags 0x%06x\n", seq_midi_port_multi_enable_flags);
650
  FLUSH_BUFFER;
651
 
2263 tk 652
#ifndef MBSEQV4L
2250 tk 653
  sprintf(line_buffer, "UiRestoreTrackSelections %d\n", seq_ui_options.RESTORE_TRACK_SELECTIONS);
654
  FLUSH_BUFFER;
2263 tk 655
#endif
2250 tk 656
 
2545 tk 657
#ifndef MBSEQV4L
658
  sprintf(line_buffer, "UiModifyPatternBanks %d\n", seq_ui_options.MODIFY_PATTERN_BANKS);
659
  FLUSH_BUFFER;
660
#endif
661
 
2564 tk 662
#ifndef MBSEQV4L
663
  sprintf(line_buffer, "UiPrintAndModifyWithoutGates %d\n", seq_ui_options.PRINT_AND_MODIFY_WITHOUT_GATES);
664
  FLUSH_BUFFER;
665
#endif
666
 
1316 tk 667
  sprintf(line_buffer, "RemoteMode %d\n", (u8)seq_midi_sysex_remote_mode);
1052 tk 668
  FLUSH_BUFFER;
669
 
2542 tk 670
  sprintf(line_buffer, "RemotePort 0x%02x\n", (u8)seq_midi_sysex_remote_port);
1052 tk 671
  FLUSH_BUFFER;
672
 
1316 tk 673
  sprintf(line_buffer, "RemoteID %d\n", (u8)seq_midi_sysex_remote_id);
1052 tk 674
  FLUSH_BUFFER;
675
 
1083 tk 676
  sprintf(line_buffer, "CV_AOUT_Type %d\n", (u8)SEQ_CV_IfGet());
677
  FLUSH_BUFFER;
678
 
2098 tk 679
  {
680
    int cv;
681
    for(cv=0; cv<SEQ_CV_NUM; ++cv) {
682
      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));
683
      FLUSH_BUFFER;
684
    }
1083 tk 685
  }
686
 
687
  sprintf(line_buffer, "CV_GateInv 0x%02x\n", (u8)SEQ_CV_GateInversionAllGet());
688
  FLUSH_BUFFER;
689
 
2385 tk 690
  sprintf(line_buffer, "CV_SusKey 0x%02x\n", (u8)SEQ_CV_SusKeyAllGet());
691
  FLUSH_BUFFER;
692
 
2098 tk 693
  {
694
    int clkout;
1083 tk 695
 
2098 tk 696
    for(clkout=0; clkout<SEQ_CV_NUM_CLKOUT; ++clkout) {
697
      sprintf(line_buffer, "CV_ExtClk %d %d %d\n", clkout, SEQ_CV_ClkDividerGet(clkout), SEQ_CV_ClkPulseWidthGet(clkout));
698
      FLUSH_BUFFER;
699
    }
700
  }
1083 tk 701
 
1864 tk 702
  sprintf(line_buffer, "TpdMode %d\n", SEQ_TPD_ModeGet());
703
  FLUSH_BUFFER;
704
 
2542 tk 705
  sprintf(line_buffer, "BLM_SCALAR_Port 0x%02x\n", (u8)BLM_SCALAR_MASTER_MIDI_PortGet(0));
1052 tk 706
  FLUSH_BUFFER;
707
 
2020 tk 708
  sprintf(line_buffer, "BLM_SCALAR_AlwaysUseFts %d\n", (u8)seq_blm_options.ALWAYS_USE_FTS);
709
  FLUSH_BUFFER;
710
 
1052 tk 711
#if !defined(MIOS32_FAMILY_EMULATION)
712
  {
713
    u32 value = UIP_TASK_IP_AddressGet();
714
    sprintf(line_buffer, "ETH_LocalIp %d.%d.%d.%d\n",
715
        (value >> 24) & 0xff,
716
        (value >> 16) & 0xff,
717
        (value >>  8) & 0xff,
718
        (value >>  0) & 0xff);
719
    FLUSH_BUFFER;
720
  }
721
 
722
  {
723
    u32 value = UIP_TASK_NetmaskGet();
724
    sprintf(line_buffer, "ETH_Netmask %d.%d.%d.%d\n",
725
        (value >> 24) & 0xff,
726
        (value >> 16) & 0xff,
727
        (value >>  8) & 0xff,
728
        (value >>  0) & 0xff);
729
    FLUSH_BUFFER;
730
  }
731
 
732
  {
733
    u32 value = UIP_TASK_GatewayGet();
734
    sprintf(line_buffer, "ETH_Gateway %d.%d.%d.%d\n",
735
        (value >> 24) & 0xff,
736
        (value >> 16) & 0xff,
737
        (value >>  8) & 0xff,
738
        (value >>  0) & 0xff);
739
    FLUSH_BUFFER;
740
  }
741
 
742
  sprintf(line_buffer, "ETH_Dhcp %d\n", UIP_TASK_DHCP_EnableGet());
743
  FLUSH_BUFFER;
744
 
1058 tk 745
  int con;
746
  for(con=0; con<OSC_SERVER_NUM_CONNECTIONS; ++con) {
747
    u32 value = OSC_SERVER_RemoteIP_Get(con);
748
    sprintf(line_buffer, "OSC_RemoteIp %d %d.%d.%d.%d\n",
749
        con,
1052 tk 750
        (value >> 24) & 0xff,
751
        (value >> 16) & 0xff,
752
        (value >>  8) & 0xff,
753
        (value >>  0) & 0xff);
754
    FLUSH_BUFFER;
755
 
1058 tk 756
    sprintf(line_buffer, "OSC_RemotePort %d %d\n", con, OSC_SERVER_RemotePortGet(con));
757
    FLUSH_BUFFER;
1052 tk 758
 
1058 tk 759
    sprintf(line_buffer, "OSC_LocalPort %d %d\n", con, OSC_SERVER_LocalPortGet(con));
760
    FLUSH_BUFFER;
1052 tk 761
 
1311 tk 762
    sprintf(line_buffer, "OSC_TransferMode %d %d\n", con, OSC_CLIENT_TransferModeGet(con));
1058 tk 763
    FLUSH_BUFFER;
764
  }
1052 tk 765
#endif
766
 
2131 tk 767
#ifndef MBSEQV4L
2130 tk 768
  sprintf(line_buffer, "ScreenSaverDelay %d\n", seq_lcd_logo_screensaver_delay);
769
  FLUSH_BUFFER;
2131 tk 770
#endif
2130 tk 771
 
1052 tk 772
  return status;
773
}
774
 
775
 
776
/////////////////////////////////////////////////////////////////////////////
777
// writes data into global config file
778
// returns < 0 on errors (error codes are documented in seq_file.h)
779
/////////////////////////////////////////////////////////////////////////////
780
s32 SEQ_FILE_GC_Write(void)
781
{
782
  seq_file_gc_info_t *info = &seq_file_gc_info;
783
 
784
  char filepath[MAX_PATH];
785
  sprintf(filepath, "%sMBSEQ_GC.V4", SEQ_FILES_PATH);
786
 
787
#if DEBUG_VERBOSE_LEVEL >= 2
788
  DEBUG_MSG("[SEQ_FILE_GC] Open global config file '%s' for writing\n", filepath);
789
#endif
790
 
791
  s32 status = 0;
1261 tk 792
  if( (status=FILE_WriteOpen(filepath, 1)) < 0 ) {
1052 tk 793
#if DEBUG_VERBOSE_LEVEL >= 1
794
    DEBUG_MSG("[SEQ_FILE_GC] Failed to open/create global config file, status: %d\n", status);
795
#endif
1261 tk 796
    FILE_WriteClose(); // important to free memory given by malloc
1052 tk 797
    info->valid = 0;
798
    return status;
799
  }
800
 
801
  // write file
802
  status |= SEQ_FILE_GC_Write_Hlp(1);
803
 
804
  // close file
1261 tk 805
  status |= FILE_WriteClose();
1052 tk 806
 
807
 
808
  // check if file is valid
809
  if( status >= 0 )
810
    info->valid = 1;
811
 
812
#if DEBUG_VERBOSE_LEVEL >= 2
813
  DEBUG_MSG("[SEQ_FILE_GC] global config file written with status %d\n", status);
814
#endif
815
 
816
  return (status < 0) ? SEQ_FILE_GC_ERR_WRITE : 0;
817
 
818
}
819
 
820
/////////////////////////////////////////////////////////////////////////////
821
// sends global config data to debug terminal
822
// returns < 0 on errors
823
/////////////////////////////////////////////////////////////////////////////
824
s32 SEQ_FILE_GC_Debug(void)
825
{
826
  return SEQ_FILE_GC_Write_Hlp(0); // send to debug terminal
827
}