private void Props_PropertyChanged(PropertyPage props, int propIdx, int rowIdx, int colIdx, object value) { if (song.UsesFamiTrackerTempo) { var tempo = song.FamitrackerTempo; var speed = song.FamitrackerSpeed; if (propIdx == famitrackerTempoPropIdx || propIdx == famitrackerSpeedPropIdx) { tempo = props.GetPropertyValue <int>(famitrackerTempoPropIdx); speed = props.GetPropertyValue <int>(famitrackerSpeedPropIdx); } var beatLength = props.GetPropertyValue <int>(notesPerBeatPropIdx); props.SetLabelText(bpmLabelPropIdx, Song.ComputeFamiTrackerBPM(song.Project.PalMode, speed, tempo, beatLength).ToString("n1")); } else { var notesPerBeat = props.GetPropertyValue <int>(notesPerBeatPropIdx); // Changing the number of notes in a beat will affect the list of available BPMs. if (propIdx == notesPerBeatPropIdx) { tempoList = FamiStudioTempoUtils.GetAvailableTempos(song.Project.PalMode, notesPerBeat); tempoStrings = tempoList.Select(t => t.bpm.ToString("n1") + (t.groove.Length == 1 ? " *" : "")).ToArray(); props.UpdateDropDownListItems(famistudioBpmPropIdx, tempoStrings); } // Changing the BPM affects the grooves and note length. if (propIdx == famistudioBpmPropIdx || propIdx == notesPerBeatPropIdx) { var tempoIndex = Array.IndexOf(tempoStrings, props.GetPropertyValue <string>(famistudioBpmPropIdx)); var tempoInfo = tempoList[tempoIndex]; var framesPerNote = Utils.Min(tempoInfo.groove); props.UpdateIntegerRange(notesPerPatternPropIdx, 1, Pattern.MaxLength / framesPerNote); var grooveList = FamiStudioTempoUtils.GetAvailableGrooves(tempoInfo.groove); grooveStrings = grooveList.Select(g => string.Join("-", g)).ToArray(); props.UpdateDropDownListItems(groovePropIdx, grooveStrings); props.SetLabelText(framesPerNotePropIdx, framesPerNote.ToString()); } } UpdateWarnings(); }
private void WavMp3_PropertyChanged(PropertyPage props, int propIdx, int rowIdx, int colIdx, object value) { if (propIdx == 1) { props.SetPropertyEnabled(3, (string)value != "WAV"); } else if (propIdx == 4) { props.SetPropertyEnabled(5, (string)value != "Duration"); props.SetPropertyEnabled(6, (string)value == "Duration"); } else if (propIdx == 7) { var separateChannels = (bool)value; props.SetPropertyEnabled(9, !separateChannels); if (separateChannels) { props.SetPropertyValue(9, false); } props.SetColumnEnabled(10, 2, props.GetPropertyValue <bool>(9)); } else if (propIdx == 9) { props.SetColumnEnabled(10, 2, (bool)value); } }
private void MappingProperties_PropertyChanged(PropertyPage props, int idx, object value) { var sourceType = MidiSourceType.GetValueForName(props.GetPropertyValue <string>(0)); if (idx == 0) { props.UpdateDropDownListItems(1, GetSourceNames(sourceType)); } var allowChannel10Mapping = false; if (sourceType == MidiSourceType.Channel) { var channelIdx = int.Parse(props.GetPropertyValue <string>(1).Substring(8)) - 1; allowChannel10Mapping = channelIdx == 9; } props.SetPropertyEnabled(1, sourceType != MidiSourceType.None); props.SetPropertyEnabled(3, sourceType != MidiSourceType.None && allowChannel10Mapping); props.SetPropertyEnabled(4, sourceType != MidiSourceType.None && allowChannel10Mapping); props.SetPropertyEnabled(5, sourceType != MidiSourceType.None && allowChannel10Mapping); }
private void Properties_PropertyChanged(PropertyPage props, int idx, object value) { if (inPropertyChanged) { return; } inPropertyChanged = true; // Prevent recursion. if (idx == 1) { bool allEffects = (bool)value; foreach (var kv in propToEffect) { props.SetPropertyValue(kv.Key, allEffects); } } else if (propToEffect.ContainsKey(idx)) { bool allEffects = true; foreach (var kv in propToEffect) { if (!props.GetPropertyValue <bool>(kv.Key)) { allEffects = false; break; } } props.SetPropertyValue(1, allEffects); } inPropertyChanged = false; }
private void UpdateWarnings() { var numFramesPerPattern = 0; if (song.UsesFamiStudioTempo) { var tempoIndex = Array.IndexOf(tempoStrings, props.GetPropertyValue <string>(famistudioBpmPropIdx)); var tempoInfo = tempoList[tempoIndex]; var notesPerBeat = props.GetPropertyValue <int>(notesPerBeatPropIdx); var notesPerPattern = props.GetPropertyValue <int>(notesPerPatternPropIdx); if (tempoInfo.groove.Length == 1) { props.SetPropertyWarning(famistudioBpmPropIdx, CommentType.Good, "Ideal tempo : notes will be perfectly evenly divided."); } else if ((tempoInfo.groove.Length % notesPerBeat) == 0 || (notesPerBeat % tempoInfo.groove.Length) == 0) { props.SetPropertyWarning(famistudioBpmPropIdx, CommentType.Warning, "Beat-aligned groove : notes will be slightly uneven, but well aligned with the beat."); } else { props.SetPropertyWarning(famistudioBpmPropIdx, CommentType.Error, "Unaligned groove : notes will be slightly uneven and not aligned to the beat."); } if (notesPerBeat != 4) { props.SetPropertyWarning(notesPerBeatPropIdx, CommentType.Error, "A value of 4 is strongly recommended as it gives the best range of available BPMs."); } else { props.SetPropertyWarning(notesPerBeatPropIdx, CommentType.Good, "4 is the recommended value."); } var groovePadMode = GroovePaddingType.GetValueForName(props.GetPropertyValue <string>(groovePadPropIdx)); numFramesPerPattern = FamiStudioTempoUtils.ComputeNumberOfFrameForGroove(notesPerPattern * Utils.Min(tempoInfo.groove), tempoInfo.groove, groovePadMode); } else if (famitrackerSpeedPropIdx >= 0) { var speed = props.GetPropertyValue <int>(famitrackerSpeedPropIdx); var tempo = props.GetPropertyValue <int>(famitrackerTempoPropIdx); if (speed == 1) { props.SetPropertyWarning(famitrackerSpeedPropIdx, CommentType.Warning, $"A speed of 1 will not produce the same BPM between platforms (PAL/NTSC)."); } else { props.SetPropertyWarning(famitrackerSpeedPropIdx, CommentType.Good, ""); } if (tempo != 150) { props.SetPropertyWarning(famitrackerTempoPropIdx, CommentType.Warning, "A tempo of 150 is strongly recommended as it produces even notes on all platforms (NTSC/PAL)."); } else { props.SetPropertyWarning(famitrackerTempoPropIdx, CommentType.Good, "150 is the recommended value."); } } if (patternIdx >= 0 && numFramesPerPattern > song.PatternLength) { props.SetPropertyWarning(notesPerPatternPropIdx, CommentType.Warning, $"Pattern is longer than the song pattern length and FamiTracker does not support this. Ignore this if you are not planning to export to FamiTracker."); } else if (numFramesPerPattern >= 256) { props.SetPropertyWarning(notesPerPatternPropIdx, CommentType.Warning, $"Pattern is longer than what FamiTracker supports. Ignore this if you are not planning to export to FamiTracker."); } else { props.SetPropertyWarning(notesPerPatternPropIdx, CommentType.Good, ""); } }
private void Properties_PropertyChanged(PropertyPage props, int propIdx, int rowIdx, int colIdx, object value) { if (propIdx == 4) { var expansionMask = GetExpansionMask(props.GetPropertyValue <bool[]>(4)); var newChannelCount = Channel.GetChannelCountForExpansionMask(expansionMask, 8); var oldChannelCount = channelSources.Length; var maxChannelIndex = 2; for (int i = 0; i < oldChannelCount; i++) { if (channelSources[i].type == MidiSourceType.Channel && channelSources[i].index != 9) { maxChannelIndex = Math.Max(maxChannelIndex, channelSources[i].index); } } Array.Resize(ref channelSources, newChannelCount); for (int i = oldChannelCount; i < newChannelCount; i++) { maxChannelIndex = Math.Min(maxChannelIndex + 1, 15); if (maxChannelIndex == 9) { maxChannelIndex++; } channelSources[i] = new MidiFileReader.MidiSource() { index = maxChannelIndex }; } UpdateListView(); bool allowPal = expansionMask == ExpansionType.NoneMask; dialog.Properties.SetPropertyEnabled(3, allowPal); if (!allowPal) { dialog.Properties.SetPropertyValue(3, false); } } else if (propIdx == 6) { Debug.Assert(colIdx == 1); var src = channelSources[rowIdx]; var str = (string)value; if (str.StartsWith("Track")) { src.type = MidiSourceType.Track; src.index = Utils.ParseIntWithTrailingGarbage(str.Substring(6)) - 1; } else if (str.StartsWith("Channel")) { src.type = MidiSourceType.Channel; src.index = Utils.ParseIntWithTrailingGarbage(str.Substring(8)) - 1; } else { src.type = MidiSourceType.None; src.index = 0; } UpdateListView(); } }