Skip to content

Commit

Permalink
Merge branch 'release-0.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
sirosss committed Dec 10, 2023
2 parents b0e7657 + 1c44c38 commit 7545483
Show file tree
Hide file tree
Showing 10 changed files with 602 additions and 89 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## 0.2.0 (2023-12-10)

### New Features
- WAH block is displayed as disabled when exp pedal is set to control something else other than wah.
- MOD, DLY, and RVB blocks are displayed with underlined text when they are in parallel.
- Long pressing on tempo button now brings up the tempo edit popup which allows
- Entering tempo with on-screen numeric keyboard
- Selecting BPM/ms display
- Enabling **Global Tempo** mode

### Improvement
- Line spacing in preset and stomp buttons are reduced to conserve space.

## 0.1.0 (2023-11-20)

**First release!**
Expand Down
5 changes: 5 additions & 0 deletions lib/app_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ class AppConstants {
static String appName = '';
static String version = '';

static const int minTempoBPM = 40;
static const int maxTempoBPM = 480;
static const int minTempoMS = 1500;
static const int maxTempoMS = 125;

static Future<void> init() async {
final info = await PackageInfo.fromPlatform();
appName = info.appName;
Expand Down
5 changes: 5 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:loader_overlay/loader_overlay.dart';
import 'package:mg30controller/screens/test_page.dart';

import 'package:provider/provider.dart';
import 'package:go_router/go_router.dart';
Expand Down Expand Up @@ -95,6 +96,10 @@ class MainApp extends StatelessWidget {
return Colors.white;
}),
)),
toggleButtonsTheme: const ToggleButtonsThemeData(
fillColor: _primaryColor,
selectedColor: Colors.white,
color: Colors.grey),
fontFamily: 'BalooBhaijaan2'),
routerConfig: router(),
)),
Expand Down
107 changes: 85 additions & 22 deletions lib/models/device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_midi_command/flutter_midi_command.dart';

import '/utils.dart';

