Skip to content

Commit fe8e992

Browse files
committed
FIX: comma should be escaped in filename when writing to .osu
1 parent ca8a39d commit fe8e992

3 files changed

Lines changed: 101 additions & 74 deletions

File tree

BmsToOsu/Converter/Osu.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static (string, HashSet<string> fileToCp) ToOsuBeatMap(
6969
if (!string.IsNullOrEmpty(bg))
7070
{
7171
fileToCp.Add(Path.GetFileName(bg));
72-
bd.AppendLine($"0,0,\"{bg}\",0,0");
72+
bd.AppendLine($"0,0,\"{bg.Escape()}\",0,0");
7373
}
7474

7575
// bga
@@ -103,12 +103,12 @@ public static (string, HashSet<string> fileToCp) ToOsuBeatMap(
103103

104104
if (vExt is not (".wmv" or ".mpg" or ".avi" or ".mp4" or ".webm" or ".mkv"))
105105
{
106-
bd.AppendLine($"Sprite,{layer},CentreRight,\"{bga.File}\",600,240");
106+
bd.AppendLine($"Sprite,{layer},CentreRight,\"{bga.File.Escape()}\",600,240");
107107
bd.AppendLine($" F,0,{(int)bga.StartTime},{(int)endTime},1");
108108
}
109109
else
110110
{
111-
bd.AppendLine($"Video,{(int)bga.StartTime},\"{bga.File}\"");
111+
bd.AppendLine($"Video,{(int)bga.StartTime},\"{bga.File.Escape()}\"");
112112
}
113113

114114
if (!string.IsNullOrEmpty(bga.File)) fileToCp.Add(bga.File);
@@ -117,7 +117,7 @@ public static (string, HashSet<string> fileToCp) ToOsuBeatMap(
117117
// sound effect
118118
foreach (var sfx in data.SoundEffects)
119119
{
120-
bd.AppendLine($"Sample,{(int)sfx.StartTime},0,\"{sfx.SoundFile}\",100");
120+
bd.AppendLine($"Sample,{(int)sfx.StartTime},0,\"{sfx.SoundFile.Escape()}\",100");
121121

122122
fileToCp.Add(sfx.SoundFile);
123123
}
@@ -126,7 +126,7 @@ public static (string, HashSet<string> fileToCp) ToOsuBeatMap(
126126
{
127127
foreach (var hitObj in data.HitObject.Values.SelectMany(obj => obj))
128128
{
129-
bd.AppendLine($"Sample,{(int)hitObj.StartTime},0,\"{hitObj.HitSoundFile}\",100");
129+
bd.AppendLine($"Sample,{(int)hitObj.StartTime},0,\"{hitObj.HitSoundFile.Escape()}\",100");
130130
}
131131
}
132132

@@ -182,8 +182,8 @@ public static (string, HashSet<string> fileToCp) ToOsuBeatMap(
182182

183183
bd.AppendLine(
184184
obj.IsLongNote
185-
? $"{xPos},192,{(int)obj.StartTime},{objType},0,{(int)obj.EndTime}:0:0:0:0:{hitSound}"
186-
: $"{xPos},192,{(int)obj.StartTime},{1 << 0},0,0:0:0:0:{hitSound}");
185+
? $"{xPos},192,{(int)obj.StartTime},{objType},0,{(int)obj.EndTime}:0:0:0:0:{hitSound.Escape()}"
186+
: $"{xPos},192,{(int)obj.StartTime},{1 << 0},0,0:0:0:0:{hitSound.Escape()}");
187187
}
188188
}
189189

BmsToOsu/Program.cs

Lines changed: 89 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
using BmsToOsu;
33
using BmsToOsu.Converter;
44
using BmsToOsu.Entity;
5+
using BmsToOsu.Utils;
56
using CommandLine;
7+
using CommandLine.Text;
68
using log4net;
79

810
Logger.Config();
@@ -14,91 +16,111 @@
1416
".bms", ".bml", ".bme", ".bmx"
1517
};
1618

17-
Parser.Default.ParseArguments<Option>(args)
18-
.WithParsed(o =>
19+
var parser = new Parser(with =>
20+
{
21+
with.AutoVersion = false;
22+
with.AutoHelp = true;
23+
with.HelpWriter = null;
24+
});
25+
26+
var result = parser.ParseArguments<Option>(args);
27+
28+
result.WithParsed(o =>
29+
{
30+
var osz = o.OutPath + ".osz";
31+
32+
// avoid removing existing folder
33+
if (Directory.Exists(o.OutPath) && !o.NoRemove)
1934
{
20-
var osz = o.OutPath + ".osz";
35+
logger.Warn($"{o.OutPath} exists, `--no-remove` will be appended to the parameter");
36+
o.NoRemove = true;
37+
}
2138

22-
// avoid removing existing folder
23-
if (Directory.Exists(o.OutPath) && !o.NoRemove)
24-
{
25-
logger.Warn($"{o.OutPath} exists, `--no-remove` will be appended to the parameter");
26-
o.NoRemove = true;
27-
}
39+
// avoid removing after generation
40+
if (o.NoZip && !o.NoRemove)
41+
{
42+
logger.Warn("`--no-remove` is appended to the parameter");
43+
o.NoRemove = true;
44+
}
45+
46+
// avoid duplication
47+
if (File.Exists(osz))
48+
{
49+
logger.Warn($"{osz} exists, ignoring...");
50+
return;
51+
}
2852

29-
// avoid removing after generation
30-
if (o.NoZip && !o.NoRemove)
53+
var ftc = new HashSet<string>();
54+
55+
var bms = Directory
56+
.GetFiles(o.InputPath, "*.*", SearchOption.AllDirectories)
57+
.Where(f => availableBmsExt.Any(ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase)));
58+
59+
Parallel.ForEach(bms, fp =>
60+
{
61+
logger.Info($"Processing {fp}");
62+
63+
var dir = Path.GetDirectoryName(fp) ?? "";
64+
65+
BmsFileData data;
66+
67+
try
3168
{
32-
logger.Warn("`--no-remove` is appended to the parameter");
33-
o.NoRemove = true;
69+
data = BmsFileData.FromFile(fp);
3470
}
35-
36-
// avoid duplication
37-
if (File.Exists(osz))
71+
catch (InvalidDataException)
3872
{
39-
logger.Warn($"{osz} exists, ignoring...");
4073
return;
4174
}
4275

43-
var ftc = new HashSet<string>();
44-
45-
var bms = Directory
46-
.GetFiles(o.InputPath, "*.*", SearchOption.AllDirectories)
47-
.Where(f => availableBmsExt.Any(ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase)));
76+
var (osu, ftc2) = data.ToOsuBeatMap(dir);
4877

49-
Parallel.ForEach(bms, fp =>
78+
lock (ftc)
5079
{
51-
logger.Info($"Processing {fp}");
52-
53-
var dir = Path.GetDirectoryName(fp) ?? "";
80+
foreach (var c in ftc2) ftc.Add(Path.Join(dir, c));
81+
}
5482

55-
BmsFileData data;
83+
var dest = dir.Replace(o.InputPath, o.OutPath);
5684

57-
try
58-
{
59-
data = BmsFileData.FromFile(fp);
60-
}
61-
catch (InvalidDataException)
62-
{
63-
return;
64-
}
85+
Directory.CreateDirectory(dest);
86+
File.WriteAllText(Path.Join(dest, Path.GetFileNameWithoutExtension(fp) + ".osu"), osu);
87+
});
6588

66-
var (osu, ftc2) = data.ToOsuBeatMap(dir);
89+
if (!o.NoCopy)
90+
{
91+
logger.Info("Copying sound files");
92+
Parallel.ForEach(ftc, c =>
93+
{
94+
var dest = c.Replace(o.InputPath, o.OutPath);
95+
dest = Path.Join(Path.GetDirectoryName(dest), Path.GetFileName(dest).Escape());
6796

68-
lock (ftc)
97+
if (!File.Exists(dest))
6998
{
70-
foreach (var c in ftc2) ftc.Add(Path.Join(dir, c));
99+
File.Copy(c, dest, true);
71100
}
72-
73-
var dest = dir.Replace(o.InputPath, o.OutPath);
74-
75-
Directory.CreateDirectory(dest);
76-
File.WriteAllText(Path.Join(dest, Path.GetFileNameWithoutExtension(fp) + ".osu"), osu);
77101
});
102+
}
78103

79-
if (!o.NoCopy)
80-
{
81-
logger.Info("Copying sound files");
82-
Parallel.ForEach(ftc, c =>
83-
{
84-
var dest = c.Replace(o.InputPath, o.OutPath);
85-
86-
if (!File.Exists(dest))
87-
{
88-
File.Copy(c, dest, true);
89-
}
90-
});
91-
}
104+
if (!o.NoZip && Directory.Exists(o.OutPath))
105+
{
106+
logger.Info($"Creating {osz}");
107+
ZipFile.CreateFromDirectory(o.OutPath, osz, CompressionLevel.Fastest, false);
108+
}
92109

93-
if (!o.NoZip && Directory.Exists(o.OutPath))
94-
{
95-
logger.Info($"Creating {osz}");
96-
ZipFile.CreateFromDirectory(o.OutPath, osz, CompressionLevel.Fastest, false);
97-
}
110+
if (!o.NoRemove)
111+
{
112+
logger.Info($"Removing {o.OutPath}");
113+
Directory.Delete(o.OutPath, true);
114+
}
115+
});
98116

99-
if (!o.NoRemove)
100-
{
101-
logger.Info($"Removing {o.OutPath}");
102-
Directory.Delete(o.OutPath, true);
103-
}
104-
});
117+
result.WithNotParsed(errs =>
118+
{
119+
var helpText = HelpText.AutoBuild(result, h =>
120+
{
121+
h.AutoHelp = true;
122+
h.AutoVersion = false;
123+
return HelpText.DefaultParsingErrorsHandler(result, h);
124+
}, e => e);
125+
Console.WriteLine(helpText);
126+
});

BmsToOsu/Utils/PathExt.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ public static Dictionary<string, string> FixSoundPath(this Dictionary<string, st
3131
.Where(kv => !string.IsNullOrEmpty(kv.Value))
3232
);
3333
}
34+
35+
public static string Escape(this string path)
36+
{
37+
return path.Replace(",", "-comma-");
38+
}
3439
}

0 commit comments

Comments
 (0)