//****************************************************************************************************** // Program.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 06/28/2011 - J. Ritchie Carroll // Generated original version of source code. // 12/13/2012 - Starlynn Danyelle Gilliam // Modified Header // //****************************************************************************************************** using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using GSF; using GSF.Configuration; using GSF.Data; using GSF.IO; using GSF.Media; using GSF.Units; namespace UpdateWAVMetaData { class Program { static int Main(string[] args) { // System settings ConfigurationFile configFile = ConfigurationFile.Current; CategorizedSettingsElementCollection systemSettings = configFile.Settings["systemSettings"]; systemSettings.Add("NodeID", Guid.NewGuid().ToString(), "Unique Node ID"); Guid nodeID = systemSettings["NodeID"].ValueAs(); bool useMemoryCache = systemSettings["UseMemoryCache"].ValueAsBoolean(false); string connectionString = systemSettings["ConnectionString"].Value; string nodeIDQueryString = null; string parameterizedQuery; int protocolID, signalTypePMID, signalTypePAID; // Define guid with query string delimiters according to database needs Dictionary settings = connectionString.ParseKeyValuePairs(); string setting; if (settings.TryGetValue("Provider", out setting)) { // Check if provider is for Access since it uses braces as Guid delimiters if (setting.StartsWith("Microsoft.Jet.OLEDB", StringComparison.OrdinalIgnoreCase)) nodeIDQueryString = "{" + nodeID + "}"; } if (string.IsNullOrWhiteSpace(nodeIDQueryString)) nodeIDQueryString = "'" + nodeID + "'"; using (AdoDataConnection database = new AdoDataConnection("systemSettings")) { IDbConnection connection = database.Connection; if (Convert.ToInt32(connection.ExecuteScalar("SELECT COUNT(*) FROM Protocol WHERE Acronym='WAV'")) == 0) { if (database.IsSQLServer || database.IsJetEngine) connection.ExecuteNonQuery("INSERT INTO Protocol(Acronym, Name, [Type], Category, AssemblyName, TypeName) VALUES('WAV', 'Wave Form Input Adapter', 'Frame', 'Audio', 'WavInputAdapter.dll', 'WavInputAdapter.WavInputAdapter')"); else connection.ExecuteNonQuery("INSERT INTO Protocol(Acronym, Name, Type, Category, AssemblyName, TypeName) VALUES('WAV', 'Wave Form Input Adapter', 'Frame', 'Audio', 'WavInputAdapter.dll', 'WavInputAdapter.WavInputAdapter')"); } protocolID = Convert.ToInt32(connection.ExecuteScalar("SELECT ID FROM Protocol WHERE Acronym='WAV'")); // Typically these values should be defined as analogs, however, we use a voltage magnitude signal type // since these types of values can be better graphed with auto-scaling in the visualization tools signalTypePMID = Convert.ToInt32(connection.ExecuteScalar("SELECT ID FROM SignalType WHERE Acronym='VPHM'")); signalTypePAID = Convert.ToInt32(connection.ExecuteScalar("SELECT ID FROM SignalType WHERE Acronym='VPHA'")); string pathRoot = FilePath.GetDirectoryName((args.Length > 0) ? args[0] : systemSettings["MusicDirectory"].Value); string sourcePath = Path.Combine(pathRoot, "*" + Path.DirectorySeparatorChar + "*.wav"); foreach (string sourceFileName in FilePath.GetFileList(sourcePath)) { WaveFile sourceWave; string fileName = FilePath.GetFileName(sourceFileName); char[] invalidChars = { '\'', '[', ']', '(', ')', ',', '-', '.' }; Console.WriteLine("Loading metadata for \"{0}\"...\r\n", fileName); sourceWave = WaveFile.Load(sourceFileName, false); fileName = FilePath.GetFileNameWithoutExtension(fileName).RemoveDuplicateWhiteSpace().RemoveCharacters(invalidChars.Contains).Trim(); string acronym = fileName.Replace(' ', '_').ToUpper() + "_" + (int)(sourceWave.SampleRate / SI.Kilo) + "KHZ"; string name = GenerateSongName(sourceWave, fileName); Console.WriteLine(" Acronym = {0}", acronym); Console.WriteLine(" Name = {0}", name); Console.WriteLine(""); // Check to see if device exists if (Convert.ToInt32(connection.ExecuteScalar(database.ParameterizedQueryString("SELECT COUNT(*) FROM Device WHERE Acronym = {0}", "acronym"), acronym)) == 0) { parameterizedQuery = database.ParameterizedQueryString("INSERT INTO Device(NodeID, Acronym, Name, ProtocolID, FramesPerSecond, " + "MeasurementReportingInterval, ConnectionString, Enabled) VALUES(" + nodeIDQueryString + ", {0}, {1}, {2}, {3}, {4}, {5}, {6})", "acronym", "name", "protocolID", "framesPerSecond", "measurementReportingInterval", "connectionString", "enabled"); // Insert new device record connection.ExecuteNonQuery(parameterizedQuery, acronym, name, protocolID, sourceWave.SampleRate, 1000000, $"wavFileName={FilePath.GetAbsolutePath(sourceFileName)}; connectOnDemand=true; outputSourceIDs={acronym}; memoryCache={useMemoryCache}", database.Bool(true)); int deviceID = Convert.ToInt32(connection.ExecuteScalar(database.ParameterizedQueryString("SELECT ID FROM Device WHERE Acronym = {0}", "acronym"), acronym)); string pointTag; int lastPhasorIndex = 0; int phasorIndex = 1; // Add a measurement for each defined wave channel for (int i = 0; i < sourceWave.Channels; i++) { int index = i + 1; int signalTypeID = index % 2 == 0 ? signalTypePAID : signalTypePMID; if (i > 0 && i % 2 == 0) phasorIndex++; if (lastPhasorIndex != phasorIndex) { lastPhasorIndex = phasorIndex; parameterizedQuery = database.ParameterizedQueryString("INSERT INTO Phasor(DeviceID, Label, Type, Phase, SourceIndex) VALUES ({0}, {1}, 'V', '+', {2})", "deviceID", "label", "sourceIndex"); // Insert new phasor record connection.ExecuteNonQuery(parameterizedQuery, (object)deviceID, acronym, phasorIndex); } string signalSuffix = index % 2 == 0 ? "-PA" : "-PM"; pointTag = acronym + ":WAVA" + index; parameterizedQuery = database.ParameterizedQueryString("INSERT INTO Measurement(DeviceID, PointTag, SignalTypeID, PhasorSourceIndex, SignalReference, Description, " + "Enabled) VALUES({0}, {1}, {2}, {3}, {4}, {5}, {6})", "deviceID", "pointTag", "signalTypeID", "phasorSourceIndex", "signalReference", "description", "enabled"); // Insert new measurement record connection.ExecuteNonQuery(parameterizedQuery, (object)deviceID, pointTag, signalTypeID, phasorIndex, acronym + signalSuffix + phasorIndex, name + " - channel " + phasorIndex, database.Bool(true)); //Convert.ToInt32(connection.ExecuteScalar(database.ParameterizedQueryString("SELECT PointID FROM Measurement WHERE PointTag = {0}", "pointTag"), pointTag)); } // Disable all non analog measurements that may be associated with this device connection.ExecuteNonQuery(database.ParameterizedQueryString("UPDATE Measurement SET Enabled = {0} WHERE DeviceID = {1} AND NOT SignalTypeID IN ({2}, {3})", "enabled", "deviceID", "signalTypePAID", "signalTypePMID"), database.Bool(false), deviceID, signalTypePAID, signalTypePMID); } } } return 0; } private static string GenerateSongName(WaveFile song, string fileName) { Dictionary infoStrings = song.InfoStrings; string title = GetInfoProperty(infoStrings, "INAM", fileName).Trim(); string artist = GetInfoProperty(infoStrings, "IART", "").Trim(); string track = GetInfoProperty(infoStrings, "ITRK", "").Trim(); string length = " " + song.AudioLength.ToString("hh\\:mm\\:ss"); string sampleRate = " @ " + (song.SampleRate / SI.Kilo).ToString("0.00kHz"); if (!string.IsNullOrEmpty(artist)) { if (string.Compare(artist, "Unknown artist", true) == 0) artist = fileName; artist = ", " + artist; } if (!string.IsNullOrEmpty(track)) track = " #" + track + ","; string suffix; if (string.IsNullOrEmpty(track) && string.IsNullOrEmpty(artist)) suffix = sampleRate; else suffix = " -" + track + length + sampleRate; if (title.Length + suffix.Length > 200) return title.TruncateRight(199 - suffix.Length) + " " + suffix; if (title.Length + artist.Length + suffix.Length > 200) return title + artist.TruncateRight(200 - title.Length - suffix.Length) + " " + suffix; return title + artist + suffix; } private static string GetInfoProperty(Dictionary infoStrings, string key, string defaultValue) { string value; if (infoStrings.TryGetValue(key, out value)) { value = value.Trim().RemoveDuplicateWhiteSpace(); if (string.IsNullOrEmpty(value)) return defaultValue; return value; } return defaultValue; } } }