class DeviceModel extends ChangeNotifier {
bool isInitialized = false;

Expand All @@ -29,6 +31,7 @@ class DeviceModel extends ChangeNotifier {
int _tempo = 40;
DateTime _lastTapTempo = DateTime.now();
bool _showTempoInMillisec = false;
bool _globalTempo = false;

MidiDevice get midiDevice {
return _midiDevice!;
Expand All @@ -54,10 +57,20 @@ class DeviceModel extends ChangeNotifier {
return _tempo;
}

String get tempoForDisplay {
return _showTempoInMillisec
? Utils.bpmToMs(_tempo).toString()
: _tempo.toString();
}

bool get showTempoInMillisec {
return _showTempoInMillisec;
}

bool get globalTempo {
return _globalTempo;
}

List<EffectBlock> get effectChain {
return _effectChain;
}
Expand Down Expand Up @@ -199,7 +212,11 @@ class DeviceModel extends ChangeNotifier {
// Incoming program change
_programNo = data[1];
_scene = 0;
_sendGetCurrentEffectStateCommand(midi);

if (_globalTempo) {
_sendSetTempoCommand(midi);
}
_sendLoadPresetCommand(midi, _programNo);
notifyListeners();
} else if (data[0] == 0xB0) {
// Incoming CC
Expand All @@ -224,13 +241,17 @@ class DeviceModel extends ChangeNotifier {
}
}
} else if ((data.length == 15) &&
(_toHex(data) == 'F0 43 58 70 7E 02 0D 00 00 00 00 00 00 00 F7')) {
(_toHex(data.sublist(0, 7)) == 'F0 43 58 70 7E 02 0D')) {
// Effect order changed
_sendGetCurrentEffectStateCommand(midi);
} else if ((data.length == 15) &&
(_toHex(data) == 'F0 43 58 70 7E 02 03 00 01 00 00 00 00 00 F7')) {
(_toHex(data.sublist(0, 7)) == 'F0 43 58 70 7E 02 03')) {
// Tempo changed
_sendGetCurrentEffectStateCommand(midi);
} else if ((data.length == 15) &&
(_toHex(data.sublist(0, 7)) == 'F0 43 58 70 7E 02 13')) {
// Control assignment changed
_sendGetCurrentEffectStateCommand(midi);
} else if ((data.length == 15) &&
(_toHex(data.sublist(0, 7)) == 'F0 43 58 70 7E 02 0B')) {
// Preset saved
Expand All @@ -242,6 +263,11 @@ class DeviceModel extends ChangeNotifier {
// Response from get current effect state
_populateEffectChain(data);
notifyListeners();
} else if ((data.length == 218) &&
(_toHex(data.sublist(0, 6)) == 'F0 43 58 70 0B 02')) {
// Response from get current effect state
_populateEffectChain(data, updateTempo: !_globalTempo);
notifyListeners();
}
}
} catch (error, stackTrace) {
Expand Down Expand Up @@ -276,22 +302,29 @@ class DeviceModel extends ChangeNotifier {
return result.join();
}

void _populateEffectChain(Uint8List data) {
void _populateEffectChain(Uint8List data, {bool updateTempo = true}) {
_effectChain.clear();
_effectMap.clear();

if (_programNo < _programNames.length) {
_programNames[_programNo] = _convertProgramName(data.sublist(165, 189));
}

_tempo = (data[143] * 64) + data[144];
if (updateTempo) {
_tempo = (data[143] * 64) + data[144];
}

final effectTypeChain = _getEffectTypeChain(data);

for (int i = 0; i < effectTypeChain.length; i++) {
switch (effectTypeChain[i]) {
case 0:
_addEffectBlock(_getSingleCodeTypeBlock(data, 'WAH', 8, 2, 1));
EffectBlock effectBlock =
_getSingleCodeTypeBlock(data, 'WAH', 8, 2, 1);
if (data[194] != 2) {
effectBlock.isEnabled = false;
}
_addEffectBlock(effectBlock);
break;
case 1:
_addEffectBlock(_getDualCodeTypeBlock(data, 'CMP', 9, 4, 1));
Expand Down Expand Up @@ -330,6 +363,22 @@ class DeviceModel extends ChangeNotifier {
throw Exception('Unknown effect type code: $effectTypeChain[i]');
}
}

List<EffectBlock> modDlyRvb = _effectChain
.where((effectBlock) =>
['MOD', 'DLY', 'RVB'].contains(effectBlock.definition.category.id))
.toList();

if (modDlyRvb.length == 3) {
if (data[146] & 2 == 2) {
modDlyRvb[0].isParallel = true;
modDlyRvb[1].isParallel = true;
}
if (data[146] & 4 == 4) {
modDlyRvb[1].isParallel = true;
modDlyRvb[2].isParallel = true;
}
}
}

void _addEffectBlock(EffectBlock effectBlock) {
Expand Down Expand Up @@ -475,7 +524,9 @@ class DeviceModel extends ChangeNotifier {
midi.sendData(Uint8List.fromList([0xC0, programNo]),
deviceId: _midiDevice?.id, timestamp: 0);

_sendGetCurrentEffectStateCommand(midi);
if (_globalTempo) {
_sendSetTempoCommand(midi);
}
}

void _sendCCCommand(MidiCommand midi, int cc, int value) {
Expand Down Expand Up @@ -528,8 +579,18 @@ class DeviceModel extends ChangeNotifier {
_lastTapTempo = now;
}

void toggleTempoDisplayMode() {
_showTempoInMillisec = !_showTempoInMillisec;
void updateAllTempoData(
int tempo, bool showTempoInMillisec, bool globalTempo) {
_tempo = tempo;
_showTempoInMillisec = showTempoInMillisec;
_globalTempo = globalTempo;
_sendSetTempoCommand(MidiCommand());
notifyListeners();
}

void updateTempoFlags(bool showTempoInMillisec, bool globalTempo) {
_showTempoInMillisec = showTempoInMillisec;
_globalTempo = globalTempo;
notifyListeners();
}

Expand Down Expand Up @@ -611,29 +672,29 @@ class DeviceModel extends ChangeNotifier {
void _loadDummyEffectChain() {
_effectChain.clear();
_effectChain.add(EffectBlock(_effectCategories['WAH']!.saveOnEffects[8]!,
[true, true, true], false));
[true, true, true], true, false));
_effectChain.add(EffectBlock(_effectCategories['CMP']!.saveOnEffects[6]!,
[false, false, false], false));
[false, false, false], true, false));
_effectChain.add(EffectBlock(_effectCategories['EFX']!.saveOnEffects[16]!,
[true, true, true], false));
[true, true, true], true, false));
_effectChain.add(EffectBlock(_effectCategories['AMP']!.saveOnEffects[13]!,
[true, true, true], false));
[true, true, true], true, false));
_effectChain.add(EffectBlock(_effectCategories['EQ']!.saveOnEffects[6]!,
[false, false, false], false));
[false, false, false], true, false));
_effectChain.add(EffectBlock(_effectCategories['GATE']!.saveOnEffects[1]!,
[true, true, true], false));
[true, true, true], true, false));
_effectChain.add(EffectBlock(_effectCategories['MOD']!.saveOnEffects[26]!,
[false, false, false], false));
[false, false, false], true, false));
_effectChain.add(EffectBlock(_effectCategories['DLY']!.saveOnEffects[4]!,
[false, false, false], false));
[false, false, false], true, false));
_effectChain.add(EffectBlock(_effectCategories['RVB']!.saveOnEffects[8]!,
[false, false, false], false));
[false, false, false], true, false));
_effectChain.add(EffectBlock(
_effectCategories['IR']!.saveOnEffects[7]!, [true, true, true], false));
_effectChain.add(EffectBlock(_effectCategories['S/R']!.saveOffEffects[1]!,
[false, false, false], false));
[false, false, false], true, false));
_effectChain.add(EffectBlock(_effectCategories['VOL']!.saveOnEffects[1]!,
[true, true, true], false));
[true, true, true], true, false));
}

