Skip to content

Commit d01fc26

Browse files
authored
Merge pull request #1 from thewsoftware/initial
Initial commit
2 parents ce1ff8a + b4c00ce commit d01fc26

13 files changed

+766
-1
lines changed

.gitignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Log files
2+
*.log
3+
4+
# Unit test reports
5+
TEST*.xml
6+
7+
# Generated by MacOS
8+
.DS_Store
9+
10+
# Generated by Windows
11+
Thumbs.db
12+
13+
# Applications
14+
*.app
15+
*.exe
16+
*.war
17+
18+
# Large media files
19+
*.mp4
20+
*.tiff
21+
*.avi
22+
*.flv
23+
*.mov
24+
*.wmv
25+
26+
# Visual Studio files
27+
*.suo
28+
*.user
29+
*.crt
30+
*.key
31+
.vs
32+
bin
33+
obj
34+
packages
35+
36+
launchSettings.json
37+
*.pubxml

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
# sdrfc
2-
SDR Frequency Converter
2+
# SDR# <-> SDR++ Frequency Converter
3+
A lightweight command line tool to convert frequency lists berween SDR# and SDR++ formats,
4+

SDR.sln

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.7.34018.315
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdrfc", "Sdrfc\Sdrfc.csproj", "{57F3A0F6-1A82-44B1-8E89-D82A3F876C51}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdrfcLib", "SdrfcLib\SdrfcLib.csproj", "{9FCD8316-90DB-4036-BF53-35B3A362A902}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{962791A7-50E6-4CEC-A3F8-E7F318548CFD}"
11+
ProjectSection(SolutionItems) = preProject
12+
.gitignore = .gitignore
13+
README.md = README.md
14+
EndProjectSection
15+
EndProject
16+
Global
17+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
18+
Debug|Any CPU = Debug|Any CPU
19+
Release|Any CPU = Release|Any CPU
20+
EndGlobalSection
21+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
22+
{57F3A0F6-1A82-44B1-8E89-D82A3F876C51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{57F3A0F6-1A82-44B1-8E89-D82A3F876C51}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{57F3A0F6-1A82-44B1-8E89-D82A3F876C51}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{57F3A0F6-1A82-44B1-8E89-D82A3F876C51}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{9FCD8316-90DB-4036-BF53-35B3A362A902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{9FCD8316-90DB-4036-BF53-35B3A362A902}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{9FCD8316-90DB-4036-BF53-35B3A362A902}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{9FCD8316-90DB-4036-BF53-35B3A362A902}.Release|Any CPU.Build.0 = Release|Any CPU
30+
EndGlobalSection
31+
GlobalSection(SolutionProperties) = preSolution
32+
HideSolutionNode = FALSE
33+
EndGlobalSection
34+
GlobalSection(ExtensibilityGlobals) = postSolution
35+
SolutionGuid = {32F0CEFF-7821-4226-B014-34B6F8B991CC}
36+
EndGlobalSection
37+
EndGlobal

Sdrfc/Program.cs

+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
using FrequencyManagerCommon;
2+
using FrequencyManagerCommon.Helpers;
3+
using FrequencyManagerCommon.Models;
4+
5+
namespace SdrSharpToSdrPlusPlus;
6+
7+
class Program
8+
{
9+
static void Main(string[] args)
10+
{
11+
const string SdrppDefaultFileName = "frequency_manager_config.json";
12+
const string SdrsharpDefaultFileName = "frequencies.xml";
13+
const string CopyOption = "-c";
14+
const string MergeOption = "-m";
15+
16+
if (args.Length == 0)
17+
{
18+
Help();
19+
}
20+
else
21+
{
22+
var option = isOption(args[0]) ? args[0].Trim().ToLower() : CopyOption;
23+
24+
if (!CopyOption.Equals(option) && !MergeOption.Equals(option))
25+
{
26+
Help();
27+
}
28+
29+
var inputFileName = !isOption(args[0]) ? args[0] : args[1];
30+
31+
var outputFileName = !isOption(args[0])
32+
? (args.Length > 1 ? args[1] : null)
33+
: (args.Length > 2 ? args[2] : null);
34+
35+
using (var sdrpp = new SdrPlusPlusHelper())
36+
using (var sdrsharp = new SdrSharpHelper())
37+
{
38+
var inputFileExt = Path.GetExtension(inputFileName);
39+
40+
if (".json".Equals(inputFileExt.ToLower()))
41+
{
42+
// convert from sdr++ format to sdr#
43+
44+
if (!File.Exists(inputFileName))
45+
{
46+
ErrorAndExit($"File does not exists; {inputFileName}");
47+
}
48+
49+
var inputChannels = sdrpp.LoadFromFile(inputFileName);
50+
51+
if (inputChannels == null || !inputChannels.Any())
52+
{
53+
ErrorAndExit($"Invalid file format; {inputFileName} is not SDR++ frequency file.");
54+
}
55+
56+
outputFileName = outputFileName?.ToLower() ?? SdrsharpDefaultFileName;
57+
58+
var outputChannels = File.Exists(outputFileName)
59+
? sdrsharp.LoadFromFile(outputFileName)
60+
: new List<Channel>();
61+
62+
try
63+
{
64+
using (var frequencyManager = new FrequencyManager(outputChannels))
65+
{
66+
if (File.Exists(outputFileName) && MergeOption.Equals(option))
67+
{
68+
WriteLine($"Merge {inputFileName.ToLower()} ({inputChannels.Count} channels) into {outputFileName.ToLower()} ({outputChannels.Count} channels).");
69+
WriteLine($"Matching by [group name]+[frequency].");
70+
}
71+
else
72+
{
73+
WriteLine($"Copy {inputFileName.ToLower()} ({inputChannels.Count} channels) into {outputFileName.ToLower()}.");
74+
}
75+
76+
(long updated, long added) = CopyOption.Equals(option)
77+
? frequencyManager.Copy(inputChannels)
78+
: frequencyManager.Merge(inputChannels);
79+
80+
WriteLine($"{updated} channels updated, {added} channels added.");
81+
82+
sdrsharp.SaveToFile(frequencyManager.Channels, outputFileName);
83+
}
84+
85+
Exit();
86+
}
87+
catch (Exception ex )
88+
{
89+
ErrorAndExit(ex.Message);
90+
};
91+
}
92+
else if (".xml".Equals(inputFileExt.ToLower()))
93+
{
94+
// convert from sdr# format to sdr++
95+
96+
if (!File.Exists(inputFileName))
97+
{
98+
ErrorAndExit($"File does not exists; {inputFileName}");
99+
}
100+
101+
var inputChannels = sdrsharp.LoadFromFile(inputFileName);
102+
103+
if (inputChannels == null || !inputChannels.Any())
104+
{
105+
ErrorAndExit($"Invalid file format; {inputFileName} is not SDR# frequency file.");
106+
}
107+
108+
outputFileName = outputFileName?.ToLower() ?? SdrppDefaultFileName;
109+
110+
var outputChannels = File.Exists(outputFileName)
111+
? sdrpp.LoadFromFile(outputFileName)
112+
: new List<Channel>();
113+
114+
try
115+
{
116+
using (var frequencyManager = new FrequencyManager(outputChannels))
117+
{
118+
if (File.Exists(outputFileName) && MergeOption.Equals(option))
119+
{
120+
WriteLine($"Merge {inputFileName.ToLower()} ({inputChannels.Count} channels) into {outputFileName.ToLower()} ({outputChannels.Count} channels).");
121+
WriteLine($"Matching by [group name]+[frequency].");
122+
}
123+
else
124+
{
125+
WriteLine($"Copy {inputFileName.ToLower()} ({inputChannels.Count} channels) into {outputFileName.ToLower()}.");
126+
}
127+
128+
(long updated, long added) = CopyOption.Equals(option)
129+
? frequencyManager.Copy(inputChannels)
130+
: frequencyManager.Merge(inputChannels);
131+
132+
WriteLine($"{updated} channels updated, {added} channels added.");
133+
134+
sdrpp.SaveToFile(frequencyManager.Channels, outputFileName);
135+
}
136+
137+
Exit();
138+
}
139+
catch (Exception ex)
140+
{
141+
ErrorAndExit(ex.Message);
142+
};
143+
}
144+
else
145+
{
146+
Help();
147+
}
148+
}
149+
}
150+
}
151+
152+
static private bool isOption(string text)
153+
{
154+
return text != null && text.Length == 2 && text.StartsWith("-");
155+
}
156+
157+
static private void Help()
158+
{
159+
Console.WriteLine("==============================================================================");
160+
Console.WriteLine($" SDR#/SRD++ frequency file converter https://github.com/thewsoftware ");
161+
Console.WriteLine("==============================================================================");
162+
Console.WriteLine("");
163+
Console.WriteLine("Usage: sdrfc [-option] [drive:][path][inputfilename] [drive:][path][outputfilename]");
164+
Console.WriteLine("");
165+
Console.WriteLine("Options:");
166+
Console.WriteLine("-c\tCopy channels from input file to output file, overwrite the output file (default).");
167+
Console.WriteLine("-m\tMerge channels from input file to output file, save the result into the output file.");
168+
Console.WriteLine("");
169+
Console.WriteLine("Convert frequency channels from one format to another. Auto-detect input and output file formats.");
170+
Console.WriteLine("Create output file if it doesn't exist. If output file does exist and '-m' option is selected");
171+
Console.WriteLine("then frequency channels from input file are merged into the output file and saved.");
172+
Console.WriteLine("");
173+
Exit();
174+
}
175+
176+
static private void Exit()
177+
{
178+
Environment.Exit(0);
179+
}
180+
181+
static private void ErrorAndExit(string message)
182+
{
183+
WriteLine($"Error: {message}");
184+
Environment.Exit(-1);
185+
}
186+
187+
static private void WriteLine(string text)
188+
{
189+
Console.WriteLine($"[SDRFC] {text}");
190+
}
191+
}

Sdrfc/Sdrfc.csproj

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<Version>1.0.0.1</Version>
9+
<Company>The WSoftware</Company>
10+
<Authors>Yuriy Shcherbakov</Authors>
11+
<Product>SDR Frequency Converter</Product>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\SdrfcLib\SdrfcLib.csproj" />
20+
</ItemGroup>
21+
22+
</Project>
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using FrequencyManagerCommon.Models;
2+
using System.Xml.Linq;
3+
4+
namespace FrequencyManagerCommon.Extensions
5+
{
6+
public static class ChannelExtensions
7+
{
8+
public static void MergeTo(this IEnumerable<Channel> src, IEnumerable<Channel> dst)
9+
{
10+
if (src == null || dst == null) return;
11+
12+
foreach (var channel in src)
13+
{
14+
}
15+
}
16+
17+
public static Channel? FindChannel(this IEnumerable<Channel> channels, Channel channel)
18+
{
19+
if (channels == null || channel == null) return null;
20+
21+
return channels.FirstOrDefault(o =>
22+
o.Frequency == channel.Frequency &&
23+
o.GroupName.Equals(channel.GroupName, StringComparison.CurrentCultureIgnoreCase));
24+
}
25+
26+
public static bool SameAs(this Channel src, Channel dst)
27+
{
28+
if (src == null || dst == null) return false;
29+
30+
return src.GroupName.Equals(dst.GroupName, StringComparison.CurrentCultureIgnoreCase) &&
31+
src.Name.Equals(dst.Name, StringComparison.CurrentCultureIgnoreCase) &&
32+
src.Modulation.Equals(dst.Modulation, StringComparison.CurrentCultureIgnoreCase) &&
33+
src.Frequency == dst.Frequency &&
34+
src.Bandwidth == dst.Bandwidth &&
35+
src.Shift == dst.Shift;
36+
}
37+
38+
public static void Update(this Channel dst, Channel src)
39+
{
40+
dst.Name = src.Name;
41+
dst.Modulation = src.Modulation;
42+
dst.Bandwidth = src.Bandwidth;
43+
dst.Shift = src.Shift;
44+
}
45+
46+
public static Channel Clone(this Channel channel)
47+
{
48+
return new Channel
49+
{
50+
IsFavorite = channel.IsFavorite,
51+
Name = channel.Name,
52+
GroupName = channel.GroupName,
53+
Frequency = channel.Frequency,
54+
Bandwidth = channel.Bandwidth,
55+
Shift = channel.Shift,
56+
Modulation = channel.Modulation,
57+
};
58+
}
59+
60+
public static (bool, bool) Merge(this List<Channel> channels, Channel channel)
61+
{
62+
var isUpdated = false;
63+
var isAdded = false;
64+
65+
var existing = channels.FindChannel(channel);
66+
67+
if (existing == null)
68+
{
69+
channels.Add(channel);
70+
isAdded = true;
71+
}
72+
else
73+
{
74+
if (!existing.SameAs(channel))
75+
{
76+
existing.Update(channel);
77+
isUpdated = true;
78+
}
79+
}
80+
81+
return (isUpdated, isAdded);
82+
}
83+
84+
}
85+
}

0 commit comments

Comments
 (0)