-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathProject.fs
More file actions
127 lines (110 loc) · 4.78 KB
/
Copy pathProject.fs
File metadata and controls
127 lines (110 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module RSXmlCombiner.FuncUI.Project
open System
open System.IO
open System.Text.Json
open System.Text.Json.Serialization
open Rocksmith2014.XML
type Dto() =
member val Tracks: Track list = List.empty with get, set
member val CommonTones: CommonTones = Map.empty with get, set
member val CombinationTitle: string = String.Empty with get, set
member val CoercePhrases: bool = true with get, set
member val GenerateDummyDD: bool = false with get, set
member val OnePhrasePerTrack: bool = false with get, set
member val AddTrackNamesToLyrics: bool = true with get, set
let private fromProgramState (state: ProgramState) =
Dto(
Tracks = state.Tracks,
CommonTones = state.CommonTones,
CombinationTitle = state.CombinationTitle,
CoercePhrases = state.CoercePhrases,
GenerateDummyDD = state.GenerateDummyDD,
OnePhrasePerTrack = state.OnePhrasePerTrack,
AddTrackNamesToLyrics = state.AddTrackNamesToLyrics
)
/// Saves a project with the given filename.
let save fileName (state: ProgramState) =
task {
let options = JsonSerializerOptions(WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase)
options.Converters.Add(JsonFSharpConverter())
let project = fromProgramState state
use file = File.Create(fileName)
do! JsonSerializer.SerializeAsync(file, project, options)
}
/// Loads a project from a file.
let load fileName =
task {
let options = JsonSerializerOptions(PropertyNamingPolicy = JsonNamingPolicy.CamelCase)
options.Converters.Add(JsonFSharpConverter())
use file = File.Open(fileName, FileMode.Open)
return! JsonSerializer.DeserializeAsync<Dto>(file, options)
}
/// Converts a project DTO into a program state record.
let toProgramState templates fileName statusMessage (dto: Dto) =
{ Tracks = dto.Tracks
CommonTones = dto.CommonTones
CombinationTitle = dto.CombinationTitle
AddTrackNamesToLyrics = dto.AddTrackNamesToLyrics
CoercePhrases = dto.CoercePhrases
GenerateDummyDD = dto.GenerateDummyDD
OnePhrasePerTrack = dto.OnePhrasePerTrack
Templates = templates
StatusMessage = statusMessage
ReplacementToneEditor = None
ProjectViewActive = true
AudioCombinerProgress = None
ArrangementCombinerProgress = None
OpenProjectFile = Some fileName
EditingTitleTrackIndex = -1
SelectedFileTones = Map.empty }
/// Updates the arrangements in the project with tone names read from the XML files.
let updateToneNames (project: Dto) =
let tracks =
project.Tracks
|> List.map (fun track ->
let arrangements =
track.Arrangements
|> List.map (fun arr ->
match arr.FileName, arr.Data with
| Some fn, Some data when File.Exists(fn) ->
let toneInfo = InstrumentalArrangement.ReadToneNames(fn)
let newData =
let toneNames =
if isNull toneInfo.Changes then
List.empty
else
toneInfo.Names
|> Seq.filter String.notEmpty
|> Seq.toList
let toneReplacements =
(data.ToneReplacements, toneNames)
||> List.fold (fun map replacement ->
if map.ContainsKey replacement then
map
else
map.Add(replacement, -1))
{ data with ToneNames = toneNames; ToneReplacements = toneReplacements }
{ arr with Data = Some newData }
| _ ->
arr)
{ track with Arrangements = arrangements })
project.Tracks <- tracks
/// Returns the names of audio files and arrangement files that do not exist anymore.
let getMissingFiles (project: Dto) =
(([], []), project.Tracks)
||> List.fold (fun state track ->
let missingAudioFiles =
match track.AudioFile with
| Some file when not <| File.Exists(file) ->
file :: (fst state)
| _ ->
fst state
let missingArrangementFiles =
([], track.Arrangements)
||> List.fold (fun missing arr ->
match arr.FileName with
| Some file when not <| File.Exists(file) ->
file :: missing
| _ ->
missing)
missingAudioFiles, (snd state) @ missingArrangementFiles)