String _toHex(Uint8List data, {String separator = ' '}) {
Expand Down Expand Up @@ -667,9 +728,11 @@ class EffectDefinition {
class EffectBlock {
final EffectDefinition definition;
List<bool> isOn;
final bool isParallel;
bool isEnabled;
bool isParallel;

EffectBlock(this.definition, this.isOn, [this.isParallel = false]);
EffectBlock(this.definition, this.isOn,
[this.isEnabled = true, this.isParallel = false]);
}

enum MG30VerificationState { init, verified, unknown }
5 changes: 4 additions & 1 deletion lib/screens/prorgam_scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,10 @@ class ProgramSelectionButton extends StatelessWidget {
alignment: Alignment.center,
child: Text(
device.getProgramName(programNo),
style: Theme.of(context).textTheme.headlineSmall,
style: Theme.of(context)
.textTheme
.headlineSmall
?.copyWith(height: 0.9),
textAlign: TextAlign.center,
))),
]),
Expand Down
71 changes: 71 additions & 0 deletions lib/screens/stomp_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '/models/device.dart';

class StompButton extends StatelessWidget {
const StompButton(this.effectCategoryId, {super.key});

final String effectCategoryId;

@override
Widget build(BuildContext context) {
return Consumer<DeviceModel>(
builder: (context, device, child) {
EffectBlock? effectBlock = device.getEffectBlock(effectCategoryId);
if (effectBlock == null) {
return const Text('');
}

Color blockColor = effectBlock.isEnabled
? effectBlock.definition.category.color
: const Color.fromARGB(255, 64, 64, 64);

Color backgroundColor = device.isEffectOn(effectBlock)
? blockColor
: Theme.of(context).colorScheme.background;
Color textColor = device.isEffectOn(effectBlock)
? Theme.of(context).colorScheme.background
: blockColor;

return GestureDetector(
onTap: () {
if (effectBlock.isEnabled) {
device.toggleEffectBlock(effectCategoryId);
}
},
child: Container(
padding: const EdgeInsets.all(5),
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: backgroundColor,
border: Border.all(
color: blockColor,
width: 4,
),
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: Text(
effectBlock.isEnabled
? effectBlock.definition.name
: effectBlock.definition.category.id,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge!.copyWith(
color: textColor,
height: 0.9,
decoration: effectBlock.isParallel
? TextDecoration.underline
: TextDecoration.none,
decorationStyle: TextDecorationStyle.solid,
decorationThickness: 2,
decorationColor: textColor,
),
),
)),
));
},
);
}
}
Loading

0 comments on commit 7545483

Please sign in to comment.