Initial commit — M3U playlist tool with MP3/AAC encoding
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
_ReSharper*/
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
.vs/
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
//
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
//
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("")]
|
||||||
|
[assembly: AssemblyCopyright("")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
//
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
|
//
|
||||||
|
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||||
|
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||||
|
//
|
||||||
|
// Use the attributes below to control which key is used for signing.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// (*) If no key is specified, the assembly is not signed.
|
||||||
|
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||||
|
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||||
|
// a key.
|
||||||
|
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||||
|
// following processing occurs:
|
||||||
|
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||||
|
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||||
|
// in the KeyFile is installed into the CSP and used.
|
||||||
|
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||||
|
// When specifying the KeyFile, the location of the KeyFile should be
|
||||||
|
// relative to the project output directory which is
|
||||||
|
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||||
|
// located in the project directory, you would specify the AssemblyKeyFile
|
||||||
|
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||||
|
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||||
|
// documentation for more information on this.
|
||||||
|
//
|
||||||
|
|
||||||
|
[assembly: AssemblyDelaySign(false)]
|
||||||
|
[assembly: AssemblyKeyFile("")]
|
||||||
|
[assembly: AssemblyKeyName("")]
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,58 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
//
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
//
|
||||||
|
[assembly: AssemblyTitle("")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("")]
|
||||||
|
[assembly: AssemblyCopyright("")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
//
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
|
//
|
||||||
|
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||||
|
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||||
|
//
|
||||||
|
// Use the attributes below to control which key is used for signing.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// (*) If no key is specified, the assembly is not signed.
|
||||||
|
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||||
|
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||||
|
// a key.
|
||||||
|
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||||
|
// following processing occurs:
|
||||||
|
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||||
|
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||||
|
// in the KeyFile is installed into the CSP and used.
|
||||||
|
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||||
|
// When specifying the KeyFile, the location of the KeyFile should be
|
||||||
|
// relative to the project output directory which is
|
||||||
|
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||||
|
// located in the project directory, you would specify the AssemblyKeyFile
|
||||||
|
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||||
|
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||||
|
// documentation for more information on this.
|
||||||
|
//
|
||||||
|
[assembly: AssemblyDelaySign(false)]
|
||||||
|
[assembly: AssemblyKeyFile("")]
|
||||||
|
[assembly: AssemblyKeyName("")]
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class DoNothingProgressCallback : IProgressCallback
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
public void Begin(int minimum, int maximum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback, without setting the range
|
||||||
|
/// </summary>
|
||||||
|
public void Begin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to reset the range in the
|
||||||
|
/// progress callback
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
public void SetRange(int minimum, int maximum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to update the progress text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The text.</param>
|
||||||
|
public void SetText(string text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
public void StepTo(int val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to step the progress meter to a
|
||||||
|
/// particular value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
public void Increment(int val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this property is true, then you should abort work
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// <c>true</c> if this instance is aborting; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
public bool IsAborting
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to finalize the progress meter
|
||||||
|
/// </summary>
|
||||||
|
public void End()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This defines an interface which can be implemented by UI elements
|
||||||
|
/// which indicate the progress of a long operation.
|
||||||
|
/// (See ProgressWindow for a typical implementation)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Based on http://www.codeproject.com/cs/miscctrl/progressdialog.asp </remarks>
|
||||||
|
public interface IProgressCallback
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
void Begin(int minimum, int maximum);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback, without setting the range
|
||||||
|
/// </summary>
|
||||||
|
void Begin();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to reset the range in the
|
||||||
|
/// progress callback
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
void SetRange(int minimum, int maximum);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to update the progress text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The text.</param>
|
||||||
|
void SetText(String text);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
void StepTo(int val);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to step the progress meter to a
|
||||||
|
/// particular value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
void Increment(int val);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this property is true, then you should abort work
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// <c>true</c> if this instance is aborting; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
bool IsAborting
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to finalize the progress meter
|
||||||
|
/// </summary>
|
||||||
|
void End();
|
||||||
|
}
|
||||||
@@ -0,0 +1,399 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2005, Marc Clifton
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of MyXaml nor the names of its contributors may be
|
||||||
|
used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Clifton.Collections.Generic
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class KeyedList<K, V> : IDictionary<K, V>, IList<KeyValuePair<K, V>>
|
||||||
|
{
|
||||||
|
private Dictionary<K, V> objectTable = new Dictionary<K, V>();
|
||||||
|
private List<KeyValuePair<K, V>> objectList = new List<KeyValuePair<K, V>>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns false.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsReadOnly
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of entries in the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return objectList.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the value at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index.</param>
|
||||||
|
/// <returns>The value.</returns>
|
||||||
|
public KeyValuePair<K, V> this[int idx]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectList[idx];
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectList[idx] = value;
|
||||||
|
objectTable[value.Key] = value.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the value associated with the specified key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <returns>The associated value.</returns>
|
||||||
|
public virtual V this[K key]
|
||||||
|
{
|
||||||
|
get { return objectTable[key]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (objectTable.ContainsKey(key))
|
||||||
|
{
|
||||||
|
objectTable[key] = value;
|
||||||
|
objectList[IndexOf(key)] = new KeyValuePair<K, V>(key, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an unordered list of keys.
|
||||||
|
/// This collection refers back to the keys in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<K> Keys
|
||||||
|
{
|
||||||
|
get { return objectTable.Keys; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an unordered list of values.
|
||||||
|
/// This collection refers back to the values in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<V> Values
|
||||||
|
{
|
||||||
|
get { return objectTable.Values; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the ordered list of keys.
|
||||||
|
/// This is a copy of the keys in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public List<K> OrderedKeys
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<K> retList = new List<K>();
|
||||||
|
|
||||||
|
foreach (KeyValuePair<K, V> kvp in objectList)
|
||||||
|
{
|
||||||
|
retList.Add(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the ordered list of values.
|
||||||
|
/// This is a copy of the values in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public List<V> OrderedValues
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<V> retList = new List<V>();
|
||||||
|
|
||||||
|
foreach (KeyValuePair<K, V> kvp in objectList)
|
||||||
|
{
|
||||||
|
retList.Add(kvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the key at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index.</param>
|
||||||
|
/// <returns>The key at the index.</returns>
|
||||||
|
public K GetKey(int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectList[idx].Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index.</param>
|
||||||
|
/// <returns>The value at the index.</returns>
|
||||||
|
public V GetValue(int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectList[idx].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the index of a particular key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key to find the index of.</param>
|
||||||
|
/// <returns>The index of the key, or -1 if not found.</returns>
|
||||||
|
public int IndexOf(K key)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < objectList.Count; i++)
|
||||||
|
{
|
||||||
|
if (objectList[i].Key.Equals(key))
|
||||||
|
{
|
||||||
|
ret = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given the key-value pair, find the index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The key-value pair.</param>
|
||||||
|
/// <returns>The index, or -1 if not found.</returns>
|
||||||
|
public int IndexOf(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
return IndexOf(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Dictionary class backing the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<K, V> ObjectTable
|
||||||
|
{
|
||||||
|
get { return objectTable; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all entries in the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
objectTable.Clear();
|
||||||
|
objectList.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test if the KeyedList contains the key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <returns>True if the key is found.</returns>
|
||||||
|
public bool ContainsKey(K key)
|
||||||
|
{
|
||||||
|
return objectTable.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test if the KeyedList contains the key in the key-value pair.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The key-value pair.</param>
|
||||||
|
/// <returns>True if the key is found.</returns>
|
||||||
|
public bool Contains(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
return objectTable.ContainsKey(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a key-value pair to the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <param name="value">The associated value.</param>
|
||||||
|
public void Add(K key, V value)
|
||||||
|
{
|
||||||
|
objectTable.Add(key, value);
|
||||||
|
objectList.Add(new KeyValuePair<K, V>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a key-value pair to the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The KeyValuePair instance.</param>
|
||||||
|
public void Add(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
Add(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy the entire key-value pairs to the KeyValuePair array, starting
|
||||||
|
/// at the specified index of the target array. The array is populated
|
||||||
|
/// as an ordered list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvpa">The KeyValuePair array.</param>
|
||||||
|
/// <param name="idx">The position to start the copy.</param>
|
||||||
|
public void CopyTo(KeyValuePair<K, V>[] kvpa, int idx)
|
||||||
|
{
|
||||||
|
objectList.CopyTo(kvpa, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Insert the key-value at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The zero-based insert point.</param>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
public void Insert(int idx, K key, V value)
|
||||||
|
{
|
||||||
|
if ((idx < 0) || (idx > Count))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectTable.Add(key, value);
|
||||||
|
objectList.Insert(idx, new KeyValuePair<K, V>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Insert the key-value pair at the specified index location.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The key.</param>
|
||||||
|
/// <param name="kvp">The value.</param>
|
||||||
|
public void Insert(int idx, KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
if ((idx < 0) || (idx > Count))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectTable.Add(kvp.Key, kvp.Value);
|
||||||
|
objectList.Insert(idx, kvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the entry.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key identifying the key-value pair.</param>
|
||||||
|
/// <returns>True if removed.</returns>
|
||||||
|
public bool Remove(K key)
|
||||||
|
{
|
||||||
|
bool found = objectTable.Remove(key);
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
objectList.RemoveAt(IndexOf(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the key in the specified KeyValuePair instance. The Value
|
||||||
|
/// property is ignored.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The key-value identifying the entry.</param>
|
||||||
|
/// <returns>True if removed.</returns>
|
||||||
|
public bool Remove(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
return Remove(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the entry at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index to the entry to be removed.</param>
|
||||||
|
public void RemoveAt(int idx)
|
||||||
|
{
|
||||||
|
if ((idx < 0) || (idx >= Count))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectTable.Remove(objectList[idx].Key);
|
||||||
|
objectList.RemoveAt(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempt to get the value, given the key, without throwing an exception if not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key indentifying the entry.</param>
|
||||||
|
/// <param name="val">The value, if found.</param>
|
||||||
|
/// <returns>True if found.</returns>
|
||||||
|
public bool TryGetValue(K key, out V val)
|
||||||
|
{
|
||||||
|
return objectTable.TryGetValue(key, out val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an ordered System.Collections KeyValuePair objects.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return objectList.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an ordered KeyValuePair enumerator.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerator<KeyValuePair<K, V>> IEnumerable<KeyValuePair<K, V>>.GetEnumerator()
|
||||||
|
{
|
||||||
|
return objectList.GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class LongestCommonSubstrings
|
||||||
|
{
|
||||||
|
//def longest_common_substrings(S, T):
|
||||||
|
// maks = 0 # length of longest match
|
||||||
|
// ret = Set([""]) # the longest matches we have found
|
||||||
|
// last = {} # length of matches ending at S[i-1] and
|
||||||
|
// next = {} # at S[i] for T[0]...T[n-1]
|
||||||
|
// for i in xrange(len(S)):
|
||||||
|
// for j in xrange(len(T)):
|
||||||
|
// if S[i] == T[j]:
|
||||||
|
// if j-1 in last:
|
||||||
|
// next[j] = last[j-1] + 1
|
||||||
|
// else:
|
||||||
|
// next[j] = 1
|
||||||
|
// if next[j] > maks:
|
||||||
|
// maks = next[j]
|
||||||
|
// ret = Set()
|
||||||
|
// if next[j] == maks:
|
||||||
|
// ret.add(S[i-maks+1:i+1]) # equals T[j-maks+1:j+1]
|
||||||
|
// last = next
|
||||||
|
// next = {}
|
||||||
|
// return ret
|
||||||
|
|
||||||
|
public static List<string> GetLongestSubstring(string s, string t)
|
||||||
|
{
|
||||||
|
int maks = 0;
|
||||||
|
List<string> ret = new List<string>();
|
||||||
|
Dictionary<int, int> last = new Dictionary<int, int>();
|
||||||
|
Dictionary<int, int> next = new Dictionary<int, int>();
|
||||||
|
for (int i = 0; i < s.Length; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < t.Length; j++)
|
||||||
|
{
|
||||||
|
if (s[i] == t[j])
|
||||||
|
{
|
||||||
|
if (last.ContainsKey(j-1))
|
||||||
|
next[j] = last[j - 1] + 1;
|
||||||
|
else
|
||||||
|
next[j] = 1;
|
||||||
|
|
||||||
|
if (next[j] > maks)
|
||||||
|
{
|
||||||
|
maks = next[j];
|
||||||
|
ret.Clear();
|
||||||
|
}
|
||||||
|
if (next[j] == maks)
|
||||||
|
ret.Add(s.Substring(i - maks + 1, maks));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last = next;
|
||||||
|
next = new Dictionary<int, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LongestCommonSequence<T> where T : IEnumerable
|
||||||
|
{
|
||||||
|
public enum BackTracking {
|
||||||
|
NEITHER,
|
||||||
|
UP,
|
||||||
|
LEFT,
|
||||||
|
UP_AND_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ConsecutiveMeasure(int k)
|
||||||
|
{
|
||||||
|
//f(k)=k*a - b;
|
||||||
|
return k*k;
|
||||||
|
}
|
||||||
|
|
||||||
|
//public T DoLCS(T list1, T list2)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
private object[] LCS(object[] list1, object[] list2)
|
||||||
|
{
|
||||||
|
int m=list1.Length ;
|
||||||
|
int n=list2.Length ;
|
||||||
|
|
||||||
|
int[,] lcs=new int[m+1, n+1];
|
||||||
|
BackTracking[ , ] backTracer=new BackTracking[m+1, n+1];
|
||||||
|
int[,] w=new int[m+1, n+1];
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i <= m; i++)
|
||||||
|
{
|
||||||
|
lcs[i,0] = 0;
|
||||||
|
backTracer[i,0]=BackTracking.UP;
|
||||||
|
|
||||||
|
}
|
||||||
|
for (j = 0; j <= n; j++)
|
||||||
|
{
|
||||||
|
lcs[0,j]=0;
|
||||||
|
backTracer[0,j]=BackTracking.LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i <= m; i++)
|
||||||
|
{
|
||||||
|
for (j = 1; j <= n; j++)
|
||||||
|
{
|
||||||
|
if(list1[i-1] == list2[j-1])
|
||||||
|
{
|
||||||
|
int k = w[i-1, j-1];
|
||||||
|
//lcs[i,j] = lcs[i-1,j-1] + 1;
|
||||||
|
lcs[i,j]=lcs[i-1,j-1] + ConsecutiveMeasure(k+1) - ConsecutiveMeasure(k);
|
||||||
|
backTracer[i,j] = BackTracking.UP_AND_LEFT;
|
||||||
|
w[i,j] = k+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lcs[i,j] = lcs[i-1,j-1];
|
||||||
|
backTracer[i,j] = BackTracking.NEITHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lcs[i-1,j] >= lcs[i,j])
|
||||||
|
{
|
||||||
|
lcs[i,j] = lcs[i-1,j];
|
||||||
|
backTracer[i,j] = BackTracking.UP;
|
||||||
|
w[i,j] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lcs[i,j-1] >= lcs[i,j])
|
||||||
|
{
|
||||||
|
lcs[i,j] = lcs[i,j-1];
|
||||||
|
backTracer [i,j] = BackTracking.LEFT;
|
||||||
|
w[i,j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i=m;
|
||||||
|
j=n;
|
||||||
|
|
||||||
|
Stack<object> subseq = new Stack<object>();
|
||||||
|
// int p=lcs[i,j];
|
||||||
|
|
||||||
|
//trace the backtracking matrix.
|
||||||
|
while( i > 0 || j > 0 )
|
||||||
|
{
|
||||||
|
if( backTracer[i,j] == BackTracking.UP_AND_LEFT )
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
subseq.Push(list1[i]);
|
||||||
|
// subseq = list1[i] + subseq;
|
||||||
|
Trace.WriteLine(i + " " + list1[i] + " " + j) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if( backTracer[i,j] == BackTracking.UP )
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if( backTracer[i,j] == BackTracking.LEFT )
|
||||||
|
{
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return subseq.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for m3uFromDirectory.
|
||||||
|
/// </summary>
|
||||||
|
public class M3uCreate
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Use the parent's directory name for the m3u name
|
||||||
|
/// </summary>
|
||||||
|
private bool mUseGeneratedOuputFilename = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Directory to grab the files from
|
||||||
|
/// </summary>
|
||||||
|
private DirectoryInfo mInputDir;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ouput m3u filename, if it isn't generated
|
||||||
|
/// </summary>
|
||||||
|
private string mOutputFilename = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter for input filenames
|
||||||
|
/// </summary>
|
||||||
|
private string mFileFilter = "*.mp3";
|
||||||
|
|
||||||
|
public bool UseGeneratedOuputFilename
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mUseGeneratedOuputFilename;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mUseGeneratedOuputFilename = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OutputFilename
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mUseGeneratedOuputFilename)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("OutputFilename:" + mInputDir.FullName + "\\" + mInputDir.Name + ".m3u");
|
||||||
|
return mInputDir.FullName + "\\" + mInputDir.Name + ".m3u";
|
||||||
|
}
|
||||||
|
return mOutputFilename;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mOutputFilename = value;
|
||||||
|
mUseGeneratedOuputFilename = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public M3uCreate(string dir) : this (new DirectoryInfo(dir))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public M3uCreate(DirectoryInfo inputDir)
|
||||||
|
{
|
||||||
|
mInputDir = inputDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// dir: "\foo\bar\" file: "\foo\bar\myfile" output: ""
|
||||||
|
/// dir: "\foo\" file: "\foo\bar\myfile" output: ".."
|
||||||
|
/// dir: "\" file: "\foo\bar\myfile" output: "..\.."
|
||||||
|
/// dir: "\har" file: "\foo\bar\myfile" output: "..\..\har"
|
||||||
|
/// dir: "\foo\bar\hey\" file: "\foo\bar\myfile" output: "hey\"
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="dir"></param>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string GetPath(DirectoryInfo dir, FileInfo file)
|
||||||
|
{
|
||||||
|
string source = dir.FullName;
|
||||||
|
string target = file.Directory.FullName;
|
||||||
|
|
||||||
|
return GetPath(source, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The source.</param>
|
||||||
|
/// <param name="target">The target.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string GetPath(string source, string target)
|
||||||
|
{
|
||||||
|
int lastCommonIndex = GetLastCommonIndex(source, target);
|
||||||
|
Debug.WriteLine(String.Format("s:{0} , t:{1} lastCommon:{2} ", source, target, lastCommonIndex));
|
||||||
|
|
||||||
|
int slashCount = CountCharacters(source, lastCommonIndex + 1, '\\');
|
||||||
|
|
||||||
|
string path = "";
|
||||||
|
for (int i = 0; i < slashCount; i++)
|
||||||
|
{
|
||||||
|
path += "..\\";
|
||||||
|
}
|
||||||
|
path += target.Substring(lastCommonIndex);
|
||||||
|
if (path.Length > 0 && path[path.Length - 1] != '\\')
|
||||||
|
path += "\\";
|
||||||
|
Debug.WriteLine(path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CountCharacters(string str, int startIdx, char c)
|
||||||
|
{
|
||||||
|
int charsCount = 0;
|
||||||
|
int currIdx = startIdx;
|
||||||
|
while (currIdx < str.Length && (currIdx = str.IndexOf(c, currIdx) + 1) != 0)
|
||||||
|
charsCount++;
|
||||||
|
return charsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetLastCommonIndex(string str1, string str2)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < str1.Length && i < str2.Length && Char.ToLower(str1[i]) == Char.ToLower(str2[i]))
|
||||||
|
i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Create()
|
||||||
|
{
|
||||||
|
string fileList = "";
|
||||||
|
DirectoryInfo ouputDirectory = (new FileInfo(OutputFilename)).Directory;
|
||||||
|
foreach (FileInfo info in mInputDir.GetFiles(mFileFilter))
|
||||||
|
{
|
||||||
|
string fileName = GetPath(ouputDirectory, info) + info.Name;
|
||||||
|
Debug.WriteLine(fileName);
|
||||||
|
fileList += fileName + Environment.NewLine;
|
||||||
|
}
|
||||||
|
SaveToFile(fileList, OutputFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveToFile(string contents, string outputFilename)
|
||||||
|
{
|
||||||
|
using (TextWriter tw = new StreamWriter(outputFilename))
|
||||||
|
{
|
||||||
|
tw.Write(contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for Form1.
|
||||||
|
/// </summary>
|
||||||
|
public class M3uMakeByDirectory : Form
|
||||||
|
{
|
||||||
|
private Button selectDirectoryButton;
|
||||||
|
private TextBox m3uDirectoryTextBox;
|
||||||
|
private TextBox outputTextBox;
|
||||||
|
private Button m3uMakeButton;
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private Container components = null;
|
||||||
|
|
||||||
|
public M3uMakeByDirectory()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Required for Windows Form Designer support
|
||||||
|
//
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Add any constructor code after InitializeComponent call
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
protected override void Dispose( bool disposing )
|
||||||
|
{
|
||||||
|
if( disposing )
|
||||||
|
{
|
||||||
|
if (components != null)
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose( disposing );
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.m3uDirectoryTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.outputTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.selectDirectoryButton = new System.Windows.Forms.Button();
|
||||||
|
this.m3uMakeButton = new System.Windows.Forms.Button();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// m3uDirectoryTextBox
|
||||||
|
//
|
||||||
|
this.m3uDirectoryTextBox.Enabled = false;
|
||||||
|
this.m3uDirectoryTextBox.Location = new System.Drawing.Point(8, 8);
|
||||||
|
this.m3uDirectoryTextBox.Name = "m3uDirectoryTextBox";
|
||||||
|
this.m3uDirectoryTextBox.Size = new System.Drawing.Size(176, 20);
|
||||||
|
this.m3uDirectoryTextBox.TabIndex = 0;
|
||||||
|
this.m3uDirectoryTextBox.Text = "";
|
||||||
|
//
|
||||||
|
// outputTextBox
|
||||||
|
//
|
||||||
|
this.outputTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.outputTextBox.Location = new System.Drawing.Point(8, 88);
|
||||||
|
this.outputTextBox.Multiline = true;
|
||||||
|
this.outputTextBox.Name = "outputTextBox";
|
||||||
|
this.outputTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||||
|
this.outputTextBox.Size = new System.Drawing.Size(272, 168);
|
||||||
|
this.outputTextBox.TabIndex = 1;
|
||||||
|
this.outputTextBox.Text = "";
|
||||||
|
//
|
||||||
|
// selectDirectoryButton
|
||||||
|
//
|
||||||
|
this.selectDirectoryButton.Location = new System.Drawing.Point(208, 8);
|
||||||
|
this.selectDirectoryButton.Name = "selectDirectoryButton";
|
||||||
|
this.selectDirectoryButton.TabIndex = 2;
|
||||||
|
this.selectDirectoryButton.Text = "Select Dir...";
|
||||||
|
this.selectDirectoryButton.Click += new System.EventHandler(this.selectDirectoryButton_Click);
|
||||||
|
//
|
||||||
|
// m3uMakeButton
|
||||||
|
//
|
||||||
|
this.m3uMakeButton.Enabled = false;
|
||||||
|
this.m3uMakeButton.Location = new System.Drawing.Point(208, 40);
|
||||||
|
this.m3uMakeButton.Name = "m3uMakeButton";
|
||||||
|
this.m3uMakeButton.TabIndex = 3;
|
||||||
|
this.m3uMakeButton.Text = "Make M3u";
|
||||||
|
this.m3uMakeButton.Click += new System.EventHandler(this.m3uMakeButton_Click);
|
||||||
|
//
|
||||||
|
// MakeSubdir
|
||||||
|
//
|
||||||
|
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
||||||
|
this.ClientSize = new System.Drawing.Size(292, 266);
|
||||||
|
this.Controls.Add(this.m3uMakeButton);
|
||||||
|
this.Controls.Add(this.selectDirectoryButton);
|
||||||
|
this.Controls.Add(this.outputTextBox);
|
||||||
|
this.Controls.Add(this.m3uDirectoryTextBox);
|
||||||
|
this.Name = "MakeSubdir";
|
||||||
|
this.Text = "M3u Make";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
Application.Run(new M3uMakeByDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectDirectoryButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
FolderBrowserDialog fbd = new FolderBrowserDialog();
|
||||||
|
DialogResult dialogResult = fbd.ShowDialog(this);
|
||||||
|
|
||||||
|
if (dialogResult == DialogResult.OK)
|
||||||
|
{
|
||||||
|
m3uDirectoryTextBox.Text = fbd.SelectedPath;
|
||||||
|
}
|
||||||
|
UpdateRunButton();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateRunButton()
|
||||||
|
{
|
||||||
|
if (m3uDirectoryTextBox.Text != null && m3uDirectoryTextBox.Text!="" && Directory.Exists(m3uDirectoryTextBox.Text))
|
||||||
|
{
|
||||||
|
m3uMakeButton.Enabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m3uMakeButton.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateM3uThread()
|
||||||
|
{
|
||||||
|
CreateM3uRecursive(new DirectoryInfo(m3uDirectoryTextBox.Text));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateM3uRecursive(DirectoryInfo info)
|
||||||
|
{
|
||||||
|
M3uCreate cm3u = new M3uCreate(info);
|
||||||
|
cm3u.Create();
|
||||||
|
outputTextBox.AppendText("Created " + cm3u.OutputFilename + Environment.NewLine);
|
||||||
|
foreach (DirectoryInfo subDir in info.GetDirectories())
|
||||||
|
{
|
||||||
|
CreateM3uRecursive(subDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void m3uMakeButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Thread t = new Thread(new ThreadStart(CreateM3uThread));
|
||||||
|
t.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used forserialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="m3uDirectoryTextBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uDirectoryTextBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uDirectoryTextBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>(Default)</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Name">
|
||||||
|
<value>MakeSubdir</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>8, 8</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>80</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
Generated
+46
@@ -0,0 +1,46 @@
|
|||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
partial class M3uToAac
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// M3uToAac
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(434, 138);
|
||||||
|
this.Name = "M3uToAac";
|
||||||
|
this.Text = "M3uToAac";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public partial class M3uToAac : Form
|
||||||
|
{
|
||||||
|
public class Mp3ToAacConversionOptions
|
||||||
|
{
|
||||||
|
string[] mInputFilenames;
|
||||||
|
string[] mOutputFilenames;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
public M3uToAac()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class Mp3Encoder : ProcessStreamWrapper
|
||||||
|
{
|
||||||
|
public Mp3Encoder(Mp3EncodingOptions encOpt)
|
||||||
|
: base(encOpt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mp3Encoder(Mp3EncodingOptions encOpt, Stream outputStream)
|
||||||
|
: base(encOpt, outputStream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ProcessExecutableFilename
|
||||||
|
{
|
||||||
|
get { return @"c:\console\audio\lame.exe"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,442 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// LAME 32bits version 3.97 (beta 1, Oct 16 2005) (http://www.mp3dev.org/)
|
||||||
|
///
|
||||||
|
/// usage: lame [options] <infile> [outfile]
|
||||||
|
///
|
||||||
|
/// <infile> and/or <outfile> can be "-", which means stdin/stdout.
|
||||||
|
///
|
||||||
|
/// RECOMMENDED:
|
||||||
|
/// lame -V2 input.wav output.mp3
|
||||||
|
///
|
||||||
|
/// OPTIONS:
|
||||||
|
/// Input options:
|
||||||
|
/// -r input is raw pcm
|
||||||
|
/// -x force byte-swapping of input
|
||||||
|
/// -s sfreq sampling frequency of input file (kHz) - default 44.1 kHz
|
||||||
|
/// --bitwidth w input bit width is w (default 16)
|
||||||
|
/// --scale <arg> scale input (multiply PCM data) by <arg>
|
||||||
|
/// --scale-l <arg> scale channel 0 (left) input (multiply PCM data) by <arg>
|
||||||
|
/// --scale-r <arg> scale channel 1 (right) input (multiply PCM data) by <arg>
|
||||||
|
/// --mp1input input file is a MPEG Layer I file
|
||||||
|
/// --mp2input input file is a MPEG Layer II file
|
||||||
|
/// --mp3input input file is a MPEG Layer III file
|
||||||
|
/// --nogap <file1> <file2> <...>
|
||||||
|
/// gapless encoding for a set of contiguous files
|
||||||
|
/// --nogapout <dir>
|
||||||
|
/// output dir for gapless encoding (must precede --nogap)
|
||||||
|
/// --nogaptags allow the use of VBR tags in gapless encoding
|
||||||
|
///
|
||||||
|
/// Operational options:
|
||||||
|
/// -a downmix from stereo to mono file for mono encoding
|
||||||
|
/// -m <mode> (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono
|
||||||
|
/// default is (j) or (s) depending on bitrate
|
||||||
|
/// joint = joins the best possible of MS and LR stereo
|
||||||
|
/// simple = force LR stereo on all frames
|
||||||
|
/// force = force MS stereo on all frames.
|
||||||
|
/// --preset type type must be "medium", "standard", "extreme", "insane",
|
||||||
|
/// or a value for an average desired bitrate and depending
|
||||||
|
/// on the value specified, appropriate quality settings will
|
||||||
|
/// be used.
|
||||||
|
/// "--preset help" gives more info on these
|
||||||
|
/// --comp <arg> choose bitrate to achive a compression ratio of <arg>
|
||||||
|
/// --replaygain-fast compute RG fast but slightly inaccurately (default)
|
||||||
|
/// --replaygain-accurate compute RG more accurately and find the peak sample
|
||||||
|
/// --noreplaygain disable ReplayGain analysis
|
||||||
|
/// --clipdetect enable --replaygain-accurate and print a message whether
|
||||||
|
/// clipping occurs and how far the waveform is from full scale
|
||||||
|
/// --freeformat produce a free format bitstream
|
||||||
|
/// --decode input=mp3 file, output=wav
|
||||||
|
/// -t disable writing wav header when using --decode
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Verbosity:
|
||||||
|
/// --disptime <arg>print progress report every arg seconds
|
||||||
|
/// -S don't print progress report, VBR histograms
|
||||||
|
/// --nohist disable VBR histogram display
|
||||||
|
/// --silent don't print anything on screen
|
||||||
|
/// --quiet don't print anything on screen
|
||||||
|
/// --brief print more useful information
|
||||||
|
/// --verbose print a lot of useful information
|
||||||
|
///
|
||||||
|
/// Noise shaping & psycho acoustic algorithms:
|
||||||
|
/// -q <arg> <arg> = 0...9. Default -q 5
|
||||||
|
/// -q 0: Highest quality, very slow
|
||||||
|
/// -q 9: Poor quality, but fast
|
||||||
|
/// -h Same as -q 2. Recommended.
|
||||||
|
/// -f Same as -q 7. Fast, ok quality
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// CBR (constant bitrate, the default) options:
|
||||||
|
/// -b <bitrate> set the bitrate in kbps, default 128 kbps
|
||||||
|
/// --cbr enforce use of constant bitrate
|
||||||
|
///
|
||||||
|
/// ABR options:
|
||||||
|
/// --abr <bitrate> specify average bitrate desired (instead of quality)
|
||||||
|
///
|
||||||
|
/// VBR options:
|
||||||
|
/// -v use variable bitrate (VBR) (--vbr-old)
|
||||||
|
/// --vbr-old use old variable bitrate (VBR) routine
|
||||||
|
/// --vbr-new use new variable bitrate (VBR) routine
|
||||||
|
/// -V n quality setting for VBR. default n=4
|
||||||
|
/// 0=high quality,bigger files. 9=smaller files
|
||||||
|
/// -b <bitrate> specify minimum allowed bitrate, default 32 kbps
|
||||||
|
/// -B <bitrate> specify maximum allowed bitrate, default 320 kbps
|
||||||
|
/// -F strictly enforce the -b option, for use with players that
|
||||||
|
/// do not support low bitrate mp3
|
||||||
|
/// -t disable writing LAME Tag
|
||||||
|
/// -T enable and force writing LAME Tag
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// PSY related:
|
||||||
|
/// --short use short blocks when appropriate
|
||||||
|
/// --noshort do not use short blocks
|
||||||
|
/// --allshort use only short blocks
|
||||||
|
/// --notemp disable temporal masking effect
|
||||||
|
/// --nssafejoint M/S switching criterion
|
||||||
|
/// --nsmsfix <arg> M/S switching tuning [effective 0-3.5]
|
||||||
|
/// --interch x adjust inter-channel masking ratio
|
||||||
|
/// --ns-bass x adjust masking for sfbs 0 - 6 (long) 0 - 5 (short)
|
||||||
|
/// --ns-alto x adjust masking for sfbs 7 - 13 (long) 6 - 10 (short)
|
||||||
|
/// --ns-treble x adjust masking for sfbs 14 - 21 (long) 11 - 12 (short)
|
||||||
|
/// --ns-sfb21 x change ns-treble by x dB for sfb21
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// experimental switches:
|
||||||
|
/// -X n[,m] selects between different noise measurements
|
||||||
|
/// n for long block, m for short. if m is omitted, m = n
|
||||||
|
/// -Y lets LAME ignore noise in sfb21, like in CBR
|
||||||
|
/// -Z [n] currently no effects
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// MP3 header/stream options:
|
||||||
|
/// -e <emp> de-emphasis n/5/c (obsolete)
|
||||||
|
/// -c mark as copyright
|
||||||
|
/// -o mark as non-original
|
||||||
|
/// -p error protection. adds 16 bit checksum to every frame
|
||||||
|
/// (the checksum is computed correctly)
|
||||||
|
/// --nores disable the bit reservoir
|
||||||
|
/// --strictly-enforce-ISO comply as much as possible to ISO MPEG spec
|
||||||
|
///
|
||||||
|
/// Filter options:
|
||||||
|
/// -k keep ALL frequencies (disables all filters),
|
||||||
|
/// Can cause ringing and twinkling
|
||||||
|
/// --lowpass <freq> frequency(kHz), lowpass filter cutoff above freq
|
||||||
|
/// --lowpass-width <freq> frequency(kHz) - default 15% of lowpass freq
|
||||||
|
/// --highpass <freq> frequency(kHz), highpass filter cutoff below freq
|
||||||
|
/// --highpass-width <freq> frequency(kHz) - default 15% of highpass freq
|
||||||
|
/// --resample <sfreq> sampling frequency of output file(kHz)- default=automatic
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// ID3 tag options:
|
||||||
|
/// --tt <title> audio/song title (max 30 chars for version 1 tag)
|
||||||
|
/// --ta <artist> audio/song artist (max 30 chars for version 1 tag)
|
||||||
|
/// --tl <album> audio/song album (max 30 chars for version 1 tag)
|
||||||
|
/// --ty <year> audio/song year of issue (1 to 9999)
|
||||||
|
/// --tc <comment> user-defined text (max 30 chars for v1 tag, 28 for v1.1)
|
||||||
|
/// --tn <track> audio/song track number (1 to 255, creates v1.1 tag)
|
||||||
|
/// --tg <genre> audio/song genre (name or number in list)
|
||||||
|
/// --add-id3v2 force addition of version 2 tag
|
||||||
|
/// --id3v1-only add only a version 1 tag
|
||||||
|
/// --id3v2-only add only a version 2 tag
|
||||||
|
/// --space-id3v1 pad version 1 tag with spaces instead of nulls
|
||||||
|
/// --pad-id3v2 pad version 2 tag with extra 128 bytes
|
||||||
|
/// --genre-list print alphabetically sorted ID3 genre list and exit
|
||||||
|
/// --ignore-tag-errors ignore errors in values passed for tags
|
||||||
|
///
|
||||||
|
/// Note: A version 2 tag will NOT be added unless one of the input fields
|
||||||
|
/// won't fit in a version 1 tag (e.g. the title string is longer than 30
|
||||||
|
/// characters), or the '--add-id3v2' or '--id3v2-only' options are used,
|
||||||
|
/// or output is redirected to stdout.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// MS-Windows-specific options:
|
||||||
|
/// --priority <type> sets the process priority:
|
||||||
|
/// 0,1 = Low priority (IDLE_PRIORITY_CLASS)
|
||||||
|
/// 2 = normal priority (NORMAL_PRIORITY_CLASS, defau
|
||||||
|
/// lt)
|
||||||
|
/// 3,4 = High priority (HIGH_PRIORITY_CLASS))
|
||||||
|
/// Note: Calling '--priority' without a parameter will select priority 0.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Platform specific:
|
||||||
|
/// --noasm <instructions> disable assembly optimizations for mmx/3dnow/sse
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// MPEG-1 layer III sample frequencies (kHz): 32 48 44.1
|
||||||
|
/// bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320
|
||||||
|
///
|
||||||
|
/// MPEG-2 layer III sample frequencies (kHz): 16 24 22.05
|
||||||
|
/// bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160
|
||||||
|
///
|
||||||
|
/// MPEG-2.5 layer III sample frequencies (kHz): 8 12 11.025
|
||||||
|
/// bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160
|
||||||
|
/// </summary>
|
||||||
|
public class Mp3EncodingOptions : ProcessArguments
|
||||||
|
{
|
||||||
|
#region Private variables
|
||||||
|
/// <summary>
|
||||||
|
/// Input filename. Can be "-", which means stdin.
|
||||||
|
/// </summary>
|
||||||
|
private string mInfile = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Output filename. Can be "-", which means stdout.
|
||||||
|
/// </summary>
|
||||||
|
private string mOutfile = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input is raw pcm (-r)
|
||||||
|
/// </summary>
|
||||||
|
private bool mRawPCMInputMode = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// force byte-swapping of input (-x)
|
||||||
|
/// </summary>
|
||||||
|
private bool mForceByteSwappingOfInput = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sampling frequency of input file (kHz) - default 44.1 kHz (-s sfreq)
|
||||||
|
/// </summary>
|
||||||
|
private SampleRateFrequency mRawPCMInputSampleSize = SampleRateFrequency.Hz_44100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input bit width is w (default 16) (--bitwidth w)
|
||||||
|
/// </summary>
|
||||||
|
private int mRawPCMInputSampleRate = 16;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input file is a MPEG Layer III file (--mp3input)
|
||||||
|
/// </summary>
|
||||||
|
private bool mMp3Input = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// downmix from stereo to mono file for mono encoding (-a)
|
||||||
|
/// </summary>
|
||||||
|
private bool mMonoDownmixing = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono (-m)
|
||||||
|
/// </summary>
|
||||||
|
private ChannelMode mChannelMode = ChannelMode.JointStereo;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// produce a free format bitstream (--freeformat)
|
||||||
|
/// </summary>
|
||||||
|
private bool mFreeFormat = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input=mp3 file, output=wav (--decode)
|
||||||
|
/// </summary>
|
||||||
|
private bool mDecodeWav = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// disable writing wav header when using --decode (-t)
|
||||||
|
/// </summary>
|
||||||
|
private bool mDisableWavHeader = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the bitrate in kbps, default 128 kbps -b <bitrate>
|
||||||
|
/// </summary>
|
||||||
|
private BitRate mBitRate = BitRate.KBPS_0;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public properties
|
||||||
|
/// <summary>
|
||||||
|
/// Input filename. Can be "-", which means stdin.
|
||||||
|
/// </summary>
|
||||||
|
public string Infile
|
||||||
|
{
|
||||||
|
get { return mInfile; }
|
||||||
|
set { mInfile = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Output filename. Can be "-", which means stdout.
|
||||||
|
/// </summary>
|
||||||
|
public string Outfile
|
||||||
|
{
|
||||||
|
get { return mOutfile; }
|
||||||
|
set { mOutfile = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input is raw pcm (-r)
|
||||||
|
/// </summary>
|
||||||
|
public bool RawPCMInputMode
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputMode; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputMode = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// force byte-swapping of input (-x)
|
||||||
|
/// </summary>
|
||||||
|
public bool ForceByteSwappingOfInput
|
||||||
|
{
|
||||||
|
get { return mForceByteSwappingOfInput; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mForceByteSwappingOfInput = value;
|
||||||
|
mRawPCMInputMode = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sampling frequency of input file (kHz) - default 44.1 kHz (-s sfreq)
|
||||||
|
/// </summary>
|
||||||
|
public SampleRateFrequency RawPCMInputSampleSize
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleSize; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleSize = value;
|
||||||
|
mRawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input bit width is w (default 16) (--bitwidth w)
|
||||||
|
/// </summary>
|
||||||
|
public int RawPCMInputSampleRate
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleRate; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleRate = value;
|
||||||
|
mRawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input file is a MPEG Layer III file (--mp3input)
|
||||||
|
/// </summary>
|
||||||
|
public bool Mp3Input
|
||||||
|
{
|
||||||
|
get { return mMp3Input; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mMp3Input = value;
|
||||||
|
if (mMp3Input)
|
||||||
|
mRawPCMInputMode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// downmix from stereo to mono file for mono encoding (-a)
|
||||||
|
/// </summary>
|
||||||
|
public bool MonoDownmixing
|
||||||
|
{
|
||||||
|
get { return mMonoDownmixing; }
|
||||||
|
set { mMonoDownmixing = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono (-m)
|
||||||
|
/// </summary>
|
||||||
|
public ChannelMode ChannelMode
|
||||||
|
{
|
||||||
|
get { return mChannelMode; }
|
||||||
|
set { mChannelMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// produce a free format bitstream (--freeformat)
|
||||||
|
/// </summary>
|
||||||
|
public bool Freeformat
|
||||||
|
{
|
||||||
|
get { return mFreeFormat; }
|
||||||
|
set { mFreeFormat = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input=mp3 file, output=wav (--decode)
|
||||||
|
/// </summary>
|
||||||
|
public bool DecodeWav
|
||||||
|
{
|
||||||
|
get { return mDecodeWav; }
|
||||||
|
set { mDecodeWav = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// disable writing wav header when using --decode (-t)
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableWavHeader
|
||||||
|
{
|
||||||
|
get { return mDisableWavHeader; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mDisableWavHeader = value;
|
||||||
|
if (mDisableWavHeader)
|
||||||
|
DecodeWav = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitRate BitRate
|
||||||
|
{
|
||||||
|
get { return mBitRate; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mBitRate = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representing the command line arguments specified by the properties in the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override string GetCommandLineArguments()
|
||||||
|
{
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
if (mRawPCMInputMode)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" -r");
|
||||||
|
if (mForceByteSwappingOfInput)
|
||||||
|
stringBuilder.Append(" -x");
|
||||||
|
if (mRawPCMInputSampleSize != SampleRateFrequency.Hz_44100)
|
||||||
|
stringBuilder.Append(" -s " + SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mRawPCMInputSampleSize));
|
||||||
|
if (mRawPCMInputSampleRate != 16)
|
||||||
|
stringBuilder.Append(" --bandwidth " + mRawPCMInputSampleRate);
|
||||||
|
}
|
||||||
|
if (mMp3Input)
|
||||||
|
stringBuilder.Append(" --mp3input");
|
||||||
|
if (mMonoDownmixing)
|
||||||
|
stringBuilder.Append(" -a");
|
||||||
|
if (mChannelMode != ChannelMode.JointStereo)
|
||||||
|
stringBuilder.Append(" -m " + ChannelModeUtility.GetChannelModeChar(mChannelMode));
|
||||||
|
|
||||||
|
if (mFreeFormat)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" --freeformat");
|
||||||
|
stringBuilder.Append(" -b " + BitRateFrequencyUtility.GetBitRateInt(BitRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDecodeWav)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" --decode");
|
||||||
|
if (mDisableWavHeader)
|
||||||
|
stringBuilder.Append(" -t");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(mInfile))
|
||||||
|
stringBuilder.Append(" " + GetQuotedCommandLineArgument(mInfile));
|
||||||
|
if (!string.IsNullOrEmpty(mOutfile))
|
||||||
|
stringBuilder.Append(" " + (mOutfile));
|
||||||
|
|
||||||
|
|
||||||
|
return stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Generated
+306
@@ -0,0 +1,306 @@
|
|||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
partial class Mp3ToAacBatch
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Mp3ToAacBatch));
|
||||||
|
this.inputListBox = new System.Windows.Forms.ListBox();
|
||||||
|
this.addFolderButton = new System.Windows.Forms.Button();
|
||||||
|
this.addFileButton = new System.Windows.Forms.Button();
|
||||||
|
this.moveUpButton = new System.Windows.Forms.Button();
|
||||||
|
this.moveDownButton = new System.Windows.Forms.Button();
|
||||||
|
this.sortButton = new System.Windows.Forms.Button();
|
||||||
|
this.updownSplitContainer = new System.Windows.Forms.SplitContainer();
|
||||||
|
this.inputLabel = new System.Windows.Forms.Label();
|
||||||
|
this.inputPanel = new System.Windows.Forms.Panel();
|
||||||
|
this.clearButton = new System.Windows.Forms.Button();
|
||||||
|
this.optionsPanel = new System.Windows.Forms.Panel();
|
||||||
|
this.singleFileCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
|
this.outputDirectoryTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.optionsLabel = new System.Windows.Forms.Label();
|
||||||
|
this.savePanel = new System.Windows.Forms.Panel();
|
||||||
|
this.saveLabel = new System.Windows.Forms.Label();
|
||||||
|
this.updownSplitContainer.Panel1.SuspendLayout();
|
||||||
|
this.updownSplitContainer.Panel2.SuspendLayout();
|
||||||
|
this.updownSplitContainer.SuspendLayout();
|
||||||
|
this.inputPanel.SuspendLayout();
|
||||||
|
this.optionsPanel.SuspendLayout();
|
||||||
|
this.savePanel.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// inputListBox
|
||||||
|
//
|
||||||
|
this.inputListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.inputListBox.FormattingEnabled = true;
|
||||||
|
this.inputListBox.Location = new System.Drawing.Point(6, 35);
|
||||||
|
this.inputListBox.Name = "inputListBox";
|
||||||
|
this.inputListBox.Size = new System.Drawing.Size(551, 264);
|
||||||
|
this.inputListBox.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// addFolderButton
|
||||||
|
//
|
||||||
|
this.addFolderButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.addFolderButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.addFolderButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.addFolderButton.Image = ((System.Drawing.Image)(resources.GetObject("addFolderButton.Image")));
|
||||||
|
this.addFolderButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.addFolderButton.Location = new System.Drawing.Point(470, 3);
|
||||||
|
this.addFolderButton.Name = "addFolderButton";
|
||||||
|
this.addFolderButton.Size = new System.Drawing.Size(87, 30);
|
||||||
|
this.addFolderButton.TabIndex = 2;
|
||||||
|
this.addFolderButton.Text = "Add Folder";
|
||||||
|
this.addFolderButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.addFolderButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// addFileButton
|
||||||
|
//
|
||||||
|
this.addFileButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.addFileButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.addFileButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.addFileButton.Image = ((System.Drawing.Image)(resources.GetObject("addFileButton.Image")));
|
||||||
|
this.addFileButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.addFileButton.Location = new System.Drawing.Point(390, 3);
|
||||||
|
this.addFileButton.Name = "addFileButton";
|
||||||
|
this.addFileButton.Size = new System.Drawing.Size(74, 30);
|
||||||
|
this.addFileButton.TabIndex = 3;
|
||||||
|
this.addFileButton.Text = "Add File";
|
||||||
|
this.addFileButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.addFileButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// moveUpButton
|
||||||
|
//
|
||||||
|
this.moveUpButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.moveUpButton.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.moveUpButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.moveUpButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.moveUpButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.moveUpButton.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.moveUpButton.Name = "moveUpButton";
|
||||||
|
this.moveUpButton.Size = new System.Drawing.Size(18, 107);
|
||||||
|
this.moveUpButton.TabIndex = 4;
|
||||||
|
this.moveUpButton.Text = "^|";
|
||||||
|
this.moveUpButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.moveUpButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// moveDownButton
|
||||||
|
//
|
||||||
|
this.moveDownButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.moveDownButton.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.moveDownButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.moveDownButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.moveDownButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.moveDownButton.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.moveDownButton.Name = "moveDownButton";
|
||||||
|
this.moveDownButton.Size = new System.Drawing.Size(18, 157);
|
||||||
|
this.moveDownButton.TabIndex = 5;
|
||||||
|
this.moveDownButton.Text = "|v";
|
||||||
|
this.moveDownButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.moveDownButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// sortButton
|
||||||
|
//
|
||||||
|
this.sortButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.sortButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.sortButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.sortButton.Image = ((System.Drawing.Image)(resources.GetObject("sortButton.Image")));
|
||||||
|
this.sortButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.sortButton.Location = new System.Drawing.Point(0, 307);
|
||||||
|
this.sortButton.Name = "sortButton";
|
||||||
|
this.sortButton.Size = new System.Drawing.Size(61, 30);
|
||||||
|
this.sortButton.TabIndex = 6;
|
||||||
|
this.sortButton.Text = "Sort";
|
||||||
|
this.sortButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.sortButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// updownSplitContainer
|
||||||
|
//
|
||||||
|
this.updownSplitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.updownSplitContainer.IsSplitterFixed = true;
|
||||||
|
this.updownSplitContainer.Location = new System.Drawing.Point(563, 35);
|
||||||
|
this.updownSplitContainer.Name = "updownSplitContainer";
|
||||||
|
this.updownSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||||
|
//
|
||||||
|
// updownSplitContainer.Panel1
|
||||||
|
//
|
||||||
|
this.updownSplitContainer.Panel1.Controls.Add(this.moveUpButton);
|
||||||
|
//
|
||||||
|
// updownSplitContainer.Panel2
|
||||||
|
//
|
||||||
|
this.updownSplitContainer.Panel2.Controls.Add(this.moveDownButton);
|
||||||
|
this.updownSplitContainer.Size = new System.Drawing.Size(18, 266);
|
||||||
|
this.updownSplitContainer.SplitterDistance = 107;
|
||||||
|
this.updownSplitContainer.SplitterWidth = 2;
|
||||||
|
this.updownSplitContainer.TabIndex = 8;
|
||||||
|
//
|
||||||
|
// inputLabel
|
||||||
|
//
|
||||||
|
this.inputLabel.AutoSize = true;
|
||||||
|
this.inputLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.inputLabel.Location = new System.Drawing.Point(3, 3);
|
||||||
|
this.inputLabel.Name = "inputLabel";
|
||||||
|
this.inputLabel.Size = new System.Drawing.Size(126, 13);
|
||||||
|
this.inputLabel.TabIndex = 9;
|
||||||
|
this.inputLabel.Text = "1) Select Input MP3s";
|
||||||
|
//
|
||||||
|
// inputPanel
|
||||||
|
//
|
||||||
|
this.inputPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.inputPanel.Controls.Add(this.clearButton);
|
||||||
|
this.inputPanel.Controls.Add(this.inputLabel);
|
||||||
|
this.inputPanel.Controls.Add(this.inputListBox);
|
||||||
|
this.inputPanel.Controls.Add(this.updownSplitContainer);
|
||||||
|
this.inputPanel.Controls.Add(this.addFolderButton);
|
||||||
|
this.inputPanel.Controls.Add(this.addFileButton);
|
||||||
|
this.inputPanel.Controls.Add(this.sortButton);
|
||||||
|
this.inputPanel.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.inputPanel.Name = "inputPanel";
|
||||||
|
this.inputPanel.Size = new System.Drawing.Size(584, 344);
|
||||||
|
this.inputPanel.TabIndex = 10;
|
||||||
|
//
|
||||||
|
// clearButton
|
||||||
|
//
|
||||||
|
this.clearButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.clearButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.clearButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.clearButton.Image = ((System.Drawing.Image)(resources.GetObject("clearButton.Image")));
|
||||||
|
this.clearButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.clearButton.Location = new System.Drawing.Point(491, 307);
|
||||||
|
this.clearButton.Name = "clearButton";
|
||||||
|
this.clearButton.Size = new System.Drawing.Size(66, 30);
|
||||||
|
this.clearButton.TabIndex = 10;
|
||||||
|
this.clearButton.Text = "Clear";
|
||||||
|
this.clearButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.clearButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// optionsPanel
|
||||||
|
//
|
||||||
|
this.optionsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.optionsPanel.Controls.Add(this.singleFileCheckBox);
|
||||||
|
this.optionsPanel.Controls.Add(this.outputDirectoryTextBox);
|
||||||
|
this.optionsPanel.Controls.Add(this.optionsLabel);
|
||||||
|
this.optionsPanel.Location = new System.Drawing.Point(12, 362);
|
||||||
|
this.optionsPanel.Name = "optionsPanel";
|
||||||
|
this.optionsPanel.Size = new System.Drawing.Size(584, 135);
|
||||||
|
this.optionsPanel.TabIndex = 11;
|
||||||
|
//
|
||||||
|
// singleFileCheckBox
|
||||||
|
//
|
||||||
|
this.singleFileCheckBox.AutoSize = true;
|
||||||
|
this.singleFileCheckBox.Location = new System.Drawing.Point(448, 12);
|
||||||
|
this.singleFileCheckBox.Name = "singleFileCheckBox";
|
||||||
|
this.singleFileCheckBox.Size = new System.Drawing.Size(109, 17);
|
||||||
|
this.singleFileCheckBox.TabIndex = 12;
|
||||||
|
this.singleFileCheckBox.Text = "Output Single File";
|
||||||
|
this.singleFileCheckBox.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// outputDirectoryTextBox
|
||||||
|
//
|
||||||
|
this.outputDirectoryTextBox.Location = new System.Drawing.Point(8, 112);
|
||||||
|
this.outputDirectoryTextBox.Name = "outputDirectoryTextBox";
|
||||||
|
this.outputDirectoryTextBox.Size = new System.Drawing.Size(100, 20);
|
||||||
|
this.outputDirectoryTextBox.TabIndex = 11;
|
||||||
|
//
|
||||||
|
// optionsLabel
|
||||||
|
//
|
||||||
|
this.optionsLabel.AutoSize = true;
|
||||||
|
this.optionsLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.optionsLabel.Location = new System.Drawing.Point(3, 0);
|
||||||
|
this.optionsLabel.Name = "optionsLabel";
|
||||||
|
this.optionsLabel.Size = new System.Drawing.Size(105, 13);
|
||||||
|
this.optionsLabel.TabIndex = 10;
|
||||||
|
this.optionsLabel.Text = "2) Select Options";
|
||||||
|
//
|
||||||
|
// savePanel
|
||||||
|
//
|
||||||
|
this.savePanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.savePanel.Controls.Add(this.saveLabel);
|
||||||
|
this.savePanel.Location = new System.Drawing.Point(12, 503);
|
||||||
|
this.savePanel.Name = "savePanel";
|
||||||
|
this.savePanel.Size = new System.Drawing.Size(584, 93);
|
||||||
|
this.savePanel.TabIndex = 12;
|
||||||
|
//
|
||||||
|
// saveLabel
|
||||||
|
//
|
||||||
|
this.saveLabel.AutoSize = true;
|
||||||
|
this.saveLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.saveLabel.Location = new System.Drawing.Point(3, 0);
|
||||||
|
this.saveLabel.Name = "saveLabel";
|
||||||
|
this.saveLabel.Size = new System.Drawing.Size(79, 13);
|
||||||
|
this.saveLabel.TabIndex = 10;
|
||||||
|
this.saveLabel.Text = "3) Save AAC";
|
||||||
|
//
|
||||||
|
// Mp3ToAacBatch
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(608, 608);
|
||||||
|
this.Controls.Add(this.savePanel);
|
||||||
|
this.Controls.Add(this.optionsPanel);
|
||||||
|
this.Controls.Add(this.inputPanel);
|
||||||
|
this.Name = "Mp3ToAacBatch";
|
||||||
|
this.Text = "Mp3 To AAC Batch";
|
||||||
|
this.updownSplitContainer.Panel1.ResumeLayout(false);
|
||||||
|
this.updownSplitContainer.Panel2.ResumeLayout(false);
|
||||||
|
this.updownSplitContainer.ResumeLayout(false);
|
||||||
|
this.inputPanel.ResumeLayout(false);
|
||||||
|
this.inputPanel.PerformLayout();
|
||||||
|
this.optionsPanel.ResumeLayout(false);
|
||||||
|
this.optionsPanel.PerformLayout();
|
||||||
|
this.savePanel.ResumeLayout(false);
|
||||||
|
this.savePanel.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ListBox inputListBox;
|
||||||
|
private System.Windows.Forms.Button addFolderButton;
|
||||||
|
private System.Windows.Forms.Button addFileButton;
|
||||||
|
private System.Windows.Forms.Button moveUpButton;
|
||||||
|
private System.Windows.Forms.Button moveDownButton;
|
||||||
|
private System.Windows.Forms.Button sortButton;
|
||||||
|
private System.Windows.Forms.SplitContainer updownSplitContainer;
|
||||||
|
private System.Windows.Forms.Label inputLabel;
|
||||||
|
private System.Windows.Forms.Panel inputPanel;
|
||||||
|
private System.Windows.Forms.Panel optionsPanel;
|
||||||
|
private System.Windows.Forms.Label optionsLabel;
|
||||||
|
private System.Windows.Forms.Button clearButton;
|
||||||
|
private System.Windows.Forms.Panel savePanel;
|
||||||
|
private System.Windows.Forms.Label saveLabel;
|
||||||
|
private System.Windows.Forms.TextBox outputDirectoryTextBox;
|
||||||
|
private System.Windows.Forms.CheckBox singleFileCheckBox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public partial class Mp3ToAacBatch : Form
|
||||||
|
{
|
||||||
|
public Mp3ToAacBatch()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
<data name="addFolderButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAO9JREFUOE9jYKAW
|
||||||
|
OLdI8T8yJslckEZ0cGyWxH+iDAEphIA5aPj/f5AcNoxiMNiAz0DNn3swMYa7IIbOrZJEuA5swOuW/48O
|
||||||
|
+uO0EZsrlhbxQAwBG3C9Baz51v5shJ2/v2OxHyj0vAUsjmLA36v5YAO+f+jEEhZoYXM86v/vn9NQDXi0
|
||||||
|
2en/yQUKIHP///8+BS9+vi/o/7k90agGnF+k+v/6DnuI7cDwwImBzn+/ywmhGRYGx2ZJ/v/wpBJiwONq
|
||||||
|
3Ph+9f97m7AYcHyONETzdWAgEsD7Z2qgugDkigPTJP4Ti+dU4kihIAliMFHJm66KAORP5xRdT7ByAAAA
|
||||||
|
AElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="addFileButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAiJJREFUOE+Nk+1L
|
||||||
|
U1Ecx/WP6v1e9d53azYqIogixAcoR2+UjErQIFjSWgZbLJnkbPMur+7pzm3OPXhRvDp0TndxbKV7cLt7
|
||||||
|
cGtf77ntgrVLdeBwD4f7+Xx/P845vT2dEYwdQl7/7buePusZ6rvW2/WPcymEP0e7DTRbP1FvtiA0WqBj
|
||||||
|
x5haiEjzn4K2SMfjSRgM8zjiczivNfHMuY/rln30vXB0S65WQGCS7PWxePJ4Enduj8Hl20OuUEYyVwLl
|
||||||
|
4qDT6X6vQhbIcP2iBbd3Ax+MFEZHLRgZmcUqwyJTrIn7HDQaTbeAwBekZxGu1JvgEjzs9k3M26LQ3nyK
|
||||||
|
twYr+HwVzBoHtVrdLbgKl6pNFIQGlukd+EK70L+bg83px9GpAH9gR1lQ6yRLcKWBH+UGnMuboD1x7PGn
|
||||||
|
EnzwvQKff1tZQMomcL4DZ0s1LFIBfPq8glQHTmTL8DBbygIZTqTyoFcTMJkCeHB/AtPTFimZwFymDJeX
|
||||||
|
VRbIyeFIGsWiAMZ/gMGB5xgefAlKPFIuc47tkxJod1xZQHpmuSysVgbhcBJmswe3tMOYfGXCV3dMglm+
|
||||||
|
iG+uqLKA9BzZ4qHtH8K9uzr03xjAo4fjmJlZhJc9lODocQHUyoay4KRQRfpMwNTrOYyPGWB8vwS9/gvM
|
||||||
|
Ni/Y9C84nCrAQYeVBaH1BNaCu2DEc/4464DRsAA7FZR6JmWTZAK/Ed9H10Uir4tsqlSq/5qy4BL8gXM2
|
||||||
|
KgxAeQAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="sortButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAOJJREFUOE+9UrkN
|
||||||
|
wzAM9Cbps4SnYO1RNIq7FFwirlOnzBDeQLkTSUOGAkhJEQOEbIP38Khp+seja863x56plZJm1le6umom
|
||||||
|
iYFxLoMEzzuaAVScRmAlIBhywiYCCxggWeQAk+R6kf4oRQkEMlvz9tpAYi5OOYRSHZRZNrsEMIt45/eJ
|
||||||
|
xAhiNlMoBeXkija7Z8AR6IrrUfws5xEUGj0ocfUgk9mB4T/5imJNEVQ4YFC1XfY388d+iyUPKmx3L8zn
|
||||||
|
oKoMepfGZkNVszZBdW2ggSQMjmM0QQ0RVHvlOpugRkh+6XkD9f86XlAO9kEAAAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="clearButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAh1JREFUOE+Vk1tP
|
||||||
|
E1EUhaeY8L+M/6WPPpgYYzTG6INEEo0aQBo00ShBjRhTi1UsUFqx1SLQG/RGL1AK0wu92jJnziz3Hm0k
|
||||||
|
meHBSU5mkplvrW+fyXEof687r7IYPp++O0ZGFH0wUM6Njip5313F5XI57L5TOIAvYQADAfQ0A62BgcYv
|
||||||
|
A7WOBL+/4lbhdDpti8wAIYE+wd0TgvsG6j0DVYIrLYkLs31znX9YsA/hgL4GdKi1ya1dA0dtAwcEl44l
|
||||||
|
IgmY67W7hxtjbmsIB7RZmVprXYnDtkS5SXBDYrcmkVYldg51xA90fA537QPqPQm1Y6BC8D61FutDWMc2
|
||||||
|
wTGCN/d1+NY79gEqzcvKewTnCc5WdaSOJJIViVhZxwbBP4pkEDkjoNw0UCTlPClnqqRMcIJatwj+uSfw
|
||||||
|
neBveYGP4bbV4PbzBAoE5xhW/ylvUet6iWGBNYIDOQFPyCbg5swGcqTMm5Ws/JmXlSMlHeECwbsCq1mB
|
||||||
|
5YyG919bVoPrEyFzl1k5airzvAIhgoME+7MallICizsa3gWa1oCr91cRp2ZWZng4b5BaVzICX9IaPm0L
|
||||||
|
LCQE3vhtAi6PLVqUA6ycJpiavUkNngTpxzTMLR9bDS7d8pi/aKjM8y5RKyt7qflDnODoCeY3Nbz0NawB
|
||||||
|
F6/N48nbFFxzSTyejWHqRRTTzyKYehrG5MwaJqaDeDTpx/iDBYzf89qfBz5p/7P4WP8G/jqMg6Vn2nUA
|
||||||
|
AAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class Mp4Encoder : ProcessStreamWrapper
|
||||||
|
{
|
||||||
|
public Mp4Encoder(Mp4EncodingOptions encOpt) : base(encOpt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mp4Encoder(Mp4EncodingOptions encOpt, Stream outputStream)
|
||||||
|
: base(encOpt, outputStream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ProcessExecutableFilename
|
||||||
|
{
|
||||||
|
get { return "faac.exe"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,527 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///FAAC 1.24.1 (May 17 2005) UNSTABLE
|
||||||
|
///
|
||||||
|
///Usage: faac [options] infiles ...
|
||||||
|
///Options:
|
||||||
|
/// -q <quality> Set quantizer quality.
|
||||||
|
/// -b <bitrate> Set average bitrate to x kbps. (ABR, lower quality mode)
|
||||||
|
/// -c <freq> Set the bandwidth in Hz. (default=automatic)
|
||||||
|
/// -o X Set output file to X (only for one input file)
|
||||||
|
/// -r Use RAW AAC output file.
|
||||||
|
/// -P Raw PCM input mode (default 44100Hz 16bit stereo).
|
||||||
|
/// -R Raw PCM input rate.
|
||||||
|
/// -B Raw PCM input sample size (8, 16 (default), 24 or 32bits).
|
||||||
|
/// -C Raw PCM input channels.
|
||||||
|
/// -X Raw PCM swap input bytes
|
||||||
|
/// -I <C,LF> Input channel config, default is 3,4 (Center third, LF fourth)
|
||||||
|
///
|
||||||
|
///MP4 specific options:
|
||||||
|
/// -w Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a)
|
||||||
|
/// --artist X Set artist to X
|
||||||
|
/// --writer X Set writer to X
|
||||||
|
/// --title X Set title to X
|
||||||
|
/// --genre X Set genre to X
|
||||||
|
/// --album X Set album to X
|
||||||
|
/// --compilation Set compilation
|
||||||
|
/// --track X Set track to X (number/total)
|
||||||
|
/// --disc X Set disc to X (number/total)
|
||||||
|
/// --year X Set year to X
|
||||||
|
/// --cover-art X Read cover art from file X
|
||||||
|
/// --comment X Set comment to X
|
||||||
|
/// </summary>
|
||||||
|
public class Mp4EncodingOptions : ProcessArguments
|
||||||
|
{
|
||||||
|
#region Private variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Files to use for input
|
||||||
|
/// </summary>
|
||||||
|
private string[] mInfiles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Quantinizer Quality -q [quality]
|
||||||
|
/// </summary>
|
||||||
|
private int mQuantinizerQuality = int.MinValue;
|
||||||
|
/// <summary>
|
||||||
|
/// BitRate -b [bitrate]
|
||||||
|
/// </summary>
|
||||||
|
private int mBitrate = int.MinValue;
|
||||||
|
/// <summary>
|
||||||
|
/// The bandwidth in Hz -c [freq]
|
||||||
|
/// </summary>
|
||||||
|
private SampleRateFrequency mBandwidth = SampleRateFrequency.Hz_0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output filename (only for one input file) -o [filename]
|
||||||
|
/// </summary>
|
||||||
|
private string mOutputFilename = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use RAW AAC output file -r
|
||||||
|
/// </summary>
|
||||||
|
private bool mRawAACOutputFile = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input mode (default 44100Hz 16bit stereo) -P
|
||||||
|
/// </summary>
|
||||||
|
private bool mRawPCMInputMode = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCMInputSampleSize (default 44100Hz 16bit stereo) -R
|
||||||
|
/// </summary>
|
||||||
|
private SampleRateFrequency mRawPCMInputSampleSize = SampleRateFrequency.Hz_44100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input rate (default 16) -B
|
||||||
|
/// </summary>
|
||||||
|
private int mRawPCMInputSampleRate = 16;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input channels -C
|
||||||
|
/// </summary>
|
||||||
|
private ChannelMode mRawInputChannels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM swap input bytes -X
|
||||||
|
/// </summary>
|
||||||
|
private bool mRawPCMSwapInputBytes = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a) -w
|
||||||
|
/// </summary>
|
||||||
|
private bool mWrapAACDataInMp4 = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set artist to X --artist X
|
||||||
|
/// </summary>
|
||||||
|
private string mArtist = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set writer to X --writer X
|
||||||
|
/// </summary>
|
||||||
|
private string mWriter = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set title to X --title X
|
||||||
|
/// </summary>
|
||||||
|
private string mTitle = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set genre to X --genre X
|
||||||
|
/// </summary>
|
||||||
|
private string mGenre = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set album to X --album X
|
||||||
|
/// </summary>
|
||||||
|
private string mAlbum = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set compilation --compilation
|
||||||
|
/// </summary>
|
||||||
|
private string mCompilation = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set track to X (number/total) --track X
|
||||||
|
/// </summary>
|
||||||
|
private string mTrack = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set disc to X (number/total) --disc X
|
||||||
|
/// </summary>
|
||||||
|
private string mDisc = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set year to X --year X
|
||||||
|
/// </summary>
|
||||||
|
private int mYear = int.MinValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load cover art from filename --cover-art X
|
||||||
|
/// </summary>
|
||||||
|
private string mCoverArtFilename = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set comment to X --comment X
|
||||||
|
/// </summary>
|
||||||
|
private string mComment = null;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the input files.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The input files.</value>
|
||||||
|
public string[] InputFiles
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mInfiles == null)
|
||||||
|
return new string[]{};
|
||||||
|
return mInfiles;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mInfiles = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Quantinizer Quality -q [quality]
|
||||||
|
/// </summary>
|
||||||
|
public int QuantinizerQuality
|
||||||
|
{
|
||||||
|
get { return mQuantinizerQuality; }
|
||||||
|
set { mQuantinizerQuality = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// BitRate -b [bitrate]
|
||||||
|
/// </summary>
|
||||||
|
public int Bitrate
|
||||||
|
{
|
||||||
|
get { return mBitrate; }
|
||||||
|
set { mBitrate = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bandwidth in Hz -c [freq]
|
||||||
|
/// </summary>
|
||||||
|
public SampleRateFrequency Bandwidth
|
||||||
|
{
|
||||||
|
get { return mBandwidth; }
|
||||||
|
set { mBandwidth = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output filename (only for one input file) -o [filename]
|
||||||
|
/// </summary>
|
||||||
|
public string OutputFilename
|
||||||
|
{
|
||||||
|
get { return mOutputFilename; }
|
||||||
|
set { mOutputFilename = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use RAW AAC output file -r
|
||||||
|
/// </summary>
|
||||||
|
public bool RawAACOutputFile
|
||||||
|
{
|
||||||
|
get { return mRawAACOutputFile; }
|
||||||
|
set { mRawAACOutputFile = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input mode (default 44100Hz 16bit stereo) -P
|
||||||
|
/// </summary>
|
||||||
|
public bool RawPCMInputMode
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputMode; }
|
||||||
|
set { mRawPCMInputMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCMInputSampleSize -R
|
||||||
|
/// </summary>
|
||||||
|
public SampleRateFrequency RawPCMInputSampleSize
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleSize; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleSize = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input rate (default 16) -B
|
||||||
|
/// </summary>
|
||||||
|
public int RawPCMInputSampleRate
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleRate; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleRate = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input channels -C
|
||||||
|
/// </summary>
|
||||||
|
public ChannelMode RawInputChannels
|
||||||
|
{
|
||||||
|
get { return mRawInputChannels; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawInputChannels = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM swap input bytes -X
|
||||||
|
/// </summary>
|
||||||
|
public bool RawPCMSwapInputBytes
|
||||||
|
{
|
||||||
|
get { return mRawPCMSwapInputBytes; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMSwapInputBytes = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a)
|
||||||
|
/// </summary>
|
||||||
|
public bool WrapAACDataInMp4
|
||||||
|
{
|
||||||
|
get { return mWrapAACDataInMp4; }
|
||||||
|
set { mWrapAACDataInMp4 = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set artist to X
|
||||||
|
/// </summary>
|
||||||
|
public string Artist
|
||||||
|
{
|
||||||
|
get { return mArtist; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mArtist = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set writer to X
|
||||||
|
/// </summary>
|
||||||
|
public string Writer
|
||||||
|
{
|
||||||
|
get { return mWriter; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mWriter = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set title to X
|
||||||
|
/// </summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get { return mTitle; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mTitle = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set genre to X
|
||||||
|
/// </summary>
|
||||||
|
public string Genre
|
||||||
|
{
|
||||||
|
get { return mGenre; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mGenre = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set album to X
|
||||||
|
/// </summary>
|
||||||
|
public string Album
|
||||||
|
{
|
||||||
|
get { return mAlbum; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mAlbum = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set compilation
|
||||||
|
/// </summary>
|
||||||
|
public string Compilation
|
||||||
|
{
|
||||||
|
get { return mCompilation; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mCompilation = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set track to X (number/total)
|
||||||
|
/// </summary>
|
||||||
|
public string Track
|
||||||
|
{
|
||||||
|
get { return mTrack; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mTrack = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set disc to X (number/total)
|
||||||
|
/// </summary>
|
||||||
|
public string Disc
|
||||||
|
{
|
||||||
|
get { return mDisc; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mDisc = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set year to X
|
||||||
|
/// </summary>
|
||||||
|
public int Year
|
||||||
|
{
|
||||||
|
get { return mYear; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mYear = value;
|
||||||
|
if (value != int.MinValue)
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load cover art from filename
|
||||||
|
/// </summary>
|
||||||
|
public string CoverArtFilename
|
||||||
|
{
|
||||||
|
get { return mCoverArtFilename; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mCoverArtFilename = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Quantinizer Quality -q [quality]
|
||||||
|
/// </summary>
|
||||||
|
public string Comment
|
||||||
|
{
|
||||||
|
get { return mComment; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mComment = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representing the command line arguments specified by the properties in the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override string GetCommandLineArguments()
|
||||||
|
{
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
if (mQuantinizerQuality != int.MinValue)
|
||||||
|
stringBuilder.Append(" -q " + mQuantinizerQuality);
|
||||||
|
if (mBitrate != int.MinValue)
|
||||||
|
stringBuilder.Append(" -b " + mBitrate);
|
||||||
|
if (mBandwidth != SampleRateFrequency.Hz_0)
|
||||||
|
stringBuilder.Append(" -c " + SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mBandwidth));
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(mOutputFilename))
|
||||||
|
{
|
||||||
|
if (mOutputFilename.Trim() == "-")
|
||||||
|
stringBuilder.Append(" -o-");
|
||||||
|
else
|
||||||
|
stringBuilder.Append(" -o " + GetQuotedCommandLineArgument(mOutputFilename));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stringBuilder.Append(" -o-");
|
||||||
|
|
||||||
|
if (mRawPCMInputMode)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" -P ");
|
||||||
|
if (mRawPCMInputSampleSize != SampleRateFrequency.Hz_44100)
|
||||||
|
stringBuilder.Append(" -R " + SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mRawPCMInputSampleSize));
|
||||||
|
if (mRawPCMInputSampleRate != 16)
|
||||||
|
stringBuilder.Append(" -B " + mRawPCMInputSampleRate);
|
||||||
|
int chanelMode = ChannelModeUtility.GetChannelModeInt(mRawInputChannels);
|
||||||
|
if (chanelMode != 2)
|
||||||
|
stringBuilder.Append(" -C " + chanelMode);
|
||||||
|
if (mRawPCMSwapInputBytes)
|
||||||
|
stringBuilder.Append(" -X ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mWrapAACDataInMp4)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" -w ");
|
||||||
|
if (!string.IsNullOrEmpty(mArtist))
|
||||||
|
stringBuilder.Append(" --artist " + mArtist);
|
||||||
|
if (!string.IsNullOrEmpty(mWriter))
|
||||||
|
stringBuilder.Append(" --writer " + mWriter);
|
||||||
|
if (!string.IsNullOrEmpty(mTitle))
|
||||||
|
stringBuilder.Append(" --title " + mTitle);
|
||||||
|
if (!string.IsNullOrEmpty(mGenre))
|
||||||
|
stringBuilder.Append(" --genre " + mGenre);
|
||||||
|
if (!string.IsNullOrEmpty(mAlbum))
|
||||||
|
stringBuilder.Append(" --album " + mAlbum);
|
||||||
|
if (!string.IsNullOrEmpty(mCompilation))
|
||||||
|
stringBuilder.Append(" --compilation " + mCompilation);
|
||||||
|
if (!string.IsNullOrEmpty(mTrack))
|
||||||
|
stringBuilder.Append(" --track " + mTrack);
|
||||||
|
if (!string.IsNullOrEmpty(mDisc))
|
||||||
|
stringBuilder.Append(" --disc " + mDisc);
|
||||||
|
if (mYear != int.MinValue)
|
||||||
|
stringBuilder.Append(" --year " + mYear);
|
||||||
|
if (!string.IsNullOrEmpty(mCoverArtFilename))
|
||||||
|
stringBuilder.Append(" --cover-art " + mCoverArtFilename);
|
||||||
|
if (!string.IsNullOrEmpty(mComment))
|
||||||
|
stringBuilder.Append(" --comment " + mComment);
|
||||||
|
}
|
||||||
|
if (mInfiles != null && mInfiles.Length > 0)
|
||||||
|
{
|
||||||
|
// use standard input
|
||||||
|
if (mInfiles[0].Trim() == "-")
|
||||||
|
stringBuilder.Append(" -");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (string infile in mInfiles)
|
||||||
|
stringBuilder.Append(" " + GetQuotedCommandLineArgument(infile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stringBuilder.Append(" -");
|
||||||
|
|
||||||
|
|
||||||
|
return stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class ProcessArguments
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representing the command line arguments specified by the properties in the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual string GetCommandLineArguments()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string GetQuotedCommandLineArgument(string argument)
|
||||||
|
{
|
||||||
|
if (argument.Contains(" ") || argument.Contains("\t"))
|
||||||
|
{
|
||||||
|
return "\"" + argument + "\"";
|
||||||
|
}
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A generic encoder. Creates an external process, sends it argument options,
|
||||||
|
/// and acts as a wrapper for streaming reads and writes
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ProcessStreamWrapper : IDisposable
|
||||||
|
{
|
||||||
|
#region Protected Variables
|
||||||
|
/// <summary>
|
||||||
|
/// The arguments to use for the process
|
||||||
|
/// </summary>
|
||||||
|
protected ProcessArguments mProcessArguments;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The process
|
||||||
|
/// </summary>
|
||||||
|
protected Process mProcess;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much data to buffer when reading and writing
|
||||||
|
/// </summary>
|
||||||
|
protected const int mBufferLength = 1000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output stream writer. If it is null, it is assumed
|
||||||
|
/// that the process will take care of output itself.
|
||||||
|
/// </summary>
|
||||||
|
protected StreamWriter mOutputStreamWriter = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Progress call-back, for status updates outside this class.
|
||||||
|
/// </summary>
|
||||||
|
protected IProgressCallback mProgressCallback = new DoNothingProgressCallback();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The progress callback.</value>
|
||||||
|
public IProgressCallback ProgressCallback
|
||||||
|
{
|
||||||
|
get { return mProgressCallback; }
|
||||||
|
set { mProgressCallback = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the process executable filename, such as "LAME.EXE", "FAAC.EXE", etc.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The process executable filename.</value>
|
||||||
|
protected abstract string ProcessExecutableFilename
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ProcessStreamWrapper"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encOpt">The enc opt.</param>
|
||||||
|
public ProcessStreamWrapper(ProcessArguments encOpt) : this (encOpt, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ProcessStreamWrapper"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encOpt">The enc opt.</param>
|
||||||
|
/// <param name="outputStream">Output to this stream</param>
|
||||||
|
public ProcessStreamWrapper(ProcessArguments encOpt, Stream outputStream)
|
||||||
|
{
|
||||||
|
mProcessArguments = encOpt;
|
||||||
|
|
||||||
|
mProcess = CreateProcess(mProcessArguments, ProcessExecutableFilename);
|
||||||
|
if (outputStream != null)
|
||||||
|
{
|
||||||
|
mOutputStreamWriter = new StreamWriter(outputStream, Encoding.Default);
|
||||||
|
mProcess.StartInfo.RedirectStandardOutput = true;
|
||||||
|
mProcess.StartInfo.StandardOutputEncoding = Encoding.Default;
|
||||||
|
}
|
||||||
|
mProcess.StartInfo.RedirectStandardError = true;
|
||||||
|
|
||||||
|
mProcess.Exited += new EventHandler(Process_Exited);
|
||||||
|
mProcess.Start();
|
||||||
|
if (mOutputStreamWriter != null)
|
||||||
|
{
|
||||||
|
Thread thread = new Thread(new ThreadStart(GetStandardOutput));
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread standardErrorThread = new Thread(new ThreadStart(GetStandardError));
|
||||||
|
standardErrorThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Static methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a process given an executable and some process arguments
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="processArguments">The enc opt.</param>
|
||||||
|
/// <param name="executable">The executable filename.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static Process CreateProcess(ProcessArguments processArguments, string executable)
|
||||||
|
{
|
||||||
|
Process process = new Process();
|
||||||
|
process.StartInfo.RedirectStandardInput = true;
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.FileName = executable;
|
||||||
|
process.StartInfo.Arguments = processArguments.GetCommandLineArguments();
|
||||||
|
process.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
|
||||||
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
|
||||||
|
process.EnableRaisingEvents = true;
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event handlers
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the Exited event of the Process.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The source of the event.</param>
|
||||||
|
/// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
|
||||||
|
void Process_Exited(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText("Process_Exited");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Utility methods
|
||||||
|
|
||||||
|
private static int GetPercentDone(long previousLeft, long currentLeft, long currentDone, int lastDone)
|
||||||
|
{
|
||||||
|
// if currentLeft > previousLeft - lastDone,
|
||||||
|
// addedLeft = previousLeft - lastDone - currentLeft
|
||||||
|
// totalLength = previousLeft + currentDone + addedLeft
|
||||||
|
|
||||||
|
long totalLength = currentLeft;
|
||||||
|
if (currentLeft != previousLeft)
|
||||||
|
{
|
||||||
|
long leftDelta = previousLeft - lastDone - currentLeft;
|
||||||
|
totalLength = previousLeft + currentDone + leftDelta;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Convert.ToInt32((currentDone / (double)totalLength) * 100);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the data to the underlying process through its input stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The data to encode</param>
|
||||||
|
/// <param name="count">How many characters to write</param>
|
||||||
|
/// <param name="startIndex">The index to begin writing from</param>
|
||||||
|
public void ProcessInput(char[] buffer, int startIndex, int count)
|
||||||
|
{
|
||||||
|
mProcess.StandardInput.Write(buffer, startIndex, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the data from the input stream to the process
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputStream"></param>
|
||||||
|
public void ProcessInput(Stream inputStream)
|
||||||
|
{
|
||||||
|
if (!inputStream.CanRead)
|
||||||
|
throw new ArgumentException("Can't read from inputStream");
|
||||||
|
|
||||||
|
mProgressCallback.SetText("ProcessInput: StreamReader sr");
|
||||||
|
|
||||||
|
long inputCount = inputStream.Length;
|
||||||
|
long previousInputCount = inputStream.Length;
|
||||||
|
long wroteCount = 0;
|
||||||
|
int percentageComplete = 0;
|
||||||
|
|
||||||
|
StreamReader sr = new StreamReader(inputStream, Encoding.Default);
|
||||||
|
//using (StreamReader sr = new StreamReader(inputStream, Encoding.Default))
|
||||||
|
{
|
||||||
|
mProgressCallback.Begin(0, 100);
|
||||||
|
mProgressCallback.SetText(mProcessArguments.GetCommandLineArguments());
|
||||||
|
|
||||||
|
char[] buffer = new char[mBufferLength];
|
||||||
|
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
int readLength = sr.Read(buffer, 0, mBufferLength);
|
||||||
|
ProcessInput(buffer, 0, readLength);
|
||||||
|
|
||||||
|
// update progress
|
||||||
|
wroteCount += readLength;
|
||||||
|
previousInputCount = inputCount;
|
||||||
|
inputCount = inputStream.Length;
|
||||||
|
int currentPercentageComplete = GetPercentDone(previousInputCount, inputCount, wroteCount, readLength);
|
||||||
|
if (currentPercentageComplete != percentageComplete)
|
||||||
|
{
|
||||||
|
percentageComplete = currentPercentageComplete;
|
||||||
|
mProgressCallback.StepTo(percentageComplete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mInputDone = true;
|
||||||
|
mProgressCallback.SetText("ProcessInput: Done. " + String.Format("Wrote: {0}", wroteCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open this file and encode it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename"></param>
|
||||||
|
public void ProcessInput(string filename)
|
||||||
|
{
|
||||||
|
using (FileStream inputStream = File.OpenRead(filename))
|
||||||
|
{
|
||||||
|
ProcessInput(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Threaded methods
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TEMP: this should be removed once GetStandardOutput is working
|
||||||
|
/// </summary>
|
||||||
|
bool mInputDone = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collects all the data from Process.StandardOutput and sends it to the outputstream writer
|
||||||
|
/// </summary>
|
||||||
|
private void GetStandardOutput()
|
||||||
|
{
|
||||||
|
int readTotal = 0;
|
||||||
|
char[] writeBuffer = new char[mBufferLength];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!mProcess.StandardOutput.EndOfStream)
|
||||||
|
//while (mProcess.StandardOutput.Peek() > -1)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText("- Before read");
|
||||||
|
int readLength = mProcess.StandardOutput.Read(writeBuffer, 0, writeBuffer.Length);
|
||||||
|
mProgressCallback.SetText("- After read: " + readLength);
|
||||||
|
mOutputStreamWriter.Write(writeBuffer, 0, readLength);
|
||||||
|
if (mInputDone)
|
||||||
|
mProgressCallback.SetText(" StandardOutput: " + new string(writeBuffer, 0, readLength));
|
||||||
|
readTotal += readLength;
|
||||||
|
mProgressCallback.SetText("Read total = " + readTotal);
|
||||||
|
|
||||||
|
//mProcess.StandardInput.Flush();
|
||||||
|
//mProcess.StandardOutput.BaseStream.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText(ex.ToString());
|
||||||
|
}
|
||||||
|
// mOutputStreamWriter.Flush();
|
||||||
|
mProgressCallback.SetText("GetStandardOutput() " + "Done!" + " StandardOutput.EndOfStream = " + mProcess.StandardOutput.EndOfStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Asynchronous implementation of GetStandardOutput
|
||||||
|
//int mReadTotal = 0;
|
||||||
|
//private byte[] mBuffer = new byte[mBufferLength];
|
||||||
|
//private void GetStandardOutputAsync()
|
||||||
|
//{
|
||||||
|
// mProcess.StandardOutput.BaseStream.BeginRead(mBuffer, 0, mBufferLength, GetStandardOutputCallback, 0);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private void GetStandardOutputCallback(IAsyncResult asyncResult)
|
||||||
|
//{
|
||||||
|
// mProgressCallback.SetText("- Before read:");
|
||||||
|
// int readLength = mProcess.StandardOutput.BaseStream.EndRead(asyncResult);
|
||||||
|
// mProgressCallback.SetText("- After read:" + readLength);
|
||||||
|
// mOutputStreamWriter.BaseStream.Write(mBuffer, 0, readLength);
|
||||||
|
// mReadTotal += readLength;
|
||||||
|
// mProgressCallback.SetText("Read total = " + mReadTotal);
|
||||||
|
// mProcess.StandardOutput.BaseStream.BeginRead(mBuffer, 0, mBufferLength, GetStandardOutputCallback, 0);
|
||||||
|
//}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collects all the data from Process.StandardError and sends it to the progress callback
|
||||||
|
/// </summary>
|
||||||
|
private void GetStandardError()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!mProcess.StandardError.EndOfStream)
|
||||||
|
{
|
||||||
|
string line = mProcess.StandardError.ReadLine();
|
||||||
|
mProgressCallback.SetText("GetStandardError() " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText(ex.ToString());
|
||||||
|
}
|
||||||
|
mProgressCallback.SetText("GetStandardError() " + "Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
mProgressCallback.SetText("Dispose()");
|
||||||
|
while (mProcess != null && !mProcess.HasExited)
|
||||||
|
{
|
||||||
|
mProcess.WaitForExit(2);
|
||||||
|
if (count++ > mBufferLength && !mProcess.HasExited)
|
||||||
|
{
|
||||||
|
mProcess.Kill();
|
||||||
|
mProgressCallback.SetText("!!! Process.Kill()");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mProgressCallback.SetText("Writing EOF");
|
||||||
|
mProcess.StandardInput.Write(new string(new char[] { (char)0x1A, '\n' }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mProgressCallback.SetText("Dispose() with exit code " + mProcess.ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+63
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:2.0.50727.42
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace m3uTool.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("m3uTool.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum Redirect
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Do not redirect anything
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Redirect standard input
|
||||||
|
/// </summary>
|
||||||
|
StandardInput = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Redirect standard output
|
||||||
|
/// </summary>
|
||||||
|
StandardOutput = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Redirect standart error
|
||||||
|
/// </summary>
|
||||||
|
StandardError = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace StdinToStdout
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simply takes anything from standard input and writes it directly to standard output.
|
||||||
|
/// </summary>
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Stream inputStream = Console.OpenStandardInput(1);
|
||||||
|
Stream outputStream = Console.OpenStandardOutput(1);
|
||||||
|
// Stream errorStream = Console.OpenStandardError();
|
||||||
|
using (StreamReader sr = new StreamReader(inputStream, Encoding.Default))
|
||||||
|
using (StreamWriter sw = new StreamWriter(outputStream, Encoding.Default))
|
||||||
|
{
|
||||||
|
char[] buffer = new char[1];
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
int readLength = sr.Read(buffer, 0, 1);
|
||||||
|
sw.Write(buffer, 0, readLength);
|
||||||
|
}
|
||||||
|
inputStream.Flush();
|
||||||
|
outputStream.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("StdinToStdout")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("StdinToStdout")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2006")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("63522965-dbbf-40a5-a4d3-5ed1ec25b611")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.50727</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{94C7033C-C8A8-4104-95FE-0D11122080E2}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>StdinToStdout</RootNamespace>
|
||||||
|
<AssemblyName>StdinToStdout</AssemblyName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for CreateM3uTest.
|
||||||
|
/// </summary>
|
||||||
|
public class CreateM3uTests
|
||||||
|
{
|
||||||
|
public void CreateM3uTest()
|
||||||
|
{
|
||||||
|
M3uCreate c = new M3uCreate(new DirectoryInfo(@"C:\mp3\"));
|
||||||
|
// c.OutputFilename = @"c:\mym3u.m3u";
|
||||||
|
Debug.WriteLine(c.OutputFilename);
|
||||||
|
c.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateSubM3uTest()
|
||||||
|
{
|
||||||
|
DirectoryInfo rootDir = new DirectoryInfo(@"C:\mp3\");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
foreach (DirectoryInfo subDir in rootDir.GetDirectories())
|
||||||
|
{
|
||||||
|
M3uCreate c = new M3uCreate(subDir);
|
||||||
|
|
||||||
|
Debug.WriteLine(c.OutputFilename);
|
||||||
|
c.Create();
|
||||||
|
|
||||||
|
if (count++ > 10)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// c.OutputFilename = @"c:\mym3u.m3u";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Win32
|
||||||
|
{
|
||||||
|
internal class HiPerfTimer
|
||||||
|
{
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
private static extern bool QueryPerformanceCounter(
|
||||||
|
out long lpPerformanceCount);
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
private static extern bool QueryPerformanceFrequency(
|
||||||
|
out long lpFrequency);
|
||||||
|
|
||||||
|
private long startTime, stopTime;
|
||||||
|
private long freq;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public HiPerfTimer()
|
||||||
|
{
|
||||||
|
startTime = 0;
|
||||||
|
stopTime = 0;
|
||||||
|
|
||||||
|
if (QueryPerformanceFrequency(out freq) == false)
|
||||||
|
{
|
||||||
|
// high-performance counter not supported
|
||||||
|
throw new Win32Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the timer
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
// lets do the waiting threads there work
|
||||||
|
Thread.Sleep(0);
|
||||||
|
|
||||||
|
QueryPerformanceCounter(out startTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the timer
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
QueryPerformanceCounter(out stopTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the duration of the timer (in seconds)
|
||||||
|
public double Duration
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (double)(stopTime - startTime) / (double)freq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class LongestCommonSequenceTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void FunctionalityTest()
|
||||||
|
{
|
||||||
|
//LongestCommonSequence<string> lcs = new LongestCommonSequence<string>();
|
||||||
|
//Debug.WriteLine(new string(lcs.LCS("what do we say", "heya".ToCharArray())));
|
||||||
|
|
||||||
|
List<string> substring = LongestCommonSubstrings.GetLongestSubstring("ABAB", "BABA");
|
||||||
|
Assert.AreEqual(2, substring.Count);
|
||||||
|
Assert.IsTrue(substring.Contains("ABA"));
|
||||||
|
Assert.IsTrue(substring.Contains("BAB"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class Mp3EncoderTests : ProgressCallbackTestBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void StreamingVsOutputMp3EncodingTest()
|
||||||
|
{
|
||||||
|
//String inputWav = "44_16_s.wav";
|
||||||
|
String inputWav = "test1.wav";
|
||||||
|
String outputOptionEncodedMp3 = "outputOptionEncodedMp3.mp3";
|
||||||
|
String streamingEncodedMp3 = "streamingEncodedMp3.mp3";
|
||||||
|
|
||||||
|
Mp3EncodingOptions encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(streamingEncodedMp3, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fs))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(inputWav);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encOpts.Outfile = outputOptionEncodedMp3;
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(inputWav);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mp3FileProperties outputOptionProperties = new Mp3FileProperties(outputOptionEncodedMp3);
|
||||||
|
Mp3FileProperties streamingProperties = new Mp3FileProperties(streamingEncodedMp3);
|
||||||
|
Assert.AreEqual(outputOptionProperties.LengthInSeconds, streamingProperties.LengthInSeconds);
|
||||||
|
|
||||||
|
// FilesAreEqual(outputOptionFileInfo, streamingFileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void StreamingVsOutputMp3DecodingTest()
|
||||||
|
{
|
||||||
|
String input = "44_16_s.mp3";
|
||||||
|
String outputOptionDecoded = "outputOptionDecoded.wav";
|
||||||
|
String streamingDecoded = "streamingDecode.wav";
|
||||||
|
|
||||||
|
Mp3EncodingOptions encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
encOpts.Mp3Input = true;
|
||||||
|
encOpts.DecodeWav = true;
|
||||||
|
|
||||||
|
using (FileStream fileStream = new FileStream(streamingDecoded, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encOpts.Outfile = outputOptionDecoded;
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInfo outputOptionFileInfo = new FileInfo(outputOptionDecoded);
|
||||||
|
FileInfo streamingFileInfo = new FileInfo(streamingDecoded);
|
||||||
|
|
||||||
|
FilesAreEqual(outputOptionFileInfo, streamingFileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FilesAreEqual(FileInfo file1, FileInfo file2)
|
||||||
|
{
|
||||||
|
//Assert.AreEqual(file1.Length, file2.Length);
|
||||||
|
|
||||||
|
int filePosition = 0;
|
||||||
|
using (FileStream outputOptionFs = file1.OpenRead())
|
||||||
|
using (StreamReader outputOptionSr = new StreamReader(outputOptionFs))
|
||||||
|
using (FileStream streamingFs = file2.OpenRead())
|
||||||
|
using (StreamReader streamingSr = new StreamReader(streamingFs))
|
||||||
|
{
|
||||||
|
char[] outputOptionBuffer = new char[4096];
|
||||||
|
char[] streamingBuffer = new char[4096];
|
||||||
|
|
||||||
|
while (!outputOptionSr.EndOfStream)
|
||||||
|
{
|
||||||
|
int outputOptionReadLength = outputOptionSr.Read(outputOptionBuffer, 0, outputOptionBuffer.Length);
|
||||||
|
int streamingReadLength = streamingSr.Read(streamingBuffer, 0, streamingBuffer.Length);
|
||||||
|
|
||||||
|
Assert.AreEqual(outputOptionReadLength, streamingReadLength);
|
||||||
|
Assert.AreEqual(outputOptionBuffer, streamingBuffer, "offset : " + filePosition);
|
||||||
|
filePosition += outputOptionBuffer.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests this instance.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void StreamingTest()
|
||||||
|
{
|
||||||
|
String inputWav = "44_16_s.wav";
|
||||||
|
String encodedMp3 = "encodedMp3.mp3";
|
||||||
|
String decodedWav = "decodedWav.wav";
|
||||||
|
String reencodedMp3 = "reencodedMp3.mp3";
|
||||||
|
|
||||||
|
using (FileStream fileStream = new FileStream(encodedMp3, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
Mp3EncodingOptions encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(inputWav);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.WriteLine("Finished writing " + encodedMp3);
|
||||||
|
|
||||||
|
Debug.WriteLine("Begin writing " + decodedWav);
|
||||||
|
using (FileStream fileStream = new FileStream(decodedWav, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
Mp3EncodingOptions wavOpts = new Mp3EncodingOptions();
|
||||||
|
wavOpts.Infile = "-";
|
||||||
|
wavOpts.Outfile = "-";
|
||||||
|
// wavOpts.MonoDownmixing = true;
|
||||||
|
wavOpts.Mp3Input = true;
|
||||||
|
wavOpts.DecodeWav = true;
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(wavOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(encodedMp3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.WriteLine("Finished writing " + decodedWav);
|
||||||
|
|
||||||
|
using (FileStream fileStream = new FileStream(reencodedMp3, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
Mp3EncodingOptions encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(decodedWav);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mp3FileProperties reencodedProperties = new Mp3FileProperties(reencodedMp3);
|
||||||
|
Mp3FileProperties encodedProperties = new Mp3FileProperties(encodedMp3);
|
||||||
|
Assert.AreEqual(encodedProperties.FileLength, reencodedProperties.FileLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
public override void StepTo(int val)
|
||||||
|
{
|
||||||
|
if (val % 10 == 0)
|
||||||
|
base.StepTo(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class Mp3EncodingOptionsTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void Mp3EncodingOptionsTest()
|
||||||
|
{
|
||||||
|
Mp3EncodingOptions e = new Mp3EncodingOptions();
|
||||||
|
e.ChannelMode = ChannelMode.SingleChannel;
|
||||||
|
e.Infile = "-";
|
||||||
|
string arguments = e.GetCommandLineArguments();
|
||||||
|
Debug.WriteLine(arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for MP3HeaderTests.
|
||||||
|
/// </summary>
|
||||||
|
public class Mp3FilePropertiesTests
|
||||||
|
{
|
||||||
|
|
||||||
|
public void Mp3FileDetailsTest()
|
||||||
|
{
|
||||||
|
string[] files = Directory.GetFiles(".", "*.mp3");
|
||||||
|
List<Mp3FileProperties> properties = new List<Mp3FileProperties>();
|
||||||
|
foreach (string mp3Filename in files)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mp3Filename);
|
||||||
|
Debug.Indent();
|
||||||
|
|
||||||
|
// bool boolIsMP3 = mp3hdr.ReadMP3Information(mp3Filename);
|
||||||
|
Mp3FileProperties fileDetails = new Mp3FileProperties(mp3Filename);
|
||||||
|
properties.Add(fileDetails);
|
||||||
|
if (fileDetails != null)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(GetMp3FilePropertyReport(fileDetails));
|
||||||
|
}
|
||||||
|
Debug.Unindent();
|
||||||
|
}
|
||||||
|
Mp3FileProperties commonProperties = Mp3FileProperties.GetCommonProperties(properties);
|
||||||
|
Debug.WriteLine(GetMp3FilePropertyReport(commonProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetMp3FilePropertyReport(Mp3FileProperties fileDetails)
|
||||||
|
{
|
||||||
|
StringBuilder report = new StringBuilder();
|
||||||
|
report.AppendLine("Filename: " + fileDetails.Mp3PathAndFilename);
|
||||||
|
report.AppendLine("mFileSize: " + fileDetails.FileSize.ToString());
|
||||||
|
report.AppendLine("mBitRate: " + fileDetails.BitRate.ToString());
|
||||||
|
report.AppendLine("mSampleRateIntegerFrequency:" + fileDetails.SampleRateIntegerFrequency.ToString());
|
||||||
|
report.AppendLine("strMode: " + fileDetails.ChannelMode);
|
||||||
|
report.AppendLine("strLengthFo: " + fileDetails.LengthFormatted);
|
||||||
|
report.AppendLine("mLengthInSeconds: " + fileDetails.LengthInSeconds.ToString());
|
||||||
|
|
||||||
|
report.AppendLine("title: " + fileDetails.Id3Title);
|
||||||
|
report.AppendLine("artist: " + fileDetails.Id3Artist);
|
||||||
|
report.AppendLine("album: " + fileDetails.Id3Album);
|
||||||
|
report.AppendLine("track#: " + fileDetails.Id3TrackNumber);
|
||||||
|
report.AppendLine("genre: " + fileDetails.Id3GenreName);
|
||||||
|
return report.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Media;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class Mp4EncoderTests : ProgressCallbackTestBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tests Encoding an Mp4 file.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void Test()
|
||||||
|
{
|
||||||
|
Mp4EncodingOptions encOpts = new Mp4EncodingOptions();
|
||||||
|
encOpts.OutputFilename = "44_16_s_opts.aac";
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp4Encoder(encOpts))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput("44_16_s.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
public override void StepTo(int val)
|
||||||
|
{
|
||||||
|
if (val%10 == 0)
|
||||||
|
base.StepTo(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class Mp4EncodingOptionsTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Mp4EncodingOptionsTest()
|
||||||
|
{
|
||||||
|
Mp4EncodingOptions e = new Mp4EncodingOptions();
|
||||||
|
e.RawInputChannels = ChannelMode.SingleChannel;
|
||||||
|
string arguments = e.GetCommandLineArguments();
|
||||||
|
Debug.WriteLine(arguments);
|
||||||
|
|
||||||
|
e = new Mp4EncodingOptions();
|
||||||
|
e.OutputFilename = "har";
|
||||||
|
Debug.WriteLine(e.GetCommandLineArguments());
|
||||||
|
|
||||||
|
e.InputFiles = new string[]{"input.txt"};
|
||||||
|
Debug.WriteLine(e.GetCommandLineArguments());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ProcessStreamWrapperTests : ProgressCallbackTestBase
|
||||||
|
{
|
||||||
|
private class StdinToStdoutProcess : ProcessStreamWrapper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the process executable filename, such as "LAME.EXE", "FAAC.EXE", etc.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The process executable filename.</value>
|
||||||
|
protected override string ProcessExecutableFilename
|
||||||
|
{
|
||||||
|
get { return "StdinToStdout.exe"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StdinToStdoutProcess(ProcessArguments encOpt, Stream outputStream)
|
||||||
|
: base(encOpt, outputStream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ProcessStreamWrapperFunctionalityTest()
|
||||||
|
{
|
||||||
|
string inputString = File.ReadAllText("testText.txt");
|
||||||
|
string writtenString = ""; // string that was written to the process
|
||||||
|
|
||||||
|
Stream inputStream = new MemoryStream();
|
||||||
|
|
||||||
|
StreamWriter sw = new StreamWriter(inputStream, Encoding.Default);
|
||||||
|
{
|
||||||
|
int writeSize = 127;
|
||||||
|
for (int i = 0; i < inputString.Length; i += writeSize)
|
||||||
|
{
|
||||||
|
// select a substring of characters from the input string
|
||||||
|
string substring = inputString.Substring(i, (i + writeSize < inputString.Length) ? writeSize : inputString.Length - i);
|
||||||
|
sw.Write(substring.ToCharArray(), 0, substring.Length);
|
||||||
|
writtenString += substring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
Stream outputStream = new MemoryStream();
|
||||||
|
using (StdinToStdoutProcess s = new StdinToStdoutProcess(new ProcessArguments(), outputStream))
|
||||||
|
{
|
||||||
|
s.ProgressCallback = this;
|
||||||
|
s.ProcessInput(inputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
string outputString;
|
||||||
|
using (StreamReader sr = new StreamReader(outputStream, Encoding.Default))
|
||||||
|
{
|
||||||
|
outputString = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
Assert.AreEqual(writtenString, outputString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Implements the interface progress callback for testing output purposes
|
||||||
|
/// </summary>
|
||||||
|
public class ProgressCallbackTestBase : IProgressCallback
|
||||||
|
{
|
||||||
|
protected string mPreface = "";
|
||||||
|
|
||||||
|
#region IProgressCallback Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
public virtual void Begin(int minimum, int maximum)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + String.Format("Begin min:{0} max:{1}", minimum, maximum));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback, without setting the range
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Begin()
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + String.Format("Begin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to reset the range in the
|
||||||
|
/// progress callback
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
public virtual void SetRange(int minimum, int maximum)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + String.Format("SetRange min:{0} max:{1}", minimum, maximum));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to update the progress text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The text.</param>
|
||||||
|
public virtual void SetText(string text)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + String.Format("SetText : {0}", text));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
public virtual void StepTo(int val)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + String.Format("StepTo : {0}", val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to step the progress meter to a
|
||||||
|
/// particular value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
public virtual void Increment(int val)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + String.Format("Increment : {0}", val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this property is true, then you should abort work
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// <c>true</c> if this instance is aborting; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
public virtual bool IsAborting
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + "IsAborting");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to finalize the progress meter
|
||||||
|
/// </summary>
|
||||||
|
public virtual void End()
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mPreface + "End");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Utility;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TranscodeTest : ProgressCallbackTestBase
|
||||||
|
{
|
||||||
|
static string inputMp3 = "Disc 01 - 04.mp3";
|
||||||
|
string outputAac = inputMp3.Replace(".mp3", ".aac");
|
||||||
|
string outputWav = inputMp3.Replace(".mp3", ".wav");
|
||||||
|
private ReaderProgress mReaderProgress = new ReaderProgress();
|
||||||
|
private WriterProgress mWriterProgress = new WriterProgress();
|
||||||
|
|
||||||
|
private Stream mPipeStream;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TranscodeSingleThreadTest()
|
||||||
|
{
|
||||||
|
Mp3FileProperties mp3Info = new Mp3FileProperties(inputMp3);
|
||||||
|
Debug.WriteLine(mp3Info);
|
||||||
|
|
||||||
|
mPipeStream = new MemoryStream();
|
||||||
|
|
||||||
|
Mp3ReadThread();
|
||||||
|
if (mPipeStream.CanSeek)
|
||||||
|
mPipeStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
WavWriteThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TranscodeMultiThreadTest()
|
||||||
|
{
|
||||||
|
//mPipeStream = new BridgeStream();
|
||||||
|
mPipeStream = new PipeStream();
|
||||||
|
(mPipeStream as PipeStream).BlockLastReadBuffer = true;
|
||||||
|
(mPipeStream as PipeStream).MaxBufferLength = 1 * PipeStream.MB;
|
||||||
|
|
||||||
|
// mPipeStream.MaxBufferLength = 100;
|
||||||
|
|
||||||
|
Thread writeThread = new Thread(new ThreadStart(AacWriteThread));
|
||||||
|
writeThread.Start();
|
||||||
|
|
||||||
|
Thread readThread = new Thread(new ThreadStart(Mp3ReadThread));
|
||||||
|
readThread.Start();
|
||||||
|
|
||||||
|
readThread.Join();
|
||||||
|
(mPipeStream as PipeStream).BlockLastReadBuffer = false;
|
||||||
|
writeThread.Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Mp3ReadThread()
|
||||||
|
{
|
||||||
|
//int skip = 3;
|
||||||
|
//int limit = 1;
|
||||||
|
//string directory = @"C:\tmp\venus bak\media\audiobooks\Bret Easton Ellis - Lunar Park";
|
||||||
|
//// string directory = @"C:\tmp\venus bak\media\audiobooks\Clarke, Arthur C. - Space Odyssey 01 - 2001, A Space Odyssey";
|
||||||
|
//// string directory = @"C:\tmp\venus bak\media\audiobooks\Guitar Gym\Part 1 - Alternate Picking (Mp3 And Tab)";
|
||||||
|
//string[] files = Directory.GetFiles(directory);
|
||||||
|
string[] files = new string[]{inputMp3};
|
||||||
|
foreach (string mp3File in files)
|
||||||
|
{
|
||||||
|
//if (skip-- > 0)
|
||||||
|
// continue;
|
||||||
|
//if (limit-- == 0)
|
||||||
|
// break;
|
||||||
|
Debug.WriteLine(mp3File);
|
||||||
|
Mp3FileProperties fp = new Mp3FileProperties(mp3File);
|
||||||
|
Debug.WriteLine(fp.ToString());
|
||||||
|
// Mp3 to wav
|
||||||
|
using (FileStream fileStream = new FileStream(mp3File, FileMode.Open))
|
||||||
|
{
|
||||||
|
Mp3EncodingOptions opts = new Mp3EncodingOptions();
|
||||||
|
opts.Infile = "-";
|
||||||
|
opts.Outfile = "-";
|
||||||
|
// opts.BitRate = BitRate.KBPS_32;
|
||||||
|
// opts.Freeformat = true;
|
||||||
|
opts.Mp3Input = true;
|
||||||
|
opts.DecodeWav = true;
|
||||||
|
// opts.DisableWavHeader = true;
|
||||||
|
Debug.WriteLine("MP3 : " + opts.GetCommandLineArguments());
|
||||||
|
// opts.Freeformat = true;
|
||||||
|
// read from the sr, and write to the memory stream
|
||||||
|
using (Mp3Encoder encoder = new Mp3Encoder(opts, mPipeStream))
|
||||||
|
{
|
||||||
|
encoder.ProgressCallback = mReaderProgress;
|
||||||
|
encoder.ProcessInput(fileStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WavWriteThread()
|
||||||
|
{
|
||||||
|
using (FileStream fs = new FileStream(outputWav, FileMode.OpenOrCreate))
|
||||||
|
using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
|
||||||
|
using (StreamReader sr = new StreamReader(mPipeStream, Encoding.Default))
|
||||||
|
{
|
||||||
|
char[] buffer = new char[1024 * 1024];
|
||||||
|
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
int readCount = sr.Read(buffer, 0, buffer.Length);
|
||||||
|
sw.Write(buffer, 0, readCount);
|
||||||
|
mWriterProgress.SetText("Wrote " + buffer.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AacWriteThread()
|
||||||
|
{
|
||||||
|
Mp4EncodingOptions mp4Opts = new Mp4EncodingOptions();
|
||||||
|
mp4Opts.OutputFilename = outputAac;
|
||||||
|
mp4Opts.RawPCMSwapInputBytes = true;
|
||||||
|
mp4Opts.RawPCMInputMode = true;
|
||||||
|
mp4Opts.RawPCMInputSampleRate = 16;
|
||||||
|
mp4Opts.RawPCMInputSampleSize = SampleRateFrequency.Hz_44100;
|
||||||
|
mp4Opts.RawInputChannels = ChannelMode.Stereo;
|
||||||
|
Debug.WriteLine("AAC : " + mp4Opts.GetCommandLineArguments());
|
||||||
|
|
||||||
|
using (Mp4Encoder encoder = new Mp4Encoder(mp4Opts))
|
||||||
|
{
|
||||||
|
encoder.ProgressCallback = mWriterProgress;
|
||||||
|
encoder.ProcessInput(mPipeStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ReaderProgress : ProgressCallbackTestBase
|
||||||
|
{
|
||||||
|
public ReaderProgress()
|
||||||
|
{
|
||||||
|
mPreface = "Reader: ";
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
public override void StepTo(int val)
|
||||||
|
{
|
||||||
|
if (val % 10 == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
base.StepTo(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WriterProgress : ProgressCallbackTestBase
|
||||||
|
{
|
||||||
|
public WriterProgress()
|
||||||
|
{
|
||||||
|
|
||||||
|
mPreface = "\t\t\t\tWriter: ";
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
public override void StepTo(int val)
|
||||||
|
{
|
||||||
|
if (val % 10 == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
base.StepTo(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectType>Local</ProjectType>
|
||||||
|
<ProductVersion>8.0.50727</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{73C5A642-71EF-471C-A82D-70899904C495}</ProjectGuid>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ApplicationIcon>App.ico</ApplicationIcon>
|
||||||
|
<AssemblyKeyContainerName>
|
||||||
|
</AssemblyKeyContainerName>
|
||||||
|
<AssemblyName>m3uTool</AssemblyName>
|
||||||
|
<AssemblyOriginatorKeyFile>
|
||||||
|
</AssemblyOriginatorKeyFile>
|
||||||
|
<DefaultClientScript>JScript</DefaultClientScript>
|
||||||
|
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||||
|
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||||
|
<DelaySign>false</DelaySign>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<RootNamespace>m3uTool</RootNamespace>
|
||||||
|
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||||
|
<StartupObject>
|
||||||
|
</StartupObject>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<UpgradeBackupLocation>
|
||||||
|
</UpgradeBackupLocation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||||
|
<BaseAddress>285212672</BaseAddress>
|
||||||
|
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||||
|
<ConfigurationOverrideFile>
|
||||||
|
</ConfigurationOverrideFile>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<DocumentationFile>
|
||||||
|
</DocumentationFile>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<FileAlignment>4096</FileAlignment>
|
||||||
|
<NoStdLib>false</NoStdLib>
|
||||||
|
<NoWarn>
|
||||||
|
</NoWarn>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<RegisterForComInterop>false</RegisterForComInterop>
|
||||||
|
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||||
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<UseVSHostingProcess>true</UseVSHostingProcess>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||||
|
<BaseAddress>285212672</BaseAddress>
|
||||||
|
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||||
|
<ConfigurationOverrideFile>
|
||||||
|
</ConfigurationOverrideFile>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<DocumentationFile>
|
||||||
|
</DocumentationFile>
|
||||||
|
<DebugSymbols>false</DebugSymbols>
|
||||||
|
<FileAlignment>4096</FileAlignment>
|
||||||
|
<NoStdLib>false</NoStdLib>
|
||||||
|
<NoWarn>
|
||||||
|
</NoWarn>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<RegisterForComInterop>false</RegisterForComInterop>
|
||||||
|
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||||
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
|
||||||
|
<Reference Include="PipeStream, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\PipeStream\code\bin\Release\PipeStream.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System">
|
||||||
|
<Name>System</Name>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data">
|
||||||
|
<Name>System.Data</Name>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Drawing">
|
||||||
|
<Name>System.Drawing</Name>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Windows.Forms">
|
||||||
|
<Name>System.Windows.Forms</Name>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml">
|
||||||
|
<Name>System.XML</Name>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="App.ico" />
|
||||||
|
<Compile Include="DoNothingProgressCallback.cs" />
|
||||||
|
<Compile Include="Redirect.cs" />
|
||||||
|
<Compile Include="Tests\HiPerfTimer.cs" />
|
||||||
|
<Compile Include="KeyedList.cs" />
|
||||||
|
<Compile Include="LongestCommonSequence.cs" />
|
||||||
|
<Compile Include="ProcessArguments.cs" />
|
||||||
|
<Compile Include="IProgressCallback.cs" />
|
||||||
|
<Compile Include="Mp3Encoder.cs" />
|
||||||
|
<Compile Include="Mp3EncodingOptions.cs" />
|
||||||
|
<Compile Include="Mp3FileProperties.cs" />
|
||||||
|
<Compile Include="ProcessStreamWrapper.cs" />
|
||||||
|
<Compile Include="Mp4Encoder.cs" />
|
||||||
|
<Compile Include="Mp4EncodingOptions.cs" />
|
||||||
|
<Compile Include="AssemblyInfo.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="M3uCreate.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="M3uMakeByDirectory.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="M3uToAac.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="M3uToAac.Designer.cs">
|
||||||
|
<DependentUpon>M3uToAac.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Mp3ToAacBatch.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Mp3ToAacBatch.Designer.cs">
|
||||||
|
<DependentUpon>Mp3ToAacBatch.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Tests\CreateM3uTests.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Tests\LongestCommonSequenceTests.cs" />
|
||||||
|
<Compile Include="Tests\Mp3EncoderTests.cs" />
|
||||||
|
<Compile Include="Tests\Mp3EncodingOptionsTests.cs" />
|
||||||
|
<Compile Include="Tests\Mp3FilePropertiesTests.cs" />
|
||||||
|
<Compile Include="Tests\Mp4EncoderTests.cs" />
|
||||||
|
<Compile Include="Tests\Mp4EncodingOptionsTests.cs" />
|
||||||
|
<Compile Include="Tests\ProgressCallbackTestBase.cs" />
|
||||||
|
<Compile Include="Tests\ProcessStreamWrapperTests.cs" />
|
||||||
|
<Compile Include="Tests\TranscodeTest.cs" />
|
||||||
|
<EmbeddedResource Include="M3uMakeByDirectory.resx">
|
||||||
|
<DependentUpon>M3uMakeByDirectory.cs</DependentUpon>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="M3uToAac.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<DependentUpon>M3uToAac.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Mp3ToAacBatch.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<DependentUpon>Mp3ToAacBatch.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Resources\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<PreBuildEvent>copy /D /Y "$(ProjectDir)Tests\"*.mp3 "$(TargetDir)"
|
||||||
|
copy /D /Y "$(ProjectDir)Tests\"*.wav "$(TargetDir)"
|
||||||
|
copy /D /Y "$(ProjectDir)Tests\"*.exe "$(TargetDir)"
|
||||||
|
copy /D /Y "$(ProjectDir)Tests\"*.txt "$(TargetDir)"</PreBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "m3uTool", "m3uTool.csproj", "{73C5A642-71EF-471C-A82D-70899904C495}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StdinToStdout", "..\StdinToStdout\StdinToStdout.csproj", "{94C7033C-C8A8-4104-95FE-0D11122080E2}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{73C5A642-71EF-471C-A82D-70899904C495}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{73C5A642-71EF-471C-A82D-70899904C495}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{73C5A642-71EF-471C-A82D-70899904C495}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{73C5A642-71EF-471C-A82D-70899904C495}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{94C7033C-C8A8-4104-95FE-0D11122080E2}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{94C7033C-C8A8-4104-95FE-0D11122080E2}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{94C7033C-C8A8-4104-95FE-0D11122080E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{94C7033C-C8A8-4104-95FE-0D11122080E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
+382
@@ -0,0 +1,382 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// BridgeStream provides a console-like "pipe" data stream for use between two threaded processes
|
||||||
|
/// in a producer-consumer type problem.
|
||||||
|
/// </summary>
|
||||||
|
/// <license>
|
||||||
|
/// Copyright (c) 2006 James Kolpack
|
||||||
|
///
|
||||||
|
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
|
/// associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
/// including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
/// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
/// furnished to do so, subject to the following conditions:
|
||||||
|
///
|
||||||
|
/// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
/// substantial portions of the Software.
|
||||||
|
///
|
||||||
|
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
/// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
/// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
/// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
||||||
|
/// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
/// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
/// </license>
|
||||||
|
public class BridgeStream : Stream
|
||||||
|
{
|
||||||
|
#region Private members
|
||||||
|
/// <summary>
|
||||||
|
/// Queue of bytes provides the datastructure for transmitting from an
|
||||||
|
/// input stream to an output stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Possibly inefficient.</remarks>
|
||||||
|
private Queue<byte> mBuffer = new Queue<byte>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event occurs after data is written.
|
||||||
|
/// </summary>
|
||||||
|
private ManualResetEvent mWriteEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event occurs after data is read.
|
||||||
|
/// </summary>
|
||||||
|
private ManualResetEvent mReadEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the input stream has been flushed and that
|
||||||
|
/// all remaining data should be written to the output stream.
|
||||||
|
/// </summary>
|
||||||
|
private bool mFlushed = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of bytes to store in the buffer.
|
||||||
|
/// </summary>
|
||||||
|
private long mMaxBufferLength = 200 * MB;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Setting this to true will cause Read() to block if it appears
|
||||||
|
/// that it will run out of data.
|
||||||
|
/// </summary>
|
||||||
|
private bool mBlockLastRead = false;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Const members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of bytes in a kilobyte
|
||||||
|
/// </summary>
|
||||||
|
public const long KB = 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of bytes in a megabyte
|
||||||
|
/// </summary>
|
||||||
|
public const long MB = KB * 1024;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the maximum number of bytes to store in the buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The length of the max buffer.</value>
|
||||||
|
public long MaxBufferLength
|
||||||
|
{
|
||||||
|
get { return mMaxBufferLength; }
|
||||||
|
set { mMaxBufferLength = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether to block last read method before the buffer is empty.
|
||||||
|
/// When true, Read() will block until it can fill the passed in buffer and count.
|
||||||
|
/// When false, Read() will not block, returning all the available buffer data.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Setting to true will remove the possibility of ending a stream reader prematurely.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>
|
||||||
|
/// <c>true</c> if block last read method before the buffer is empty; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
public bool BlockLastReadBuffer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mBlockLastRead;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mBlockLastRead = value;
|
||||||
|
|
||||||
|
// when turning off the block last read, signal Read() that it may now read the rest of the buffer.
|
||||||
|
if (!mBlockLastRead)
|
||||||
|
mWriteEvent.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BridgeStream"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public BridgeStream()
|
||||||
|
{
|
||||||
|
mWriteEvent = new ManualResetEvent(false);
|
||||||
|
mReadEvent = new ManualResetEvent(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Stream overide methods
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||||
|
///</summary>
|
||||||
|
///<filterpriority>2</filterpriority>
|
||||||
|
public new void Dispose()
|
||||||
|
{
|
||||||
|
// clear the internal buffer
|
||||||
|
mBuffer.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<exception cref="T:System.IO.IOException">An I/O error occurs. </exception><filterpriority>2</filterpriority>
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
mFlushed = true;
|
||||||
|
mWriteEvent.Set(); // signal any waiting read events.
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, sets the position within the current stream.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<returns>
|
||||||
|
///The new position within the current stream.
|
||||||
|
///</returns>
|
||||||
|
///
|
||||||
|
///<param name="offset">A byte offset relative to the origin parameter. </param>
|
||||||
|
///<param name="origin">A value of type <see cref="T:System.IO.SeekOrigin"></see> indicating the reference point used to obtain the new position. </param>
|
||||||
|
///<exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
|
||||||
|
///<exception cref="T:System.NotSupportedException">The stream does not support seeking, such as if the stream is constructed from a pipe or console output. </exception>
|
||||||
|
///<exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception><filterpriority>1</filterpriority>
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, sets the length of the current stream.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<param name="value">The desired length of the current stream in bytes. </param>
|
||||||
|
///<exception cref="T:System.NotSupportedException">The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. </exception>
|
||||||
|
///<exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
|
||||||
|
///<exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception><filterpriority>2</filterpriority>
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<returns>
|
||||||
|
///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
|
||||||
|
///</returns>
|
||||||
|
///
|
||||||
|
///<param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream. </param>
|
||||||
|
///<param name="count">The maximum number of bytes to be read from the current stream. </param>
|
||||||
|
///<param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. </param>
|
||||||
|
///<exception cref="T:System.ArgumentException">The sum of offset and count is larger than the buffer length. </exception>
|
||||||
|
///<exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
|
||||||
|
///<exception cref="T:System.NotSupportedException">The stream does not support reading. </exception>
|
||||||
|
///<exception cref="T:System.ArgumentNullException">buffer is null. </exception>
|
||||||
|
///<exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
|
||||||
|
///<exception cref="T:System.ArgumentOutOfRangeException">offset or count is negative. </exception><filterpriority>1</filterpriority>
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (offset != 0)
|
||||||
|
throw new NotImplementedException("Offsets with value of non-zero are not supported");
|
||||||
|
if (buffer == null)
|
||||||
|
throw new ArgumentException("Buffer is null");
|
||||||
|
if (offset + count > buffer.Length)
|
||||||
|
throw new ArgumentException("The sum of offset and count is greater than the buffer length. ");
|
||||||
|
if (offset < 0 || count < 0)
|
||||||
|
throw new ArgumentOutOfRangeException("offset or count is negative.");
|
||||||
|
if (BlockLastReadBuffer && count >= mMaxBufferLength)
|
||||||
|
throw new ArgumentException("count > mMaxBufferLength");
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int readLength = 0;
|
||||||
|
|
||||||
|
while ((Length < count && !mFlushed) ||
|
||||||
|
(Length < (count + 1) && BlockLastReadBuffer))
|
||||||
|
{
|
||||||
|
mWriteEvent.Reset(); // turn off an existing write signal
|
||||||
|
mReadEvent.Set(); // signal any waiting reads, preventing deadlock
|
||||||
|
mWriteEvent.WaitOne(); // wait until a write occurs
|
||||||
|
}
|
||||||
|
lock (mBuffer)
|
||||||
|
{
|
||||||
|
// fill the read buffer
|
||||||
|
for (; readLength < count && Length > 0; readLength++)
|
||||||
|
{
|
||||||
|
buffer[readLength] = mBuffer.Dequeue();
|
||||||
|
}
|
||||||
|
mReadEvent.Set();
|
||||||
|
}
|
||||||
|
return readLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream. </param>
|
||||||
|
///<param name="count">The number of bytes to be written to the current stream. </param>
|
||||||
|
///<param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream. </param>
|
||||||
|
///<exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
|
||||||
|
///<exception cref="T:System.NotSupportedException">The stream does not support writing. </exception>
|
||||||
|
///<exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
|
||||||
|
///<exception cref="T:System.ArgumentNullException">buffer is null. </exception>
|
||||||
|
///<exception cref="T:System.ArgumentException">The sum of offset and count is greater than the buffer length. </exception>
|
||||||
|
///<exception cref="T:System.ArgumentOutOfRangeException">offset or count is negative. </exception><filterpriority>1</filterpriority>
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (buffer == null)
|
||||||
|
throw new ArgumentException("Buffer is null");
|
||||||
|
if (offset + count > buffer.Length)
|
||||||
|
throw new ArgumentException("The sum of offset and count is greater than the buffer length. ");
|
||||||
|
if (offset < 0 || count < 0)
|
||||||
|
throw new ArgumentOutOfRangeException("offset or count is negative.");
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
while (Length >= mMaxBufferLength)
|
||||||
|
{
|
||||||
|
mReadEvent.Reset();
|
||||||
|
//Debug.WriteLine(String.Format("\t\t\tWrite(): mBuffer.Count({0}) >= mMaxBufferLength({1})", mBuffer.Count, mMaxBufferLength));
|
||||||
|
mWriteEvent.Set(); // release any blocked read events
|
||||||
|
mReadEvent.WaitOne();
|
||||||
|
}
|
||||||
|
lock (mBuffer)
|
||||||
|
{
|
||||||
|
mFlushed = false; // if it were flushed before, it soon will not be.
|
||||||
|
|
||||||
|
// queue up the buffer data
|
||||||
|
for (int i = offset; i < count; i++)
|
||||||
|
{
|
||||||
|
mBuffer.Enqueue(buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
mWriteEvent.Set(); // signal that write has occured
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, gets a value indicating whether the current stream supports reading.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<returns>
|
||||||
|
///true if the stream supports reading; otherwise, false.
|
||||||
|
///</returns>
|
||||||
|
///<filterpriority>1</filterpriority>
|
||||||
|
public override bool CanRead
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, gets a value indicating whether the current stream supports seeking.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<returns>
|
||||||
|
///true if the stream supports seeking; otherwise, false.
|
||||||
|
///</returns>
|
||||||
|
///<filterpriority>1</filterpriority>
|
||||||
|
public override bool CanSeek
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, gets a value indicating whether the current stream supports writing.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<returns>
|
||||||
|
///true if the stream supports writing; otherwise, false.
|
||||||
|
///</returns>
|
||||||
|
///<filterpriority>1</filterpriority>
|
||||||
|
public override bool CanWrite
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, gets the length in bytes of the stream.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<returns>
|
||||||
|
///A long value representing the length of the stream in bytes.
|
||||||
|
///</returns>
|
||||||
|
///
|
||||||
|
///<exception cref="T:System.NotSupportedException">A class derived from Stream does not support seeking. </exception>
|
||||||
|
///<exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception><filterpriority>1</filterpriority>
|
||||||
|
public override long Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mBuffer.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///When overridden in a derived class, gets or sets the position within the current stream.
|
||||||
|
///</summary>
|
||||||
|
///
|
||||||
|
///<returns>
|
||||||
|
///The current position within the stream.
|
||||||
|
///</returns>
|
||||||
|
///
|
||||||
|
///<exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
|
||||||
|
///<exception cref="T:System.NotSupportedException">The stream does not support seeking. </exception>
|
||||||
|
///<exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception><filterpriority>1</filterpriority>
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for m3uFromDirectory.
|
||||||
|
/// </summary>
|
||||||
|
public class CreateM3u
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Use the parent's directory name for the m3u name
|
||||||
|
/// </summary>
|
||||||
|
private bool mUseGeneratedOuputFilename = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Directory to grab the files from
|
||||||
|
/// </summary>
|
||||||
|
private DirectoryInfo mInputDir;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ouput m3u filename, if it isn't generated
|
||||||
|
/// </summary>
|
||||||
|
private string mOutputFilename = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter for input filenames
|
||||||
|
/// </summary>
|
||||||
|
private string mFileFilter = "*.mp3";
|
||||||
|
|
||||||
|
public bool UseGeneratedOuputFilename
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mUseGeneratedOuputFilename;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mUseGeneratedOuputFilename = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OutputFilename
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mUseGeneratedOuputFilename)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("OutputFilename:" + mInputDir.FullName + "\\" + mInputDir.Name + ".m3u");
|
||||||
|
return mInputDir.FullName + "\\" + mInputDir.Name + ".m3u";
|
||||||
|
}
|
||||||
|
return mOutputFilename;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mOutputFilename = value;
|
||||||
|
mUseGeneratedOuputFilename = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateM3u(string dir) : this (new DirectoryInfo(dir))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateM3u(DirectoryInfo inputDir)
|
||||||
|
{
|
||||||
|
mInputDir = inputDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// dir: "\foo\bar\" file: "\foo\bar\myfile" output: ""
|
||||||
|
/// dir: "\foo\" file: "\foo\bar\myfile" output: ".."
|
||||||
|
/// dir: "\" file: "\foo\bar\myfile" output: "..\.."
|
||||||
|
/// dir: "\har" file: "\foo\bar\myfile" output: "..\..\har"
|
||||||
|
/// dir: "\foo\bar\hey\" file: "\foo\bar\myfile" output: "hey\"
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="dir"></param>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string GetPath(DirectoryInfo dir, FileInfo file)
|
||||||
|
{
|
||||||
|
string source = dir.FullName;
|
||||||
|
string target = file.Directory.FullName;
|
||||||
|
|
||||||
|
return GetPath(source, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetPath(string source, string target)
|
||||||
|
{
|
||||||
|
int lastCommonIndex = GetLastCommonIndex(source, target);
|
||||||
|
Debug.WriteLine(String.Format("s:{0} , t:{1} lastCommon:{2} ", source, target, lastCommonIndex));
|
||||||
|
|
||||||
|
int slashCount = CountCharacters(source, lastCommonIndex + 1, '\\');
|
||||||
|
|
||||||
|
string path = "";
|
||||||
|
for (int i = 0; i < slashCount; i++)
|
||||||
|
{
|
||||||
|
path += "..\\";
|
||||||
|
}
|
||||||
|
path += target.Substring(lastCommonIndex);
|
||||||
|
if (path.Length > 0 && path[path.Length - 1] != '\\')
|
||||||
|
path += "\\";
|
||||||
|
Debug.WriteLine(path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CountCharacters(string str, int startIdx, char c)
|
||||||
|
{
|
||||||
|
int charsCount = 0;
|
||||||
|
int currIdx = startIdx;
|
||||||
|
while (currIdx < str.Length && (currIdx = str.IndexOf(c, currIdx) + 1) != 0)
|
||||||
|
charsCount++;
|
||||||
|
return charsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetLastCommonIndex(string str1, string str2)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < str1.Length && i < str2.Length && Char.ToLower(str1[i]) == Char.ToLower(str2[i]))
|
||||||
|
i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Create()
|
||||||
|
{
|
||||||
|
string fileList = "";
|
||||||
|
DirectoryInfo ouputDirectory = (new FileInfo(OutputFilename)).Directory;
|
||||||
|
foreach (FileInfo info in mInputDir.GetFiles(mFileFilter))
|
||||||
|
{
|
||||||
|
string fileName = GetPath(ouputDirectory, info) + info.Name;
|
||||||
|
Debug.WriteLine(fileName);
|
||||||
|
fileList += fileName + Environment.NewLine;
|
||||||
|
}
|
||||||
|
SaveToFile(fileList, OutputFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveToFile(string contents, string outputFilename)
|
||||||
|
{
|
||||||
|
using (TextWriter tw = new StreamWriter(outputFilename))
|
||||||
|
{
|
||||||
|
tw.Write(contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class DoNothingProgressCallback : IProgressCallback
|
||||||
|
{
|
||||||
|
#region IProgressCallback Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
public void Begin(int minimum, int maximum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback, without setting the range
|
||||||
|
/// </summary>
|
||||||
|
public void Begin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to reset the range in the
|
||||||
|
/// progress callback
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
public void SetRange(int minimum, int maximum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to update the progress text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The text.</param>
|
||||||
|
public void SetText(string text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
public void StepTo(int val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to step the progress meter to a
|
||||||
|
/// particular value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
public void Increment(int val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this property is true, then you should abort work
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// <c>true</c> if this instance is aborting; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
public bool IsAborting
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to finalize the progress meter
|
||||||
|
/// </summary>
|
||||||
|
public void End()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
+274
@@ -0,0 +1,274 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A generic encoder. Creates an external process, sends it argument options,
|
||||||
|
/// and acts as a wrapper for streaming reads and writes
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Encoder : IDisposable
|
||||||
|
{
|
||||||
|
protected ProcessArguments mEncOpt;
|
||||||
|
protected Process mEncoderProcess;
|
||||||
|
protected const int mBufferLength = 16384;
|
||||||
|
protected StreamWriter mOutputStreamWriter = null;
|
||||||
|
protected IProgressCallback mProgressCallback = new DoNothingProgressCallback();
|
||||||
|
protected const byte mEndOfStream = 26;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The progress callback.</value>
|
||||||
|
public IProgressCallback ProgressCallback
|
||||||
|
{
|
||||||
|
get { return mProgressCallback; }
|
||||||
|
set { mProgressCallback = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the process executable filename, such as "LAME.EXE", "FAAC.EXE", etc.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The process executable filename.</value>
|
||||||
|
protected abstract string ProcessExecutableFilename
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encOpt"></param>
|
||||||
|
public Encoder(ProcessArguments encOpt) : this (encOpt, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Encoder"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encOpt">The enc opt.</param>
|
||||||
|
/// <param name="outputStream">Output to this stream</param>
|
||||||
|
public Encoder(ProcessArguments encOpt, Stream outputStream)
|
||||||
|
{
|
||||||
|
//if (!outputStream.CanWrite)
|
||||||
|
// throw new ArgumentException("Can't write to output stream");
|
||||||
|
//if (!string.IsNullOrEmpty(encOpt.OutputFilename) && encOpt.OutputFilename.Trim() != "-")
|
||||||
|
// throw new ArgumentException("Trying to output to both a stream and a file " + encOpt.OutputFilename);
|
||||||
|
//encOpt.OutputFilename = "-";
|
||||||
|
|
||||||
|
mEncOpt = encOpt;
|
||||||
|
|
||||||
|
mEncoderProcess = CreateEncoderProcess(mEncOpt, ProcessExecutableFilename);
|
||||||
|
if (outputStream != null)
|
||||||
|
{
|
||||||
|
mOutputStreamWriter = new StreamWriter(outputStream, Encoding.Default);
|
||||||
|
mEncoderProcess.StartInfo.RedirectStandardOutput = true;
|
||||||
|
}
|
||||||
|
mEncoderProcess.StartInfo.RedirectStandardError = true;
|
||||||
|
|
||||||
|
mEncoderProcess.Start();
|
||||||
|
if (mOutputStreamWriter != null)
|
||||||
|
{
|
||||||
|
Thread thread = new Thread(new ThreadStart(GetStandardOutput));
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread standardErrorThread = new Thread(new ThreadStart(GetStandardError));
|
||||||
|
standardErrorThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Process CreateEncoderProcess(ProcessArguments encOpt, string encoderFilename)
|
||||||
|
{
|
||||||
|
Process encoderProcess = new Process();
|
||||||
|
encoderProcess.StartInfo.RedirectStandardInput = true;
|
||||||
|
encoderProcess.StartInfo.UseShellExecute = false;
|
||||||
|
encoderProcess.StartInfo.FileName = encoderFilename;
|
||||||
|
encoderProcess.StartInfo.Arguments = encOpt.GetCommandLineArguments();
|
||||||
|
encoderProcess.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
|
||||||
|
encoderProcess.StartInfo.CreateNoWindow = true;
|
||||||
|
|
||||||
|
encoderProcess.EnableRaisingEvents = true;
|
||||||
|
encoderProcess.Exited += new EventHandler(encoderProcess_Exited);
|
||||||
|
return encoderProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
void encoderProcess_Exited(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText("encoderProcess_Exited");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the data to the underlying process through its input stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The data to encode</param>
|
||||||
|
/// <param name="count">How many characters to write</param>
|
||||||
|
/// <param name="startIndex">The index to begin writing from</param>
|
||||||
|
public void Encode(char[] buffer, int startIndex, int count)
|
||||||
|
{
|
||||||
|
// Debug.WriteLine("-");
|
||||||
|
mEncoderProcess.StandardInput.Write(buffer, startIndex, count);
|
||||||
|
if (count != mBufferLength)
|
||||||
|
mProgressCallback.SetText("Encode : " + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteEndOfStream()
|
||||||
|
{
|
||||||
|
if (!mEncoderProcess.HasExited)
|
||||||
|
{
|
||||||
|
mEncoderProcess.StandardInput.BaseStream.Write(new byte[] { mEndOfStream }, 0, 1);
|
||||||
|
mEncoderProcess.StandardInput.BaseStream.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetPercentDone(long previousLeft, long currentLeft, long currentDone, int lastDone)
|
||||||
|
{
|
||||||
|
// if currentLeft > previousLeft - lastDone,
|
||||||
|
// addedLeft = previousLeft - lastDone - currentLeft
|
||||||
|
// totalLength = previousLeft + currentDone + addedLeft
|
||||||
|
|
||||||
|
long totalLength = currentLeft;
|
||||||
|
if (currentLeft != previousLeft)
|
||||||
|
{
|
||||||
|
long leftDelta = previousLeft - lastDone - currentLeft;
|
||||||
|
totalLength = previousLeft + currentDone + leftDelta;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Convert.ToInt32((currentDone / (double)totalLength) * 100);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes all of the data in the input stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputStream"></param>
|
||||||
|
public void Encode(Stream inputStream)
|
||||||
|
{
|
||||||
|
if (!inputStream.CanRead)
|
||||||
|
throw new ArgumentException("Can't read from inputStream");
|
||||||
|
|
||||||
|
mProgressCallback.SetText("Encode: StreamReader sr");
|
||||||
|
|
||||||
|
long inputCount = inputStream.Length;
|
||||||
|
long previousInputCount = inputStream.Length;
|
||||||
|
long processCount = 0;
|
||||||
|
int percentageComplete = 0;
|
||||||
|
|
||||||
|
using (StreamReader sr = new StreamReader(inputStream, Encoding.Default))
|
||||||
|
{
|
||||||
|
mProgressCallback.Begin(0, 100);
|
||||||
|
mProgressCallback.SetText(mEncOpt.GetCommandLineArguments());
|
||||||
|
|
||||||
|
char[] buffer = new char[mBufferLength];
|
||||||
|
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
int readLength = sr.Read(buffer, 0, mBufferLength);
|
||||||
|
if (buffer[readLength - 1] == mEndOfStream)
|
||||||
|
readLength--;
|
||||||
|
Encode(buffer, 0, readLength);
|
||||||
|
|
||||||
|
// update progress
|
||||||
|
processCount += readLength;
|
||||||
|
previousInputCount = inputCount;
|
||||||
|
inputCount = inputStream.Length;
|
||||||
|
int currentPercentageComplete = GetPercentDone(previousInputCount, inputCount, processCount, readLength);
|
||||||
|
if (currentPercentageComplete != percentageComplete)
|
||||||
|
{
|
||||||
|
percentageComplete = currentPercentageComplete;
|
||||||
|
mProgressCallback.StepTo(percentageComplete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mProgressCallback.SetText("Encode: Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open this file and encode it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename"></param>
|
||||||
|
public void Encode(string filename)
|
||||||
|
{
|
||||||
|
using (FileStream inputStream = File.OpenRead(filename))
|
||||||
|
{
|
||||||
|
Encode(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void GetStandardOutput()
|
||||||
|
{
|
||||||
|
char[] writeBuffer = new char[mBufferLength];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!mEncoderProcess.StandardOutput.EndOfStream)
|
||||||
|
{
|
||||||
|
int readLength = mEncoderProcess.StandardOutput.Read(writeBuffer, 0, writeBuffer.Length);
|
||||||
|
mOutputStreamWriter.Write(writeBuffer, 0, readLength);
|
||||||
|
//Debug.WriteLine("GetStandardOutput() " + "mOutputStreamWriter.Write : " + readLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText(ex.ToString());
|
||||||
|
}
|
||||||
|
mProgressCallback.SetText("GetStandardOutput() " + "Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetStandardError()
|
||||||
|
{
|
||||||
|
// char[] writeBuffer = new char[10];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!mEncoderProcess.StandardError.EndOfStream)
|
||||||
|
{
|
||||||
|
string line = mEncoderProcess.StandardError.ReadLine();
|
||||||
|
//int readLength = mEncoderProcess.StandardError.Read(writeBuffer, 0, writeBuffer.Length);
|
||||||
|
Debug.WriteLine("GetStandardError() " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText(ex.ToString());
|
||||||
|
}
|
||||||
|
mProgressCallback.SetText("GetStandardError() " + "Done!");
|
||||||
|
}
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
mProgressCallback.SetText("Dispose()");
|
||||||
|
while (mEncoderProcess != null && !mEncoderProcess.HasExited)
|
||||||
|
{
|
||||||
|
//WriteEndOfStream();
|
||||||
|
//Debug.Write(".");
|
||||||
|
if (count++ > 50)
|
||||||
|
mEncoderProcess.Kill();
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
mEncoderProcess.WaitForExit();
|
||||||
|
if (mOutputStreamWriter != null)
|
||||||
|
mOutputStreamWriter.Flush();
|
||||||
|
//if (mEncoderProcess.ExitCode != 0)
|
||||||
|
// throw new ApplicationException("Exit code " + mEncoderProcess.ExitCode);
|
||||||
|
mProgressCallback.SetText("Dispose() with exit code " + mEncoderProcess.ExitCode);
|
||||||
|
|
||||||
|
|
||||||
|
//if (mEncoderProcess != null && mEncoderProcess.Responding)
|
||||||
|
// mEncoderProcess.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This defines an interface which can be implemented by UI elements
|
||||||
|
/// which indicate the progress of a long operation.
|
||||||
|
/// (See ProgressWindow for a typical implementation)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Based on http://www.codeproject.com/cs/miscctrl/progressdialog.asp </remarks>
|
||||||
|
public interface IProgressCallback
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// If this property is true, then you should abort work
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// <c>true</c> if this instance is aborting; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
bool IsAborting { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
void Begin(int minimum, int maximum);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to initialize
|
||||||
|
/// the progress callback, without setting the range
|
||||||
|
/// </summary>
|
||||||
|
void Begin();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to reset the range in the
|
||||||
|
/// progress callback
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minimum">The minimum.</param>
|
||||||
|
/// <param name="maximum">The maximum.</param>
|
||||||
|
void SetRange(int minimum, int maximum);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to update the progress text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The text.</param>
|
||||||
|
void SetText(String text);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
void StepTo(int val);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to step the progress meter to a
|
||||||
|
/// particular value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val">The val.</param>
|
||||||
|
void Increment(int val);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to finalize the progress meter
|
||||||
|
/// </summary>
|
||||||
|
void End();
|
||||||
|
}
|
||||||
+407
@@ -0,0 +1,407 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2005, Marc Clifton
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of MyXaml nor the names of its contributors may be
|
||||||
|
used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Clifton.Collections.Generic
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class KeyedList<K, V> : IDictionary<K, V>, IList<KeyValuePair<K, V>>
|
||||||
|
{
|
||||||
|
private readonly List<KeyValuePair<K, V>> objectList = new List<KeyValuePair<K, V>>();
|
||||||
|
private readonly Dictionary<K, V> objectTable = new Dictionary<K, V>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the ordered list of keys.
|
||||||
|
/// This is a copy of the keys in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public List<K> OrderedKeys
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var retList = new List<K>();
|
||||||
|
|
||||||
|
foreach (var kvp in objectList)
|
||||||
|
{
|
||||||
|
retList.Add(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the ordered list of values.
|
||||||
|
/// This is a copy of the values in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public List<V> OrderedValues
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var retList = new List<V>();
|
||||||
|
|
||||||
|
foreach (var kvp in objectList)
|
||||||
|
{
|
||||||
|
retList.Add(kvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Dictionary class backing the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<K, V> ObjectTable
|
||||||
|
{
|
||||||
|
get { return objectTable; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IDictionary<K,V> Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns false.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsReadOnly
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of entries in the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return objectList.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the value associated with the specified key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <returns>The associated value.</returns>
|
||||||
|
public virtual V this[K key]
|
||||||
|
{
|
||||||
|
get { return objectTable[key]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (objectTable.ContainsKey(key))
|
||||||
|
{
|
||||||
|
objectTable[key] = value;
|
||||||
|
objectList[IndexOf(key)] = new KeyValuePair<K, V>(key, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an unordered list of keys.
|
||||||
|
/// This collection refers back to the keys in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<K> Keys
|
||||||
|
{
|
||||||
|
get { return objectTable.Keys; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an unordered list of values.
|
||||||
|
/// This collection refers back to the values in the original Dictionary.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<V> Values
|
||||||
|
{
|
||||||
|
get { return objectTable.Values; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all entries in the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
objectTable.Clear();
|
||||||
|
objectList.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test if the KeyedList contains the key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <returns>True if the key is found.</returns>
|
||||||
|
public bool ContainsKey(K key)
|
||||||
|
{
|
||||||
|
return objectTable.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test if the KeyedList contains the key in the key-value pair.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The key-value pair.</param>
|
||||||
|
/// <returns>True if the key is found.</returns>
|
||||||
|
public bool Contains(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
return objectTable.ContainsKey(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a key-value pair to the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <param name="value">The associated value.</param>
|
||||||
|
public void Add(K key, V value)
|
||||||
|
{
|
||||||
|
objectTable.Add(key, value);
|
||||||
|
objectList.Add(new KeyValuePair<K, V>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a key-value pair to the KeyedList.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The KeyValuePair instance.</param>
|
||||||
|
public void Add(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
Add(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy the entire key-value pairs to the KeyValuePair array, starting
|
||||||
|
/// at the specified index of the target array. The array is populated
|
||||||
|
/// as an ordered list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvpa">The KeyValuePair array.</param>
|
||||||
|
/// <param name="idx">The position to start the copy.</param>
|
||||||
|
public void CopyTo(KeyValuePair<K, V>[] kvpa, int idx)
|
||||||
|
{
|
||||||
|
objectList.CopyTo(kvpa, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the entry.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key identifying the key-value pair.</param>
|
||||||
|
/// <returns>True if removed.</returns>
|
||||||
|
public bool Remove(K key)
|
||||||
|
{
|
||||||
|
bool found = objectTable.Remove(key);
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
objectList.RemoveAt(IndexOf(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the key in the specified KeyValuePair instance. The Value
|
||||||
|
/// property is ignored.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The key-value identifying the entry.</param>
|
||||||
|
/// <returns>True if removed.</returns>
|
||||||
|
public bool Remove(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
return Remove(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempt to get the value, given the key, without throwing an exception if not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key indentifying the entry.</param>
|
||||||
|
/// <param name="val">The value, if found.</param>
|
||||||
|
/// <returns>True if found.</returns>
|
||||||
|
public bool TryGetValue(K key, out V val)
|
||||||
|
{
|
||||||
|
return objectTable.TryGetValue(key, out val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an ordered System.Collections KeyValuePair objects.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return objectList.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an ordered KeyValuePair enumerator.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerator<KeyValuePair<K, V>> IEnumerable<KeyValuePair<K, V>>.GetEnumerator()
|
||||||
|
{
|
||||||
|
return objectList.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IList<KeyValuePair<K,V>> Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the value at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index.</param>
|
||||||
|
/// <returns>The value.</returns>
|
||||||
|
public KeyValuePair<K, V> this[int idx]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectList[idx];
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectList[idx] = value;
|
||||||
|
objectTable[value.Key] = value.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given the key-value pair, find the index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="kvp">The key-value pair.</param>
|
||||||
|
/// <returns>The index, or -1 if not found.</returns>
|
||||||
|
public int IndexOf(KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
return IndexOf(kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Insert the key-value pair at the specified index location.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The key.</param>
|
||||||
|
/// <param name="kvp">The value.</param>
|
||||||
|
public void Insert(int idx, KeyValuePair<K, V> kvp)
|
||||||
|
{
|
||||||
|
if ((idx < 0) || (idx > Count))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectTable.Add(kvp.Key, kvp.Value);
|
||||||
|
objectList.Insert(idx, kvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the entry at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index to the entry to be removed.</param>
|
||||||
|
public void RemoveAt(int idx)
|
||||||
|
{
|
||||||
|
if ((idx < 0) || (idx >= Count))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectTable.Remove(objectList[idx].Key);
|
||||||
|
objectList.RemoveAt(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the key at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index.</param>
|
||||||
|
/// <returns>The key at the index.</returns>
|
||||||
|
public K GetKey(int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectList[idx].Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The index.</param>
|
||||||
|
/// <returns>The value at the index.</returns>
|
||||||
|
public V GetValue(int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectList[idx].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the index of a particular key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key to find the index of.</param>
|
||||||
|
/// <returns>The index of the key, or -1 if not found.</returns>
|
||||||
|
public int IndexOf(K key)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < objectList.Count; i++)
|
||||||
|
{
|
||||||
|
if (objectList[i].Key.Equals(key))
|
||||||
|
{
|
||||||
|
ret = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Insert the key-value at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx">The zero-based insert point.</param>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
public void Insert(int idx, K key, V value)
|
||||||
|
{
|
||||||
|
if ((idx < 0) || (idx > Count))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
objectTable.Add(key, value);
|
||||||
|
objectList.Insert(idx, new KeyValuePair<K, V>(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class LongestCommonSubstrings
|
||||||
|
{
|
||||||
|
//def longest_common_substrings(S, T):
|
||||||
|
// maks = 0 # length of longest match
|
||||||
|
// ret = Set([""]) # the longest matches we have found
|
||||||
|
// last = {} # length of matches ending at S[i-1] and
|
||||||
|
// next = {} # at S[i] for T[0]...T[n-1]
|
||||||
|
// for i in xrange(len(S)):
|
||||||
|
// for j in xrange(len(T)):
|
||||||
|
// if S[i] == T[j]:
|
||||||
|
// if j-1 in last:
|
||||||
|
// next[j] = last[j-1] + 1
|
||||||
|
// else:
|
||||||
|
// next[j] = 1
|
||||||
|
// if next[j] > maks:
|
||||||
|
// maks = next[j]
|
||||||
|
// ret = Set()
|
||||||
|
// if next[j] == maks:
|
||||||
|
// ret.add(S[i-maks+1:i+1]) # equals T[j-maks+1:j+1]
|
||||||
|
// last = next
|
||||||
|
// next = {}
|
||||||
|
// return ret
|
||||||
|
|
||||||
|
public static List<string> GetLongestSubstring(string s, string t)
|
||||||
|
{
|
||||||
|
int maks = 0;
|
||||||
|
var ret = new List<string>();
|
||||||
|
var last = new Dictionary<int, int>();
|
||||||
|
var next = new Dictionary<int, int>();
|
||||||
|
for (int i = 0; i < s.Length; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < t.Length; j++)
|
||||||
|
{
|
||||||
|
if (s[i] == t[j])
|
||||||
|
{
|
||||||
|
if (last.ContainsKey(j - 1))
|
||||||
|
next[j] = last[j - 1] + 1;
|
||||||
|
else
|
||||||
|
next[j] = 1;
|
||||||
|
|
||||||
|
if (next[j] > maks)
|
||||||
|
{
|
||||||
|
maks = next[j];
|
||||||
|
ret.Clear();
|
||||||
|
}
|
||||||
|
if (next[j] == maks)
|
||||||
|
ret.Add(s.Substring(i - maks + 1, maks));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last = next;
|
||||||
|
next = new Dictionary<int, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LongestCommonSequence<T> where T : IEnumerable
|
||||||
|
{
|
||||||
|
#region BackTracking enum
|
||||||
|
|
||||||
|
public enum BackTracking
|
||||||
|
{
|
||||||
|
NEITHER,
|
||||||
|
UP,
|
||||||
|
LEFT,
|
||||||
|
UP_AND_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private static int ConsecutiveMeasure(int k)
|
||||||
|
{
|
||||||
|
//f(k)=k*a - b;
|
||||||
|
return k*k;
|
||||||
|
}
|
||||||
|
|
||||||
|
//public T DoLCS(T list1, T list2)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
private object[] LCS(object[] list1, object[] list2)
|
||||||
|
{
|
||||||
|
int m = list1.Length;
|
||||||
|
int n = list2.Length;
|
||||||
|
|
||||||
|
var lcs = new int[m + 1,n + 1];
|
||||||
|
var backTracer = new BackTracking[m + 1,n + 1];
|
||||||
|
var w = new int[m + 1,n + 1];
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i <= m; i++)
|
||||||
|
{
|
||||||
|
lcs[i, 0] = 0;
|
||||||
|
backTracer[i, 0] = BackTracking.UP;
|
||||||
|
}
|
||||||
|
for (j = 0; j <= n; j++)
|
||||||
|
{
|
||||||
|
lcs[0, j] = 0;
|
||||||
|
backTracer[0, j] = BackTracking.LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i <= m; i++)
|
||||||
|
{
|
||||||
|
for (j = 1; j <= n; j++)
|
||||||
|
{
|
||||||
|
if (list1[i - 1] == list2[j - 1])
|
||||||
|
{
|
||||||
|
int k = w[i - 1, j - 1];
|
||||||
|
//lcs[i,j] = lcs[i-1,j-1] + 1;
|
||||||
|
lcs[i, j] = lcs[i - 1, j - 1] + ConsecutiveMeasure(k + 1) - ConsecutiveMeasure(k);
|
||||||
|
backTracer[i, j] = BackTracking.UP_AND_LEFT;
|
||||||
|
w[i, j] = k + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lcs[i, j] = lcs[i - 1, j - 1];
|
||||||
|
backTracer[i, j] = BackTracking.NEITHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lcs[i - 1, j] >= lcs[i, j])
|
||||||
|
{
|
||||||
|
lcs[i, j] = lcs[i - 1, j];
|
||||||
|
backTracer[i, j] = BackTracking.UP;
|
||||||
|
w[i, j] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lcs[i, j - 1] >= lcs[i, j])
|
||||||
|
{
|
||||||
|
lcs[i, j] = lcs[i, j - 1];
|
||||||
|
backTracer[i, j] = BackTracking.LEFT;
|
||||||
|
w[i, j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i = m;
|
||||||
|
j = n;
|
||||||
|
|
||||||
|
var subseq = new Stack<object>();
|
||||||
|
// int p=lcs[i,j];
|
||||||
|
|
||||||
|
//trace the backtracking matrix.
|
||||||
|
while (i > 0 || j > 0)
|
||||||
|
{
|
||||||
|
if (backTracer[i, j] == BackTracking.UP_AND_LEFT)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
subseq.Push(list1[i]);
|
||||||
|
// subseq = list1[i] + subseq;
|
||||||
|
Trace.WriteLine(i + " " + list1[i] + " " + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (backTracer[i, j] == BackTracking.UP)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (backTracer[i, j] == BackTracking.LEFT)
|
||||||
|
{
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return subseq.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for m3uFromDirectory.
|
||||||
|
/// </summary>
|
||||||
|
public class M3uCreate
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Directory to grab the files from
|
||||||
|
/// </summary>
|
||||||
|
private readonly DirectoryInfo mInputDir;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter for input filenames
|
||||||
|
/// </summary>
|
||||||
|
private string mFileFilter = "*.mp3";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ouput m3u filename, if it isn't generated
|
||||||
|
/// </summary>
|
||||||
|
private string mOutputFilename;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the parent's directory name for the m3u name
|
||||||
|
/// </summary>
|
||||||
|
private bool mUseGeneratedOuputFilename = true;
|
||||||
|
|
||||||
|
public M3uCreate(string dir) : this(new DirectoryInfo(dir))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public M3uCreate(DirectoryInfo inputDir)
|
||||||
|
{
|
||||||
|
mInputDir = inputDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseGeneratedOuputFilename
|
||||||
|
{
|
||||||
|
get { return mUseGeneratedOuputFilename; }
|
||||||
|
set { mUseGeneratedOuputFilename = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OutputFilename
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mUseGeneratedOuputFilename)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("OutputFilename:" + mInputDir.FullName + "\\" + mInputDir.Name + ".m3u");
|
||||||
|
return mInputDir.FullName + "\\" + mInputDir.Name + ".m3u";
|
||||||
|
}
|
||||||
|
return mOutputFilename;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mOutputFilename = value;
|
||||||
|
mUseGeneratedOuputFilename = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// dir: "\foo\bar\" file: "\foo\bar\myfile" output: ""
|
||||||
|
/// dir: "\foo\" file: "\foo\bar\myfile" output: ".."
|
||||||
|
/// dir: "\" file: "\foo\bar\myfile" output: "..\.."
|
||||||
|
/// dir: "\har" file: "\foo\bar\myfile" output: "..\..\har"
|
||||||
|
/// dir: "\foo\bar\hey\" file: "\foo\bar\myfile" output: "hey\"
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="dir"></param>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string GetPath(DirectoryInfo dir, FileInfo file)
|
||||||
|
{
|
||||||
|
string source = dir.FullName;
|
||||||
|
string target = file.Directory.FullName;
|
||||||
|
|
||||||
|
return GetPath(source, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The source.</param>
|
||||||
|
/// <param name="target">The target.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string GetPath(string source, string target)
|
||||||
|
{
|
||||||
|
int lastCommonIndex = GetLastCommonIndex(source, target);
|
||||||
|
Debug.WriteLine(String.Format("s:{0} , t:{1} lastCommon:{2} ", source, target, lastCommonIndex));
|
||||||
|
|
||||||
|
int slashCount = CountCharacters(source, lastCommonIndex + 1, '\\');
|
||||||
|
|
||||||
|
string path = "";
|
||||||
|
for (int i = 0; i < slashCount; i++)
|
||||||
|
{
|
||||||
|
path += "..\\";
|
||||||
|
}
|
||||||
|
path += target.Substring(lastCommonIndex);
|
||||||
|
if (path.Length > 0 && path[path.Length - 1] != '\\')
|
||||||
|
path += "\\";
|
||||||
|
Debug.WriteLine(path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CountCharacters(string str, int startIdx, char c)
|
||||||
|
{
|
||||||
|
int charsCount = 0;
|
||||||
|
int currIdx = startIdx;
|
||||||
|
while (currIdx < str.Length && (currIdx = str.IndexOf(c, currIdx) + 1) != 0)
|
||||||
|
charsCount++;
|
||||||
|
return charsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetLastCommonIndex(string str1, string str2)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < str1.Length && i < str2.Length && Char.ToLower(str1[i]) == Char.ToLower(str2[i]))
|
||||||
|
i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Create()
|
||||||
|
{
|
||||||
|
string fileList = "";
|
||||||
|
DirectoryInfo ouputDirectory = (new FileInfo(OutputFilename)).Directory;
|
||||||
|
foreach (FileInfo info in mInputDir.GetFiles(mFileFilter))
|
||||||
|
{
|
||||||
|
string fileName = GetPath(ouputDirectory, info) + info.Name;
|
||||||
|
Debug.WriteLine(fileName);
|
||||||
|
fileList += fileName + Environment.NewLine;
|
||||||
|
}
|
||||||
|
SaveToFile(fileList, OutputFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveToFile(string contents, string outputFilename)
|
||||||
|
{
|
||||||
|
using (TextWriter tw = new StreamWriter(outputFilename))
|
||||||
|
{
|
||||||
|
tw.Write(contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for Form1.
|
||||||
|
/// </summary>
|
||||||
|
public class M3uMakeByDirectory : Form
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Container components;
|
||||||
|
|
||||||
|
private TextBox m3uDirectoryTextBox;
|
||||||
|
private Button m3uMakeButton;
|
||||||
|
private TextBox outputTextBox;
|
||||||
|
private Button selectDirectoryButton;
|
||||||
|
|
||||||
|
public M3uMakeByDirectory()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Required for Windows Form Designer support
|
||||||
|
//
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Add any constructor code after InitializeComponent call
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (components != null)
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
private static void Main()
|
||||||
|
{
|
||||||
|
Application.Run(new M3uMakeByDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectDirectoryButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var fbd = new FolderBrowserDialog();
|
||||||
|
DialogResult dialogResult = fbd.ShowDialog(this);
|
||||||
|
|
||||||
|
if (dialogResult == DialogResult.OK)
|
||||||
|
{
|
||||||
|
m3uDirectoryTextBox.Text = fbd.SelectedPath;
|
||||||
|
}
|
||||||
|
UpdateRunButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateRunButton()
|
||||||
|
{
|
||||||
|
if (m3uDirectoryTextBox.Text != null && m3uDirectoryTextBox.Text != "" &&
|
||||||
|
Directory.Exists(m3uDirectoryTextBox.Text))
|
||||||
|
{
|
||||||
|
m3uMakeButton.Enabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m3uMakeButton.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateM3uThread()
|
||||||
|
{
|
||||||
|
CreateM3uRecursive(new DirectoryInfo(m3uDirectoryTextBox.Text));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateM3uRecursive(DirectoryInfo info)
|
||||||
|
{
|
||||||
|
var cm3u = new M3uCreate(info);
|
||||||
|
cm3u.Create();
|
||||||
|
outputTextBox.AppendText("Created " + cm3u.OutputFilename + Environment.NewLine);
|
||||||
|
foreach (DirectoryInfo subDir in info.GetDirectories())
|
||||||
|
{
|
||||||
|
CreateM3uRecursive(subDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void m3uMakeButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var t = new Thread(CreateM3uThread);
|
||||||
|
t.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.m3uDirectoryTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.outputTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.selectDirectoryButton = new System.Windows.Forms.Button();
|
||||||
|
this.m3uMakeButton = new System.Windows.Forms.Button();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// m3uDirectoryTextBox
|
||||||
|
//
|
||||||
|
this.m3uDirectoryTextBox.Enabled = false;
|
||||||
|
this.m3uDirectoryTextBox.Location = new System.Drawing.Point(8, 8);
|
||||||
|
this.m3uDirectoryTextBox.Name = "m3uDirectoryTextBox";
|
||||||
|
this.m3uDirectoryTextBox.Size = new System.Drawing.Size(176, 20);
|
||||||
|
this.m3uDirectoryTextBox.TabIndex = 0;
|
||||||
|
this.m3uDirectoryTextBox.Text = "";
|
||||||
|
//
|
||||||
|
// outputTextBox
|
||||||
|
//
|
||||||
|
this.outputTextBox.Anchor =
|
||||||
|
((System.Windows.Forms.AnchorStyles)
|
||||||
|
((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.outputTextBox.Location = new System.Drawing.Point(8, 88);
|
||||||
|
this.outputTextBox.Multiline = true;
|
||||||
|
this.outputTextBox.Name = "outputTextBox";
|
||||||
|
this.outputTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||||
|
this.outputTextBox.Size = new System.Drawing.Size(272, 168);
|
||||||
|
this.outputTextBox.TabIndex = 1;
|
||||||
|
this.outputTextBox.Text = "";
|
||||||
|
//
|
||||||
|
// selectDirectoryButton
|
||||||
|
//
|
||||||
|
this.selectDirectoryButton.Location = new System.Drawing.Point(208, 8);
|
||||||
|
this.selectDirectoryButton.Name = "selectDirectoryButton";
|
||||||
|
this.selectDirectoryButton.TabIndex = 2;
|
||||||
|
this.selectDirectoryButton.Text = "Select Dir...";
|
||||||
|
this.selectDirectoryButton.Click += new System.EventHandler(this.selectDirectoryButton_Click);
|
||||||
|
//
|
||||||
|
// m3uMakeButton
|
||||||
|
//
|
||||||
|
this.m3uMakeButton.Enabled = false;
|
||||||
|
this.m3uMakeButton.Location = new System.Drawing.Point(208, 40);
|
||||||
|
this.m3uMakeButton.Name = "m3uMakeButton";
|
||||||
|
this.m3uMakeButton.TabIndex = 3;
|
||||||
|
this.m3uMakeButton.Text = "Make M3u";
|
||||||
|
this.m3uMakeButton.Click += new System.EventHandler(this.m3uMakeButton_Click);
|
||||||
|
//
|
||||||
|
// MakeSubdir
|
||||||
|
//
|
||||||
|
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
||||||
|
this.ClientSize = new System.Drawing.Size(292, 266);
|
||||||
|
this.Controls.Add(this.m3uMakeButton);
|
||||||
|
this.Controls.Add(this.selectDirectoryButton);
|
||||||
|
this.Controls.Add(this.outputTextBox);
|
||||||
|
this.Controls.Add(this.m3uDirectoryTextBox);
|
||||||
|
this.Name = "MakeSubdir";
|
||||||
|
this.Text = "M3u Make";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used forserialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="m3uDirectoryTextBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uDirectoryTextBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uDirectoryTextBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>(Default)</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Name">
|
||||||
|
<value>MakeSubdir</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>8, 8</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>80</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
Generated
+46
@@ -0,0 +1,46 @@
|
|||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
partial class M3uToAac
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// M3uToAac
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(434, 138);
|
||||||
|
this.Name = "M3uToAac";
|
||||||
|
this.Text = "M3uToAac";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public partial class M3uToAac : Form
|
||||||
|
{
|
||||||
|
public M3uToAac()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Nested type: Mp3ToAacConversionOptions
|
||||||
|
|
||||||
|
public class Mp3ToAacConversionOptions
|
||||||
|
{
|
||||||
|
private string[] mInputFilenames;
|
||||||
|
private string[] mOutputFilenames;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
+468
@@ -0,0 +1,468 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that a problem existed when parsing an mp3 file
|
||||||
|
/// </summary>
|
||||||
|
public class Mp3FormatException : Exception
|
||||||
|
{
|
||||||
|
string mFilename;
|
||||||
|
|
||||||
|
string mFormatExceptionString;
|
||||||
|
|
||||||
|
public string Filename
|
||||||
|
{
|
||||||
|
get { return mFilename; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FormatExceptionString
|
||||||
|
{
|
||||||
|
get { return mFormatExceptionString; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename"></param>
|
||||||
|
/// <param name="formatExceptionString"></param>
|
||||||
|
public Mp3FormatException(string filename, string formatExceptionString)
|
||||||
|
{
|
||||||
|
mFilename = filename;
|
||||||
|
mFormatExceptionString = formatExceptionString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------
|
||||||
|
|
||||||
|
original C++ code by:
|
||||||
|
Gustav "Grim Reaper" Munkby
|
||||||
|
http://floach.pimpin.net/grd/
|
||||||
|
grimreaperdesigns@gmx.net
|
||||||
|
|
||||||
|
modified and converted to C# by:
|
||||||
|
Robert A. Wlodarczyk
|
||||||
|
http://rob.wincereview.com:8080
|
||||||
|
rwlodarc@hotmail.com
|
||||||
|
---------------------------------------------------------- */
|
||||||
|
public class Mp3Header
|
||||||
|
{
|
||||||
|
//// Public variables for storing the information about the MP3
|
||||||
|
//public int intBitRate;
|
||||||
|
//public string strFileName;
|
||||||
|
//public long lngFileSize;
|
||||||
|
//public int intFrequency;
|
||||||
|
//public string strMode;
|
||||||
|
//public int intLength;
|
||||||
|
//public string strLengthFormatted;
|
||||||
|
|
||||||
|
|
||||||
|
// Private variables used in the process of reading in the MP3 files
|
||||||
|
private ulong bithdr;
|
||||||
|
private bool boolVBitRate;
|
||||||
|
private int intVFrames;
|
||||||
|
|
||||||
|
public Mp3FileDetails ReadMP3Information(string fileName)
|
||||||
|
{
|
||||||
|
mFileDetails = new Mp3FileDetails();
|
||||||
|
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
|
||||||
|
// Set the filename not including the path information
|
||||||
|
mFileDetails.strFileName = @fs.Name;
|
||||||
|
char[] chrSeparators = new char[]{'\\','/'};
|
||||||
|
string[] strSeparator = mFileDetails.strFileName.Split(chrSeparators);
|
||||||
|
int intUpper = strSeparator.GetUpperBound(0);
|
||||||
|
mFileDetails.strFileName = strSeparator[intUpper];
|
||||||
|
|
||||||
|
// Replace ' with '' for the SQL INSERT statement
|
||||||
|
mFileDetails.strFileName = mFileDetails.strFileName.Replace("'", "''");
|
||||||
|
|
||||||
|
// Set the file size
|
||||||
|
mFileDetails.lngFileSize = fs.Length;
|
||||||
|
|
||||||
|
byte[] bytHeader = new byte[4];
|
||||||
|
byte[] bytVBitRate = new byte[12];
|
||||||
|
int intPos = 0;
|
||||||
|
|
||||||
|
// Keep reading 4 bytes from the header until we know for sure that in
|
||||||
|
// fact it's an MP3
|
||||||
|
do
|
||||||
|
{
|
||||||
|
fs.Position = intPos;
|
||||||
|
fs.Read(bytHeader,0,4);
|
||||||
|
intPos++;
|
||||||
|
LoadMP3Header(bytHeader);
|
||||||
|
}
|
||||||
|
while(!IsValidHeader() && (fs.Position!=fs.Length));
|
||||||
|
|
||||||
|
// If the current file stream position is equal to the length,
|
||||||
|
// that means that we've read the entire file and it's not a valid MP3 file
|
||||||
|
if(fs.Position != fs.Length)
|
||||||
|
{
|
||||||
|
intPos += 3;
|
||||||
|
|
||||||
|
if(getVersionIndex() == 3) // MPEG Version 1
|
||||||
|
{
|
||||||
|
if(getModeIndex() == 3) // Single Channel
|
||||||
|
{
|
||||||
|
intPos += 17;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
intPos += 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // MPEG Version 2.0 or 2.5
|
||||||
|
{
|
||||||
|
if(getModeIndex() == 3) // Single Channel
|
||||||
|
{
|
||||||
|
intPos += 9;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
intPos += 17;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the MP3 has a variable bitrate
|
||||||
|
fs.Position = intPos;
|
||||||
|
fs.Read(bytVBitRate,0,12);
|
||||||
|
boolVBitRate = LoadVBRHeader(bytVBitRate);
|
||||||
|
|
||||||
|
// Once the file's read in, then assign the properties of the file to the public variables
|
||||||
|
mFileDetails.intBitRate = getBitrate();
|
||||||
|
mFileDetails.intFrequency = getFrequency();
|
||||||
|
mFileDetails.strMode = getMode();
|
||||||
|
mFileDetails.intLength = getLengthInSeconds();
|
||||||
|
mFileDetails.strLengthFormatted = getFormattedLength();
|
||||||
|
fs.Close();
|
||||||
|
return mFileDetails;
|
||||||
|
}
|
||||||
|
throw new Mp3FormatException(fileName, "Invalid mp3 file");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadMP3Header(byte[] c)
|
||||||
|
{
|
||||||
|
// this thing is quite interesting, it works like the following
|
||||||
|
// c[0] = 00000011
|
||||||
|
// c[1] = 00001100
|
||||||
|
// c[2] = 00110000
|
||||||
|
// c[3] = 11000000
|
||||||
|
// the operator << means that we'll move the bits in that direction
|
||||||
|
// 00000011 << 24 = 00000011000000000000000000000000
|
||||||
|
// 00001100 << 16 = 000011000000000000000000
|
||||||
|
// 00110000 << 24 = 0011000000000000
|
||||||
|
// 11000000 = 11000000
|
||||||
|
// +_________________________________
|
||||||
|
// 00000011000011000011000011000000
|
||||||
|
bithdr = (ulong)(((c[0] & 255) << 24) | ((c[1] & 255) << 16) | ((c[2] & 255) << 8) | ((c[3] & 255)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool LoadVBRHeader(byte[] inputheader)
|
||||||
|
{
|
||||||
|
// If it's a variable bitrate MP3, the first 4 bytes will read 'Xing'
|
||||||
|
// since they're the ones who added variable bitrate-edness to MP3s
|
||||||
|
if(inputheader[0] == 88 && inputheader[1] == 105 &&
|
||||||
|
inputheader[2] == 110 && inputheader[3] == 103)
|
||||||
|
{
|
||||||
|
int flags = (((inputheader[4] & 255) << 24) | ((inputheader[5] & 255) << 16) | ((inputheader[6] & 255) << 8) | ((inputheader[7] & 255)));
|
||||||
|
if((flags & 0x0001) == 1)
|
||||||
|
{
|
||||||
|
intVFrames = (((inputheader[8] & 255) << 24) | ((inputheader[9] & 255) << 16) | ((inputheader[10] & 255) << 8) | ((inputheader[11] & 255)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
intVFrames = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsValidHeader()
|
||||||
|
{
|
||||||
|
return (((getFrameSync() & 2047)==2047) &&
|
||||||
|
((getVersionIndex() & 3)!= 1) &&
|
||||||
|
((getLayerIndex() & 3)!= 0) &&
|
||||||
|
((getBitrateIndex() & 15)!= 0) &&
|
||||||
|
((getBitrateIndex() & 15)!= 15) &&
|
||||||
|
((getFrequencyIndex() & 3)!= 3) &&
|
||||||
|
((getEmphasisIndex() & 3)!= 2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getFrameSync()
|
||||||
|
{
|
||||||
|
return (int)((bithdr>>21) & 2047);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getVersionIndex()
|
||||||
|
{
|
||||||
|
return (int)((bithdr>>19) & 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLayerIndex()
|
||||||
|
{
|
||||||
|
return (int)((bithdr>>17) & 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//private int getProtectionBit()
|
||||||
|
//{
|
||||||
|
// return (int)((bithdr>>16) & 1);
|
||||||
|
//}
|
||||||
|
|
||||||
|
private int getBitrateIndex()
|
||||||
|
{
|
||||||
|
return (int)((bithdr>>12) & 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getFrequencyIndex()
|
||||||
|
{
|
||||||
|
return (int)((bithdr>>10) & 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//private int getPaddingBit()
|
||||||
|
//{
|
||||||
|
// return (int)((bithdr>>9) & 1);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private int getPrivateBit()
|
||||||
|
//{
|
||||||
|
// return (int)((bithdr>>8) & 1);
|
||||||
|
//}
|
||||||
|
|
||||||
|
private int getModeIndex()
|
||||||
|
{
|
||||||
|
return (int)((bithdr>>6) & 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//private int getModeExtIndex()
|
||||||
|
//{
|
||||||
|
// return (int)((bithdr>>4) & 3);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private int getCoprightBit()
|
||||||
|
//{
|
||||||
|
// return (int)((bithdr>>3) & 1);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private int getOrginalBit()
|
||||||
|
//{
|
||||||
|
// return (int)((bithdr>>2) & 1);
|
||||||
|
//}
|
||||||
|
|
||||||
|
private int getEmphasisIndex()
|
||||||
|
{
|
||||||
|
return (int)(bithdr & 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//private double getVersion()
|
||||||
|
//{
|
||||||
|
// double[] table = {2.5, 0.0, 2.0, 1.0};
|
||||||
|
// return table[getVersionIndex()];
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private int getLayer()
|
||||||
|
//{
|
||||||
|
// return (int)(4 - getLayerIndex());
|
||||||
|
//}
|
||||||
|
|
||||||
|
private int getBitrate()
|
||||||
|
{
|
||||||
|
// If the file has a variable bitrate, then we return an integer average bitrate,
|
||||||
|
// otherwise, we use a lookup table to return the bitrate
|
||||||
|
if(boolVBitRate)
|
||||||
|
{
|
||||||
|
double medFrameSize = (double)mFileDetails.lngFileSize/ (double)getNumberOfFrames();
|
||||||
|
return (int)((medFrameSize * getFrequency()) / (1000.0 * ((getLayerIndex()==3) ? 12.0 : 144.0)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int[,,] table = {
|
||||||
|
{ // MPEG 2 & 2.5
|
||||||
|
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0}, // Layer III
|
||||||
|
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0}, // Layer II
|
||||||
|
{0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0} // Layer I
|
||||||
|
},
|
||||||
|
{ // MPEG 1
|
||||||
|
{0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,0}, // Layer III
|
||||||
|
{0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, // Layer II
|
||||||
|
{0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448,0} // Layer I
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return table[getVersionIndex() & 1, getLayerIndex()-1, getBitrateIndex()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getFrequency()
|
||||||
|
{
|
||||||
|
int[,] table = {
|
||||||
|
{32000, 16000, 8000}, // MPEG 2.5
|
||||||
|
{ 0, 0, 0}, // reserved
|
||||||
|
{22050, 24000, 16000}, // MPEG 2
|
||||||
|
{44100, 48000, 32000} // MPEG 1
|
||||||
|
};
|
||||||
|
|
||||||
|
return table[getVersionIndex(), getFrequencyIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
private string getMode()
|
||||||
|
{
|
||||||
|
switch(getModeIndex())
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return "Stereo";
|
||||||
|
case 1:
|
||||||
|
return "Joint Stereo";
|
||||||
|
case 2:
|
||||||
|
return "Dual Channel";
|
||||||
|
case 3:
|
||||||
|
return "Single Channel";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLengthInSeconds()
|
||||||
|
{
|
||||||
|
// "intKilBitFileSize" made by dividing by 1000 in order to match the "Kilobits/second"
|
||||||
|
int intKiloBitFileSize = ((8 * (int)mFileDetails.lngFileSize) / 1000);
|
||||||
|
return (intKiloBitFileSize/getBitrate());
|
||||||
|
}
|
||||||
|
|
||||||
|
private string getFormattedLength()
|
||||||
|
{
|
||||||
|
// Complete number of seconds
|
||||||
|
int s = getLengthInSeconds();
|
||||||
|
|
||||||
|
// Seconds to display
|
||||||
|
int ss = s%60;
|
||||||
|
|
||||||
|
// Complete number of minutes
|
||||||
|
int m = (s-ss)/60;
|
||||||
|
|
||||||
|
// Minutes to display
|
||||||
|
int mm = m%60;
|
||||||
|
|
||||||
|
// Complete number of hours
|
||||||
|
int h = (m-mm)/60;
|
||||||
|
|
||||||
|
// Make "hh:mm:ss"
|
||||||
|
return h.ToString("D2") + ":" + mm.ToString("D2") + ":" + ss.ToString("D2");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getNumberOfFrames()
|
||||||
|
{
|
||||||
|
// Again, the number of MPEG frames is dependant on whether it's a variable bitrate MP3 or not
|
||||||
|
if (!boolVBitRate)
|
||||||
|
{
|
||||||
|
double medFrameSize = (((getLayerIndex()==3) ? 12 : 144) *((1000.0 * (float)getBitrate())/(float)getFrequency()));
|
||||||
|
return (int)(mFileDetails.lngFileSize/medFrameSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return intVFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ReadMP3Tag(ref Mp3FileDetails paramMP3)
|
||||||
|
{
|
||||||
|
// Read the 128 byte ID3 tag into a byte array
|
||||||
|
FileStream oFileStream;
|
||||||
|
oFileStream = new FileStream(paramMP3.fileComplete, FileMode.Open);
|
||||||
|
byte[] bBuffer = new byte[128];
|
||||||
|
oFileStream.Seek(-128, SeekOrigin.End);
|
||||||
|
oFileStream.Read(bBuffer, 0, 128);
|
||||||
|
oFileStream.Close();
|
||||||
|
|
||||||
|
// Convert the Byte Array to a String
|
||||||
|
Encoding instEncoding = new ASCIIEncoding(); // NB: Encoding is an Abstract class
|
||||||
|
string id3Tag = instEncoding.GetString(bBuffer);
|
||||||
|
|
||||||
|
// If there is an attched ID3 v1.x TAG then read it
|
||||||
|
if (id3Tag.Substring(0, 3) == "TAG")
|
||||||
|
{
|
||||||
|
paramMP3.id3Title = id3Tag.Substring(3, 30).Trim();
|
||||||
|
paramMP3.id3Artist = id3Tag.Substring(33, 30).Trim();
|
||||||
|
paramMP3.id3Album = id3Tag.Substring(63, 30).Trim();
|
||||||
|
paramMP3.id3Year = id3Tag.Substring(93, 4).Trim();
|
||||||
|
paramMP3.id3Comment = id3Tag.Substring(97, 28).Trim();
|
||||||
|
|
||||||
|
// Get the track number if TAG conforms to ID3 v1.1
|
||||||
|
if (id3Tag[125] == 0)
|
||||||
|
paramMP3.id3TrackNumber = bBuffer[126];
|
||||||
|
else
|
||||||
|
paramMP3.id3TrackNumber = 0;
|
||||||
|
paramMP3.id3Genre = bBuffer[127];
|
||||||
|
paramMP3.hasID3Tag = true;
|
||||||
|
// ********* IF USED IN ANGER: ENSURE to test for non-numeric year
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ID3 Tag not found so create an empty TAG in case the user saces later
|
||||||
|
paramMP3.id3Title = "";
|
||||||
|
paramMP3.id3Artist = "";
|
||||||
|
paramMP3.id3Album = "";
|
||||||
|
paramMP3.id3Year = "";
|
||||||
|
paramMP3.id3Comment = "";
|
||||||
|
paramMP3.id3TrackNumber = 0;
|
||||||
|
paramMP3.id3Genre = 0;
|
||||||
|
paramMP3.hasID3Tag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateMP3ID3Tag(ref Mp3FileDetails paramMP3)
|
||||||
|
{
|
||||||
|
// Trim any whitespace
|
||||||
|
paramMP3.id3Title = paramMP3.id3Title.Trim();
|
||||||
|
paramMP3.id3Artist = paramMP3.id3Artist.Trim();
|
||||||
|
paramMP3.id3Album = paramMP3.id3Album.Trim();
|
||||||
|
paramMP3.id3Year = paramMP3.id3Year.Trim();
|
||||||
|
paramMP3.id3Comment = paramMP3.id3Comment.Trim();
|
||||||
|
|
||||||
|
// Ensure all properties are correct size
|
||||||
|
if (paramMP3.id3Title.Length > 30) paramMP3.id3Title = paramMP3.id3Title.Substring(0, 30);
|
||||||
|
if (paramMP3.id3Artist.Length > 30) paramMP3.id3Artist = paramMP3.id3Artist.Substring(0, 30);
|
||||||
|
if (paramMP3.id3Album.Length > 30) paramMP3.id3Album = paramMP3.id3Album.Substring(0, 30);
|
||||||
|
if (paramMP3.id3Year.Length > 4) paramMP3.id3Year = paramMP3.id3Year.Substring(0, 4);
|
||||||
|
if (paramMP3.id3Comment.Length > 28) paramMP3.id3Comment = paramMP3.id3Comment.Substring(0, 28);
|
||||||
|
|
||||||
|
// Build a new ID3 Tag (128 Bytes)
|
||||||
|
byte[] tagByteArray = new byte[128];
|
||||||
|
for (int i = 0; i < tagByteArray.Length; i++)
|
||||||
|
tagByteArray[i] = 0; // Initialise array to nulls
|
||||||
|
|
||||||
|
// Convert the Byte Array to a String
|
||||||
|
Encoding instEncoding = new ASCIIEncoding(); // NB: Encoding is an Abstract class // ************ To DO: Make a shared instance of ASCIIEncoding so we don't keep creating/destroying it
|
||||||
|
// Copy "TAG" to Array
|
||||||
|
byte[] workingByteArray = instEncoding.GetBytes("TAG");
|
||||||
|
Array.Copy(workingByteArray, 0, tagByteArray, 0, workingByteArray.Length);
|
||||||
|
// Copy Title to Array
|
||||||
|
workingByteArray = instEncoding.GetBytes(paramMP3.id3Title);
|
||||||
|
Array.Copy(workingByteArray, 0, tagByteArray, 3, workingByteArray.Length);
|
||||||
|
// Copy Artist to Array
|
||||||
|
workingByteArray = instEncoding.GetBytes(paramMP3.id3Artist);
|
||||||
|
Array.Copy(workingByteArray, 0, tagByteArray, 33, workingByteArray.Length);
|
||||||
|
// Copy Album to Array
|
||||||
|
workingByteArray = instEncoding.GetBytes(paramMP3.id3Album);
|
||||||
|
Array.Copy(workingByteArray, 0, tagByteArray, 63, workingByteArray.Length);
|
||||||
|
// Copy Year to Array
|
||||||
|
workingByteArray = instEncoding.GetBytes(paramMP3.id3Year);
|
||||||
|
Array.Copy(workingByteArray, 0, tagByteArray, 93, workingByteArray.Length);
|
||||||
|
// Copy Comment to Array
|
||||||
|
workingByteArray = instEncoding.GetBytes(paramMP3.id3Comment);
|
||||||
|
Array.Copy(workingByteArray, 0, tagByteArray, 97, workingByteArray.Length);
|
||||||
|
// Copy Track and Genre to Array
|
||||||
|
tagByteArray[126] = paramMP3.id3TrackNumber;
|
||||||
|
tagByteArray[127] = paramMP3.id3Genre;
|
||||||
|
|
||||||
|
// SAVE TO DISK: Replace the final 128 Bytes with our new ID3 tag
|
||||||
|
FileStream oFileStream = new FileStream(paramMP3.fileComplete, FileMode.Open);
|
||||||
|
if (paramMP3.hasID3Tag)
|
||||||
|
oFileStream.Seek(-128, SeekOrigin.End);
|
||||||
|
else
|
||||||
|
oFileStream.Seek(0, SeekOrigin.End);
|
||||||
|
oFileStream.Write(tagByteArray, 0, 128);
|
||||||
|
oFileStream.Close();
|
||||||
|
paramMP3.hasID3Tag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+174
@@ -0,0 +1,174 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Collections;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for Form1.
|
||||||
|
/// </summary>
|
||||||
|
public class MakeSubdir : System.Windows.Forms.Form
|
||||||
|
{
|
||||||
|
private System.Windows.Forms.Button selectDirectoryButton;
|
||||||
|
private System.Windows.Forms.TextBox m3uDirectoryTextBox;
|
||||||
|
private System.Windows.Forms.TextBox outputTextBox;
|
||||||
|
private System.Windows.Forms.Button m3uMakeButton;
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.Container components = null;
|
||||||
|
|
||||||
|
public MakeSubdir()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Required for Windows Form Designer support
|
||||||
|
//
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Add any constructor code after InitializeComponent call
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
protected override void Dispose( bool disposing )
|
||||||
|
{
|
||||||
|
if( disposing )
|
||||||
|
{
|
||||||
|
if (components != null)
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose( disposing );
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.m3uDirectoryTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.outputTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.selectDirectoryButton = new System.Windows.Forms.Button();
|
||||||
|
this.m3uMakeButton = new System.Windows.Forms.Button();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// m3uDirectoryTextBox
|
||||||
|
//
|
||||||
|
this.m3uDirectoryTextBox.Enabled = false;
|
||||||
|
this.m3uDirectoryTextBox.Location = new System.Drawing.Point(8, 8);
|
||||||
|
this.m3uDirectoryTextBox.Name = "m3uDirectoryTextBox";
|
||||||
|
this.m3uDirectoryTextBox.Size = new System.Drawing.Size(176, 20);
|
||||||
|
this.m3uDirectoryTextBox.TabIndex = 0;
|
||||||
|
this.m3uDirectoryTextBox.Text = "";
|
||||||
|
//
|
||||||
|
// outputTextBox
|
||||||
|
//
|
||||||
|
this.outputTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.outputTextBox.Location = new System.Drawing.Point(8, 88);
|
||||||
|
this.outputTextBox.Multiline = true;
|
||||||
|
this.outputTextBox.Name = "outputTextBox";
|
||||||
|
this.outputTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||||
|
this.outputTextBox.Size = new System.Drawing.Size(272, 168);
|
||||||
|
this.outputTextBox.TabIndex = 1;
|
||||||
|
this.outputTextBox.Text = "";
|
||||||
|
//
|
||||||
|
// selectDirectoryButton
|
||||||
|
//
|
||||||
|
this.selectDirectoryButton.Location = new System.Drawing.Point(208, 8);
|
||||||
|
this.selectDirectoryButton.Name = "selectDirectoryButton";
|
||||||
|
this.selectDirectoryButton.TabIndex = 2;
|
||||||
|
this.selectDirectoryButton.Text = "Select Dir...";
|
||||||
|
this.selectDirectoryButton.Click += new System.EventHandler(this.selectDirectoryButton_Click);
|
||||||
|
//
|
||||||
|
// m3uMakeButton
|
||||||
|
//
|
||||||
|
this.m3uMakeButton.Enabled = false;
|
||||||
|
this.m3uMakeButton.Location = new System.Drawing.Point(208, 40);
|
||||||
|
this.m3uMakeButton.Name = "m3uMakeButton";
|
||||||
|
this.m3uMakeButton.TabIndex = 3;
|
||||||
|
this.m3uMakeButton.Text = "Make M3u";
|
||||||
|
this.m3uMakeButton.Click += new System.EventHandler(this.m3uMakeButton_Click);
|
||||||
|
//
|
||||||
|
// MakeSubdir
|
||||||
|
//
|
||||||
|
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
||||||
|
this.ClientSize = new System.Drawing.Size(292, 266);
|
||||||
|
this.Controls.Add(this.m3uMakeButton);
|
||||||
|
this.Controls.Add(this.selectDirectoryButton);
|
||||||
|
this.Controls.Add(this.outputTextBox);
|
||||||
|
this.Controls.Add(this.m3uDirectoryTextBox);
|
||||||
|
this.Name = "MakeSubdir";
|
||||||
|
this.Text = "M3u Make";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
Application.Run(new MakeSubdir());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectDirectoryButton_Click(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
FolderBrowserDialog fbd = new FolderBrowserDialog();
|
||||||
|
DialogResult dialogResult = fbd.ShowDialog(this);
|
||||||
|
|
||||||
|
if (dialogResult == DialogResult.OK)
|
||||||
|
{
|
||||||
|
m3uDirectoryTextBox.Text = fbd.SelectedPath;
|
||||||
|
}
|
||||||
|
UpdateRunButton();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateRunButton()
|
||||||
|
{
|
||||||
|
if (m3uDirectoryTextBox.Text != null && m3uDirectoryTextBox.Text!="" && Directory.Exists(m3uDirectoryTextBox.Text))
|
||||||
|
{
|
||||||
|
m3uMakeButton.Enabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m3uMakeButton.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateM3uThread()
|
||||||
|
{
|
||||||
|
CreateM3uRecursive(new DirectoryInfo(m3uDirectoryTextBox.Text));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateM3uRecursive(DirectoryInfo info)
|
||||||
|
{
|
||||||
|
CreateM3u cm3u = new CreateM3u(info);
|
||||||
|
cm3u.Create();
|
||||||
|
outputTextBox.AppendText("Created " + cm3u.OutputFilename + Environment.NewLine);
|
||||||
|
foreach (DirectoryInfo subDir in info.GetDirectories())
|
||||||
|
{
|
||||||
|
CreateM3uRecursive(subDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void m3uMakeButton_Click(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
Thread t = new Thread(new ThreadStart(CreateM3uThread));
|
||||||
|
t.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used forserialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="m3uDirectoryTextBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uDirectoryTextBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uDirectoryTextBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="outputTextBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="selectDirectoryButton.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="m3uMakeButton.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>(Default)</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Name">
|
||||||
|
<value>MakeSubdir</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>8, 8</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>80</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class Mp3Encoder : ProcessStreamWrapper
|
||||||
|
{
|
||||||
|
public Mp3Encoder(Mp3EncodingOptions encOpt)
|
||||||
|
: base(encOpt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mp3Encoder(Mp3EncodingOptions encOpt, Stream outputStream)
|
||||||
|
: base(encOpt, outputStream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ProcessExecutableFilename
|
||||||
|
{
|
||||||
|
get { return @"c:\console\audio\lame.exe"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,437 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// LAME 32bits version 3.97 (beta 1, Oct 16 2005) (http://www.mp3dev.org/)
|
||||||
|
///
|
||||||
|
/// usage: lame [options] <infile> [outfile]
|
||||||
|
///
|
||||||
|
/// <infile> and/or <outfile> can be "-", which means stdin/stdout.
|
||||||
|
///
|
||||||
|
/// RECOMMENDED:
|
||||||
|
/// lame -V2 input.wav output.mp3
|
||||||
|
///
|
||||||
|
/// OPTIONS:
|
||||||
|
/// Input options:
|
||||||
|
/// -r input is raw pcm
|
||||||
|
/// -x force byte-swapping of input
|
||||||
|
/// -s sfreq sampling frequency of input file (kHz) - default 44.1 kHz
|
||||||
|
/// --bitwidth w input bit width is w (default 16)
|
||||||
|
/// --scale <arg> scale input (multiply PCM data) by <arg>
|
||||||
|
/// --scale-l <arg> scale channel 0 (left) input (multiply PCM data) by <arg>
|
||||||
|
/// --scale-r <arg> scale channel 1 (right) input (multiply PCM data) by <arg>
|
||||||
|
/// --mp1input input file is a MPEG Layer I file
|
||||||
|
/// --mp2input input file is a MPEG Layer II file
|
||||||
|
/// --mp3input input file is a MPEG Layer III file
|
||||||
|
/// --nogap <file1> <file2> <...>
|
||||||
|
/// gapless encoding for a set of contiguous files
|
||||||
|
/// --nogapout <dir>
|
||||||
|
/// output dir for gapless encoding (must precede --nogap)
|
||||||
|
/// --nogaptags allow the use of VBR tags in gapless encoding
|
||||||
|
///
|
||||||
|
/// Operational options:
|
||||||
|
/// -a downmix from stereo to mono file for mono encoding
|
||||||
|
/// -m <mode> (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono
|
||||||
|
/// default is (j) or (s) depending on bitrate
|
||||||
|
/// joint = joins the best possible of MS and LR stereo
|
||||||
|
/// simple = force LR stereo on all frames
|
||||||
|
/// force = force MS stereo on all frames.
|
||||||
|
/// --preset type type must be "medium", "standard", "extreme", "insane",
|
||||||
|
/// or a value for an average desired bitrate and depending
|
||||||
|
/// on the value specified, appropriate quality settings will
|
||||||
|
/// be used.
|
||||||
|
/// "--preset help" gives more info on these
|
||||||
|
/// --comp <arg> choose bitrate to achive a compression ratio of <arg>
|
||||||
|
/// --replaygain-fast compute RG fast but slightly inaccurately (default)
|
||||||
|
/// --replaygain-accurate compute RG more accurately and find the peak sample
|
||||||
|
/// --noreplaygain disable ReplayGain analysis
|
||||||
|
/// --clipdetect enable --replaygain-accurate and print a message whether
|
||||||
|
/// clipping occurs and how far the waveform is from full scale
|
||||||
|
/// --freeformat produce a free format bitstream
|
||||||
|
/// --decode input=mp3 file, output=wav
|
||||||
|
/// -t disable writing wav header when using --decode
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Verbosity:
|
||||||
|
/// --disptime <arg>print progress report every arg seconds
|
||||||
|
/// -S don't print progress report, VBR histograms
|
||||||
|
/// --nohist disable VBR histogram display
|
||||||
|
/// --silent don't print anything on screen
|
||||||
|
/// --quiet don't print anything on screen
|
||||||
|
/// --brief print more useful information
|
||||||
|
/// --verbose print a lot of useful information
|
||||||
|
///
|
||||||
|
/// Noise shaping & psycho acoustic algorithms:
|
||||||
|
/// -q <arg> <arg> = 0...9. Default -q 5
|
||||||
|
/// -q 0: Highest quality, very slow
|
||||||
|
/// -q 9: Poor quality, but fast
|
||||||
|
/// -h Same as -q 2. Recommended.
|
||||||
|
/// -f Same as -q 7. Fast, ok quality
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// CBR (constant bitrate, the default) options:
|
||||||
|
/// -b <bitrate> set the bitrate in kbps, default 128 kbps
|
||||||
|
/// --cbr enforce use of constant bitrate
|
||||||
|
///
|
||||||
|
/// ABR options:
|
||||||
|
/// --abr <bitrate> specify average bitrate desired (instead of quality)
|
||||||
|
///
|
||||||
|
/// VBR options:
|
||||||
|
/// -v use variable bitrate (VBR) (--vbr-old)
|
||||||
|
/// --vbr-old use old variable bitrate (VBR) routine
|
||||||
|
/// --vbr-new use new variable bitrate (VBR) routine
|
||||||
|
/// -V n quality setting for VBR. default n=4
|
||||||
|
/// 0=high quality,bigger files. 9=smaller files
|
||||||
|
/// -b <bitrate> specify minimum allowed bitrate, default 32 kbps
|
||||||
|
/// -B <bitrate> specify maximum allowed bitrate, default 320 kbps
|
||||||
|
/// -F strictly enforce the -b option, for use with players that
|
||||||
|
/// do not support low bitrate mp3
|
||||||
|
/// -t disable writing LAME Tag
|
||||||
|
/// -T enable and force writing LAME Tag
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// PSY related:
|
||||||
|
/// --short use short blocks when appropriate
|
||||||
|
/// --noshort do not use short blocks
|
||||||
|
/// --allshort use only short blocks
|
||||||
|
/// --notemp disable temporal masking effect
|
||||||
|
/// --nssafejoint M/S switching criterion
|
||||||
|
/// --nsmsfix <arg> M/S switching tuning [effective 0-3.5]
|
||||||
|
/// --interch x adjust inter-channel masking ratio
|
||||||
|
/// --ns-bass x adjust masking for sfbs 0 - 6 (long) 0 - 5 (short)
|
||||||
|
/// --ns-alto x adjust masking for sfbs 7 - 13 (long) 6 - 10 (short)
|
||||||
|
/// --ns-treble x adjust masking for sfbs 14 - 21 (long) 11 - 12 (short)
|
||||||
|
/// --ns-sfb21 x change ns-treble by x dB for sfb21
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// experimental switches:
|
||||||
|
/// -X n[,m] selects between different noise measurements
|
||||||
|
/// n for long block, m for short. if m is omitted, m = n
|
||||||
|
/// -Y lets LAME ignore noise in sfb21, like in CBR
|
||||||
|
/// -Z [n] currently no effects
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// MP3 header/stream options:
|
||||||
|
/// -e <emp> de-emphasis n/5/c (obsolete)
|
||||||
|
/// -c mark as copyright
|
||||||
|
/// -o mark as non-original
|
||||||
|
/// -p error protection. adds 16 bit checksum to every frame
|
||||||
|
/// (the checksum is computed correctly)
|
||||||
|
/// --nores disable the bit reservoir
|
||||||
|
/// --strictly-enforce-ISO comply as much as possible to ISO MPEG spec
|
||||||
|
///
|
||||||
|
/// Filter options:
|
||||||
|
/// -k keep ALL frequencies (disables all filters),
|
||||||
|
/// Can cause ringing and twinkling
|
||||||
|
/// --lowpass <freq> frequency(kHz), lowpass filter cutoff above freq
|
||||||
|
/// --lowpass-width <freq> frequency(kHz) - default 15% of lowpass freq
|
||||||
|
/// --highpass <freq> frequency(kHz), highpass filter cutoff below freq
|
||||||
|
/// --highpass-width <freq> frequency(kHz) - default 15% of highpass freq
|
||||||
|
/// --resample <sfreq> sampling frequency of output file(kHz)- default=automatic
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// ID3 tag options:
|
||||||
|
/// --tt <title> audio/song title (max 30 chars for version 1 tag)
|
||||||
|
/// --ta <artist> audio/song artist (max 30 chars for version 1 tag)
|
||||||
|
/// --tl <album> audio/song album (max 30 chars for version 1 tag)
|
||||||
|
/// --ty <year> audio/song year of issue (1 to 9999)
|
||||||
|
/// --tc <comment> user-defined text (max 30 chars for v1 tag, 28 for v1.1)
|
||||||
|
/// --tn <track> audio/song track number (1 to 255, creates v1.1 tag)
|
||||||
|
/// --tg <genre> audio/song genre (name or number in list)
|
||||||
|
/// --add-id3v2 force addition of version 2 tag
|
||||||
|
/// --id3v1-only add only a version 1 tag
|
||||||
|
/// --id3v2-only add only a version 2 tag
|
||||||
|
/// --space-id3v1 pad version 1 tag with spaces instead of nulls
|
||||||
|
/// --pad-id3v2 pad version 2 tag with extra 128 bytes
|
||||||
|
/// --genre-list print alphabetically sorted ID3 genre list and exit
|
||||||
|
/// --ignore-tag-errors ignore errors in values passed for tags
|
||||||
|
///
|
||||||
|
/// Note: A version 2 tag will NOT be added unless one of the input fields
|
||||||
|
/// won't fit in a version 1 tag (e.g. the title string is longer than 30
|
||||||
|
/// characters), or the '--add-id3v2' or '--id3v2-only' options are used,
|
||||||
|
/// or output is redirected to stdout.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// MS-Windows-specific options:
|
||||||
|
/// --priority <type> sets the process priority:
|
||||||
|
/// 0,1 = Low priority (IDLE_PRIORITY_CLASS)
|
||||||
|
/// 2 = normal priority (NORMAL_PRIORITY_CLASS, defau
|
||||||
|
/// lt)
|
||||||
|
/// 3,4 = High priority (HIGH_PRIORITY_CLASS))
|
||||||
|
/// Note: Calling '--priority' without a parameter will select priority 0.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Platform specific:
|
||||||
|
/// --noasm <instructions> disable assembly optimizations for mmx/3dnow/sse
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// MPEG-1 layer III sample frequencies (kHz): 32 48 44.1
|
||||||
|
/// bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320
|
||||||
|
///
|
||||||
|
/// MPEG-2 layer III sample frequencies (kHz): 16 24 22.05
|
||||||
|
/// bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160
|
||||||
|
///
|
||||||
|
/// MPEG-2.5 layer III sample frequencies (kHz): 8 12 11.025
|
||||||
|
/// bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160
|
||||||
|
///</summary>
|
||||||
|
public class Mp3EncodingOptions : ProcessArguments
|
||||||
|
{
|
||||||
|
#region Private variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the bitrate in kbps, default 128 kbps -b <bitrate>
|
||||||
|
/// </summary>
|
||||||
|
private BitRate mBitRate = BitRate.KBPS_0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono (-m)
|
||||||
|
/// </summary>
|
||||||
|
private ChannelMode mChannelMode = ChannelMode.JointStereo;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input=mp3 file, output=wav (--decode)
|
||||||
|
/// </summary>
|
||||||
|
private bool mDecodeWav;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// disable writing wav header when using --decode (-t)
|
||||||
|
/// </summary>
|
||||||
|
private bool mDisableWavHeader;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// force byte-swapping of input (-x)
|
||||||
|
/// </summary>
|
||||||
|
private bool mForceByteSwappingOfInput;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// produce a free format bitstream (--freeformat)
|
||||||
|
/// </summary>
|
||||||
|
private bool mFreeFormat;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Input filename. Can be "-", which means stdin.
|
||||||
|
/// </summary>
|
||||||
|
private string mInfile;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// downmix from stereo to mono file for mono encoding (-a)
|
||||||
|
/// </summary>
|
||||||
|
private bool mMonoDownmixing;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input file is a MPEG Layer III file (--mp3input)
|
||||||
|
/// </summary>
|
||||||
|
private bool mMp3Input;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Output filename. Can be "-", which means stdout.
|
||||||
|
/// </summary>
|
||||||
|
private string mOutfile;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input is raw pcm (-r)
|
||||||
|
/// </summary>
|
||||||
|
private bool mRawPCMInputMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input bit width is w (default 16) (--bitwidth w)
|
||||||
|
/// </summary>
|
||||||
|
private int mRawPCMInputSampleRate = 16;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sampling frequency of input file (kHz) - default 44.1 kHz (-s sfreq)
|
||||||
|
/// </summary>
|
||||||
|
private SampleRateFrequency mRawPCMInputSampleSize = SampleRateFrequency.Hz_44100;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Input filename. Can be "-", which means stdin.
|
||||||
|
/// </summary>
|
||||||
|
public string Infile
|
||||||
|
{
|
||||||
|
get { return mInfile; }
|
||||||
|
set { mInfile = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Output filename. Can be "-", which means stdout.
|
||||||
|
/// </summary>
|
||||||
|
public string Outfile
|
||||||
|
{
|
||||||
|
get { return mOutfile; }
|
||||||
|
set { mOutfile = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input is raw pcm (-r)
|
||||||
|
/// </summary>
|
||||||
|
public bool RawPCMInputMode
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputMode; }
|
||||||
|
set { mRawPCMInputMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// force byte-swapping of input (-x)
|
||||||
|
/// </summary>
|
||||||
|
public bool ForceByteSwappingOfInput
|
||||||
|
{
|
||||||
|
get { return mForceByteSwappingOfInput; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mForceByteSwappingOfInput = value;
|
||||||
|
mRawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sampling frequency of input file (kHz) - default 44.1 kHz (-s sfreq)
|
||||||
|
/// </summary>
|
||||||
|
public SampleRateFrequency RawPCMInputSampleSize
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleSize; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleSize = value;
|
||||||
|
mRawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input bit width is w (default 16) (--bitwidth w)
|
||||||
|
/// </summary>
|
||||||
|
public int RawPCMInputSampleRate
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleRate; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleRate = value;
|
||||||
|
mRawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input file is a MPEG Layer III file (--mp3input)
|
||||||
|
/// </summary>
|
||||||
|
public bool Mp3Input
|
||||||
|
{
|
||||||
|
get { return mMp3Input; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mMp3Input = value;
|
||||||
|
if (mMp3Input)
|
||||||
|
mRawPCMInputMode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// downmix from stereo to mono file for mono encoding (-a)
|
||||||
|
/// </summary>
|
||||||
|
public bool MonoDownmixing
|
||||||
|
{
|
||||||
|
get { return mMonoDownmixing; }
|
||||||
|
set { mMonoDownmixing = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono (-m)
|
||||||
|
/// </summary>
|
||||||
|
public ChannelMode ChannelMode
|
||||||
|
{
|
||||||
|
get { return mChannelMode; }
|
||||||
|
set { mChannelMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// produce a free format bitstream (--freeformat)
|
||||||
|
/// </summary>
|
||||||
|
public bool Freeformat
|
||||||
|
{
|
||||||
|
get { return mFreeFormat; }
|
||||||
|
set { mFreeFormat = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// input=mp3 file, output=wav (--decode)
|
||||||
|
/// </summary>
|
||||||
|
public bool DecodeWav
|
||||||
|
{
|
||||||
|
get { return mDecodeWav; }
|
||||||
|
set { mDecodeWav = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// disable writing wav header when using --decode (-t)
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableWavHeader
|
||||||
|
{
|
||||||
|
get { return mDisableWavHeader; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mDisableWavHeader = value;
|
||||||
|
if (mDisableWavHeader)
|
||||||
|
DecodeWav = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitRate BitRate
|
||||||
|
{
|
||||||
|
get { return mBitRate; }
|
||||||
|
set { mBitRate = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representing the command line arguments specified by the properties in the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override string GetCommandLineArguments()
|
||||||
|
{
|
||||||
|
var stringBuilder = new StringBuilder();
|
||||||
|
if (mRawPCMInputMode)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" -r");
|
||||||
|
if (mForceByteSwappingOfInput)
|
||||||
|
stringBuilder.Append(" -x");
|
||||||
|
if (mRawPCMInputSampleSize != SampleRateFrequency.Hz_44100)
|
||||||
|
stringBuilder.Append(" -s " +
|
||||||
|
SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mRawPCMInputSampleSize));
|
||||||
|
if (mRawPCMInputSampleRate != 16)
|
||||||
|
stringBuilder.Append(" --bandwidth " + mRawPCMInputSampleRate);
|
||||||
|
}
|
||||||
|
if (mMp3Input)
|
||||||
|
stringBuilder.Append(" --mp3input");
|
||||||
|
if (mMonoDownmixing)
|
||||||
|
stringBuilder.Append(" -a");
|
||||||
|
if (mChannelMode != ChannelMode.JointStereo)
|
||||||
|
stringBuilder.Append(" -m " + ChannelModeUtility.GetChannelModeChar(mChannelMode));
|
||||||
|
|
||||||
|
if (mFreeFormat)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" --freeformat");
|
||||||
|
stringBuilder.Append(" -b " + BitRateFrequencyUtility.GetBitRateInt(BitRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDecodeWav)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" --decode");
|
||||||
|
if (mDisableWavHeader)
|
||||||
|
stringBuilder.Append(" -t");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(mInfile))
|
||||||
|
stringBuilder.Append(" " + GetQuotedCommandLineArgument(mInfile));
|
||||||
|
if (!string.IsNullOrEmpty(mOutfile))
|
||||||
|
stringBuilder.Append(" " + (mOutfile));
|
||||||
|
|
||||||
|
|
||||||
|
return stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Generated
+306
@@ -0,0 +1,306 @@
|
|||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
partial class Mp3ToAacBatch
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Mp3ToAacBatch));
|
||||||
|
this.inputListBox = new System.Windows.Forms.ListBox();
|
||||||
|
this.addFolderButton = new System.Windows.Forms.Button();
|
||||||
|
this.addFileButton = new System.Windows.Forms.Button();
|
||||||
|
this.moveUpButton = new System.Windows.Forms.Button();
|
||||||
|
this.moveDownButton = new System.Windows.Forms.Button();
|
||||||
|
this.sortButton = new System.Windows.Forms.Button();
|
||||||
|
this.updownSplitContainer = new System.Windows.Forms.SplitContainer();
|
||||||
|
this.inputLabel = new System.Windows.Forms.Label();
|
||||||
|
this.inputPanel = new System.Windows.Forms.Panel();
|
||||||
|
this.clearButton = new System.Windows.Forms.Button();
|
||||||
|
this.optionsPanel = new System.Windows.Forms.Panel();
|
||||||
|
this.singleFileCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
|
this.outputDirectoryTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.optionsLabel = new System.Windows.Forms.Label();
|
||||||
|
this.savePanel = new System.Windows.Forms.Panel();
|
||||||
|
this.saveLabel = new System.Windows.Forms.Label();
|
||||||
|
this.updownSplitContainer.Panel1.SuspendLayout();
|
||||||
|
this.updownSplitContainer.Panel2.SuspendLayout();
|
||||||
|
this.updownSplitContainer.SuspendLayout();
|
||||||
|
this.inputPanel.SuspendLayout();
|
||||||
|
this.optionsPanel.SuspendLayout();
|
||||||
|
this.savePanel.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// inputListBox
|
||||||
|
//
|
||||||
|
this.inputListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.inputListBox.FormattingEnabled = true;
|
||||||
|
this.inputListBox.Location = new System.Drawing.Point(6, 35);
|
||||||
|
this.inputListBox.Name = "inputListBox";
|
||||||
|
this.inputListBox.Size = new System.Drawing.Size(551, 264);
|
||||||
|
this.inputListBox.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// addFolderButton
|
||||||
|
//
|
||||||
|
this.addFolderButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.addFolderButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.addFolderButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.addFolderButton.Image = ((System.Drawing.Image)(resources.GetObject("addFolderButton.Image")));
|
||||||
|
this.addFolderButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.addFolderButton.Location = new System.Drawing.Point(470, 3);
|
||||||
|
this.addFolderButton.Name = "addFolderButton";
|
||||||
|
this.addFolderButton.Size = new System.Drawing.Size(87, 30);
|
||||||
|
this.addFolderButton.TabIndex = 2;
|
||||||
|
this.addFolderButton.Text = "Add Folder";
|
||||||
|
this.addFolderButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.addFolderButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// addFileButton
|
||||||
|
//
|
||||||
|
this.addFileButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.addFileButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.addFileButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.addFileButton.Image = ((System.Drawing.Image)(resources.GetObject("addFileButton.Image")));
|
||||||
|
this.addFileButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.addFileButton.Location = new System.Drawing.Point(390, 3);
|
||||||
|
this.addFileButton.Name = "addFileButton";
|
||||||
|
this.addFileButton.Size = new System.Drawing.Size(74, 30);
|
||||||
|
this.addFileButton.TabIndex = 3;
|
||||||
|
this.addFileButton.Text = "Add File";
|
||||||
|
this.addFileButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.addFileButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// moveUpButton
|
||||||
|
//
|
||||||
|
this.moveUpButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.moveUpButton.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.moveUpButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.moveUpButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.moveUpButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.moveUpButton.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.moveUpButton.Name = "moveUpButton";
|
||||||
|
this.moveUpButton.Size = new System.Drawing.Size(18, 107);
|
||||||
|
this.moveUpButton.TabIndex = 4;
|
||||||
|
this.moveUpButton.Text = "^|";
|
||||||
|
this.moveUpButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.moveUpButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// moveDownButton
|
||||||
|
//
|
||||||
|
this.moveDownButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.moveDownButton.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.moveDownButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.moveDownButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.moveDownButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.moveDownButton.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.moveDownButton.Name = "moveDownButton";
|
||||||
|
this.moveDownButton.Size = new System.Drawing.Size(18, 157);
|
||||||
|
this.moveDownButton.TabIndex = 5;
|
||||||
|
this.moveDownButton.Text = "|v";
|
||||||
|
this.moveDownButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.moveDownButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// sortButton
|
||||||
|
//
|
||||||
|
this.sortButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.sortButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.sortButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.sortButton.Image = ((System.Drawing.Image)(resources.GetObject("sortButton.Image")));
|
||||||
|
this.sortButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.sortButton.Location = new System.Drawing.Point(0, 307);
|
||||||
|
this.sortButton.Name = "sortButton";
|
||||||
|
this.sortButton.Size = new System.Drawing.Size(61, 30);
|
||||||
|
this.sortButton.TabIndex = 6;
|
||||||
|
this.sortButton.Text = "Sort";
|
||||||
|
this.sortButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.sortButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// updownSplitContainer
|
||||||
|
//
|
||||||
|
this.updownSplitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.updownSplitContainer.IsSplitterFixed = true;
|
||||||
|
this.updownSplitContainer.Location = new System.Drawing.Point(563, 35);
|
||||||
|
this.updownSplitContainer.Name = "updownSplitContainer";
|
||||||
|
this.updownSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||||
|
//
|
||||||
|
// updownSplitContainer.Panel1
|
||||||
|
//
|
||||||
|
this.updownSplitContainer.Panel1.Controls.Add(this.moveUpButton);
|
||||||
|
//
|
||||||
|
// updownSplitContainer.Panel2
|
||||||
|
//
|
||||||
|
this.updownSplitContainer.Panel2.Controls.Add(this.moveDownButton);
|
||||||
|
this.updownSplitContainer.Size = new System.Drawing.Size(18, 266);
|
||||||
|
this.updownSplitContainer.SplitterDistance = 107;
|
||||||
|
this.updownSplitContainer.SplitterWidth = 2;
|
||||||
|
this.updownSplitContainer.TabIndex = 8;
|
||||||
|
//
|
||||||
|
// inputLabel
|
||||||
|
//
|
||||||
|
this.inputLabel.AutoSize = true;
|
||||||
|
this.inputLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.inputLabel.Location = new System.Drawing.Point(3, 3);
|
||||||
|
this.inputLabel.Name = "inputLabel";
|
||||||
|
this.inputLabel.Size = new System.Drawing.Size(126, 13);
|
||||||
|
this.inputLabel.TabIndex = 9;
|
||||||
|
this.inputLabel.Text = "1) Select Input MP3s";
|
||||||
|
//
|
||||||
|
// inputPanel
|
||||||
|
//
|
||||||
|
this.inputPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.inputPanel.Controls.Add(this.clearButton);
|
||||||
|
this.inputPanel.Controls.Add(this.inputLabel);
|
||||||
|
this.inputPanel.Controls.Add(this.inputListBox);
|
||||||
|
this.inputPanel.Controls.Add(this.updownSplitContainer);
|
||||||
|
this.inputPanel.Controls.Add(this.addFolderButton);
|
||||||
|
this.inputPanel.Controls.Add(this.addFileButton);
|
||||||
|
this.inputPanel.Controls.Add(this.sortButton);
|
||||||
|
this.inputPanel.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.inputPanel.Name = "inputPanel";
|
||||||
|
this.inputPanel.Size = new System.Drawing.Size(584, 344);
|
||||||
|
this.inputPanel.TabIndex = 10;
|
||||||
|
//
|
||||||
|
// clearButton
|
||||||
|
//
|
||||||
|
this.clearButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.clearButton.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||||
|
this.clearButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.clearButton.Image = ((System.Drawing.Image)(resources.GetObject("clearButton.Image")));
|
||||||
|
this.clearButton.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.clearButton.Location = new System.Drawing.Point(491, 307);
|
||||||
|
this.clearButton.Name = "clearButton";
|
||||||
|
this.clearButton.Size = new System.Drawing.Size(66, 30);
|
||||||
|
this.clearButton.TabIndex = 10;
|
||||||
|
this.clearButton.Text = "Clear";
|
||||||
|
this.clearButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||||
|
this.clearButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// optionsPanel
|
||||||
|
//
|
||||||
|
this.optionsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.optionsPanel.Controls.Add(this.singleFileCheckBox);
|
||||||
|
this.optionsPanel.Controls.Add(this.outputDirectoryTextBox);
|
||||||
|
this.optionsPanel.Controls.Add(this.optionsLabel);
|
||||||
|
this.optionsPanel.Location = new System.Drawing.Point(12, 362);
|
||||||
|
this.optionsPanel.Name = "optionsPanel";
|
||||||
|
this.optionsPanel.Size = new System.Drawing.Size(584, 135);
|
||||||
|
this.optionsPanel.TabIndex = 11;
|
||||||
|
//
|
||||||
|
// singleFileCheckBox
|
||||||
|
//
|
||||||
|
this.singleFileCheckBox.AutoSize = true;
|
||||||
|
this.singleFileCheckBox.Location = new System.Drawing.Point(448, 12);
|
||||||
|
this.singleFileCheckBox.Name = "singleFileCheckBox";
|
||||||
|
this.singleFileCheckBox.Size = new System.Drawing.Size(109, 17);
|
||||||
|
this.singleFileCheckBox.TabIndex = 12;
|
||||||
|
this.singleFileCheckBox.Text = "Output Single File";
|
||||||
|
this.singleFileCheckBox.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// outputDirectoryTextBox
|
||||||
|
//
|
||||||
|
this.outputDirectoryTextBox.Location = new System.Drawing.Point(8, 112);
|
||||||
|
this.outputDirectoryTextBox.Name = "outputDirectoryTextBox";
|
||||||
|
this.outputDirectoryTextBox.Size = new System.Drawing.Size(100, 20);
|
||||||
|
this.outputDirectoryTextBox.TabIndex = 11;
|
||||||
|
//
|
||||||
|
// optionsLabel
|
||||||
|
//
|
||||||
|
this.optionsLabel.AutoSize = true;
|
||||||
|
this.optionsLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.optionsLabel.Location = new System.Drawing.Point(3, 0);
|
||||||
|
this.optionsLabel.Name = "optionsLabel";
|
||||||
|
this.optionsLabel.Size = new System.Drawing.Size(105, 13);
|
||||||
|
this.optionsLabel.TabIndex = 10;
|
||||||
|
this.optionsLabel.Text = "2) Select Options";
|
||||||
|
//
|
||||||
|
// savePanel
|
||||||
|
//
|
||||||
|
this.savePanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.savePanel.Controls.Add(this.saveLabel);
|
||||||
|
this.savePanel.Location = new System.Drawing.Point(12, 503);
|
||||||
|
this.savePanel.Name = "savePanel";
|
||||||
|
this.savePanel.Size = new System.Drawing.Size(584, 93);
|
||||||
|
this.savePanel.TabIndex = 12;
|
||||||
|
//
|
||||||
|
// saveLabel
|
||||||
|
//
|
||||||
|
this.saveLabel.AutoSize = true;
|
||||||
|
this.saveLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.saveLabel.Location = new System.Drawing.Point(3, 0);
|
||||||
|
this.saveLabel.Name = "saveLabel";
|
||||||
|
this.saveLabel.Size = new System.Drawing.Size(79, 13);
|
||||||
|
this.saveLabel.TabIndex = 10;
|
||||||
|
this.saveLabel.Text = "3) Save AAC";
|
||||||
|
//
|
||||||
|
// Mp3ToAacBatch
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(608, 608);
|
||||||
|
this.Controls.Add(this.savePanel);
|
||||||
|
this.Controls.Add(this.optionsPanel);
|
||||||
|
this.Controls.Add(this.inputPanel);
|
||||||
|
this.Name = "Mp3ToAacBatch";
|
||||||
|
this.Text = "Mp3 To AAC Batch";
|
||||||
|
this.updownSplitContainer.Panel1.ResumeLayout(false);
|
||||||
|
this.updownSplitContainer.Panel2.ResumeLayout(false);
|
||||||
|
this.updownSplitContainer.ResumeLayout(false);
|
||||||
|
this.inputPanel.ResumeLayout(false);
|
||||||
|
this.inputPanel.PerformLayout();
|
||||||
|
this.optionsPanel.ResumeLayout(false);
|
||||||
|
this.optionsPanel.PerformLayout();
|
||||||
|
this.savePanel.ResumeLayout(false);
|
||||||
|
this.savePanel.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ListBox inputListBox;
|
||||||
|
private System.Windows.Forms.Button addFolderButton;
|
||||||
|
private System.Windows.Forms.Button addFileButton;
|
||||||
|
private System.Windows.Forms.Button moveUpButton;
|
||||||
|
private System.Windows.Forms.Button moveDownButton;
|
||||||
|
private System.Windows.Forms.Button sortButton;
|
||||||
|
private System.Windows.Forms.SplitContainer updownSplitContainer;
|
||||||
|
private System.Windows.Forms.Label inputLabel;
|
||||||
|
private System.Windows.Forms.Panel inputPanel;
|
||||||
|
private System.Windows.Forms.Panel optionsPanel;
|
||||||
|
private System.Windows.Forms.Label optionsLabel;
|
||||||
|
private System.Windows.Forms.Button clearButton;
|
||||||
|
private System.Windows.Forms.Panel savePanel;
|
||||||
|
private System.Windows.Forms.Label saveLabel;
|
||||||
|
private System.Windows.Forms.TextBox outputDirectoryTextBox;
|
||||||
|
private System.Windows.Forms.CheckBox singleFileCheckBox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public partial class Mp3ToAacBatch : Form
|
||||||
|
{
|
||||||
|
public Mp3ToAacBatch()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
<data name="addFolderButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAO9JREFUOE9jYKAW
|
||||||
|
OLdI8T8yJslckEZ0cGyWxH+iDAEphIA5aPj/f5AcNoxiMNiAz0DNn3swMYa7IIbOrZJEuA5swOuW/48O
|
||||||
|
+uO0EZsrlhbxQAwBG3C9Baz51v5shJ2/v2OxHyj0vAUsjmLA36v5YAO+f+jEEhZoYXM86v/vn9NQDXi0
|
||||||
|
2en/yQUKIHP///8+BS9+vi/o/7k90agGnF+k+v/6DnuI7cDwwImBzn+/ywmhGRYGx2ZJ/v/wpBJiwONq
|
||||||
|
3Ph+9f97m7AYcHyONETzdWAgEsD7Z2qgugDkigPTJP4Ti+dU4kihIAliMFHJm66KAORP5xRdT7ByAAAA
|
||||||
|
AElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="addFileButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAiJJREFUOE+Nk+1L
|
||||||
|
U1Ecx/WP6v1e9d53azYqIogixAcoR2+UjErQIFjSWgZbLJnkbPMur+7pzm3OPXhRvDp0TndxbKV7cLt7
|
||||||
|
cGtf77ntgrVLdeBwD4f7+Xx/P845vT2dEYwdQl7/7buePusZ6rvW2/WPcymEP0e7DTRbP1FvtiA0WqBj
|
||||||
|
x5haiEjzn4K2SMfjSRgM8zjiczivNfHMuY/rln30vXB0S65WQGCS7PWxePJ4Enduj8Hl20OuUEYyVwLl
|
||||||
|
4qDT6X6vQhbIcP2iBbd3Ax+MFEZHLRgZmcUqwyJTrIn7HDQaTbeAwBekZxGu1JvgEjzs9k3M26LQ3nyK
|
||||||
|
twYr+HwVzBoHtVrdLbgKl6pNFIQGlukd+EK70L+bg83px9GpAH9gR1lQ6yRLcKWBH+UGnMuboD1x7PGn
|
||||||
|
EnzwvQKff1tZQMomcL4DZ0s1LFIBfPq8glQHTmTL8DBbygIZTqTyoFcTMJkCeHB/AtPTFimZwFymDJeX
|
||||||
|
VRbIyeFIGsWiAMZ/gMGB5xgefAlKPFIuc47tkxJod1xZQHpmuSysVgbhcBJmswe3tMOYfGXCV3dMglm+
|
||||||
|
iG+uqLKA9BzZ4qHtH8K9uzr03xjAo4fjmJlZhJc9lODocQHUyoay4KRQRfpMwNTrOYyPGWB8vwS9/gvM
|
||||||
|
Ni/Y9C84nCrAQYeVBaH1BNaCu2DEc/4464DRsAA7FZR6JmWTZAK/Ed9H10Uir4tsqlSq/5qy4BL8gXM2
|
||||||
|
KgxAeQAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="sortButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAOJJREFUOE+9UrkN
|
||||||
|
wzAM9Cbps4SnYO1RNIq7FFwirlOnzBDeQLkTSUOGAkhJEQOEbIP38Khp+seja863x56plZJm1le6umom
|
||||||
|
iYFxLoMEzzuaAVScRmAlIBhywiYCCxggWeQAk+R6kf4oRQkEMlvz9tpAYi5OOYRSHZRZNrsEMIt45/eJ
|
||||||
|
xAhiNlMoBeXkija7Z8AR6IrrUfws5xEUGj0ocfUgk9mB4T/5imJNEVQ4YFC1XfY388d+iyUPKmx3L8zn
|
||||||
|
oKoMepfGZkNVszZBdW2ggSQMjmM0QQ0RVHvlOpugRkh+6XkD9f86XlAO9kEAAAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="clearButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAh1JREFUOE+Vk1tP
|
||||||
|
E1EUhaeY8L+M/6WPPpgYYzTG6INEEo0aQBo00ShBjRhTi1UsUFqx1SLQG/RGL1AK0wu92jJnziz3Hm0k
|
||||||
|
meHBSU5mkplvrW+fyXEof687r7IYPp++O0ZGFH0wUM6Njip5313F5XI57L5TOIAvYQADAfQ0A62BgcYv
|
||||||
|
A7WOBL+/4lbhdDpti8wAIYE+wd0TgvsG6j0DVYIrLYkLs31znX9YsA/hgL4GdKi1ya1dA0dtAwcEl44l
|
||||||
|
IgmY67W7hxtjbmsIB7RZmVprXYnDtkS5SXBDYrcmkVYldg51xA90fA537QPqPQm1Y6BC8D61FutDWMc2
|
||||||
|
wTGCN/d1+NY79gEqzcvKewTnCc5WdaSOJJIViVhZxwbBP4pkEDkjoNw0UCTlPClnqqRMcIJatwj+uSfw
|
||||||
|
neBveYGP4bbV4PbzBAoE5xhW/ylvUet6iWGBNYIDOQFPyCbg5swGcqTMm5Ws/JmXlSMlHeECwbsCq1mB
|
||||||
|
5YyG919bVoPrEyFzl1k5airzvAIhgoME+7MallICizsa3gWa1oCr91cRp2ZWZng4b5BaVzICX9IaPm0L
|
||||||
|
LCQE3vhtAi6PLVqUA6ycJpiavUkNngTpxzTMLR9bDS7d8pi/aKjM8y5RKyt7qflDnODoCeY3Nbz0NawB
|
||||||
|
F6/N48nbFFxzSTyejWHqRRTTzyKYehrG5MwaJqaDeDTpx/iDBYzf89qfBz5p/7P4WP8G/jqMg6Vn2nUA
|
||||||
|
AAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class Mp4Encoder : ProcessStreamWrapper
|
||||||
|
{
|
||||||
|
public Mp4Encoder(Mp4EncodingOptions encOpt) : base(encOpt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mp4Encoder(Mp4EncodingOptions encOpt, Stream outputStream)
|
||||||
|
: base(encOpt, outputStream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ProcessExecutableFilename
|
||||||
|
{
|
||||||
|
get { return "faac.exe"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,515 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///FAAC 1.24.1 (May 17 2005) UNSTABLE
|
||||||
|
///
|
||||||
|
///Usage: faac [options] infiles ...
|
||||||
|
///Options:
|
||||||
|
/// -q <quality> Set quantizer quality.
|
||||||
|
/// -b <bitrate> Set average bitrate to x kbps. (ABR, lower quality mode)
|
||||||
|
/// -c <freq> Set the bandwidth in Hz. (default=automatic)
|
||||||
|
/// -o X Set output file to X (only for one input file)
|
||||||
|
/// -r Use RAW AAC output file.
|
||||||
|
/// -P Raw PCM input mode (default 44100Hz 16bit stereo).
|
||||||
|
/// -R Raw PCM input rate.
|
||||||
|
/// -B Raw PCM input sample size (8, 16 (default), 24 or 32bits).
|
||||||
|
/// -C Raw PCM input channels.
|
||||||
|
/// -X Raw PCM swap input bytes
|
||||||
|
/// -I <C,LF> Input channel config, default is 3,4 (Center third, LF fourth)
|
||||||
|
///
|
||||||
|
///MP4 specific options:
|
||||||
|
/// -w Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a)
|
||||||
|
/// --artist X Set artist to X
|
||||||
|
/// --writer X Set writer to X
|
||||||
|
/// --title X Set title to X
|
||||||
|
/// --genre X Set genre to X
|
||||||
|
/// --album X Set album to X
|
||||||
|
/// --compilation Set compilation
|
||||||
|
/// --track X Set track to X (number/total)
|
||||||
|
/// --disc X Set disc to X (number/total)
|
||||||
|
/// --year X Set year to X
|
||||||
|
/// --cover-art X Read cover art from file X
|
||||||
|
/// --comment X Set comment to X
|
||||||
|
/// </summary>
|
||||||
|
public class Mp4EncodingOptions : ProcessArguments
|
||||||
|
{
|
||||||
|
#region Private variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set album to X --album X
|
||||||
|
/// </summary>
|
||||||
|
private string mAlbum;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set artist to X --artist X
|
||||||
|
/// </summary>
|
||||||
|
private string mArtist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bandwidth in Hz -c [freq]
|
||||||
|
/// </summary>
|
||||||
|
private SampleRateFrequency mBandwidth = SampleRateFrequency.Hz_0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// BitRate -b [bitrate]
|
||||||
|
/// </summary>
|
||||||
|
private int mBitrate = int.MinValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set comment to X --comment X
|
||||||
|
/// </summary>
|
||||||
|
private string mComment;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set compilation --compilation
|
||||||
|
/// </summary>
|
||||||
|
private string mCompilation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load cover art from filename --cover-art X
|
||||||
|
/// </summary>
|
||||||
|
private string mCoverArtFilename;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set disc to X (number/total) --disc X
|
||||||
|
/// </summary>
|
||||||
|
private string mDisc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set genre to X --genre X
|
||||||
|
/// </summary>
|
||||||
|
private string mGenre;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Files to use for input
|
||||||
|
/// </summary>
|
||||||
|
private string[] mInfiles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output filename (only for one input file) -o [filename]
|
||||||
|
/// </summary>
|
||||||
|
private string mOutputFilename;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Quantinizer Quality -q [quality]
|
||||||
|
/// </summary>
|
||||||
|
private int mQuantinizerQuality = int.MinValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input channels -C
|
||||||
|
/// </summary>
|
||||||
|
private ChannelMode mRawInputChannels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input mode (default 44100Hz 16bit stereo) -P
|
||||||
|
/// </summary>
|
||||||
|
private bool mRawPCMInputMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input rate (default 16) -B
|
||||||
|
/// </summary>
|
||||||
|
private int mRawPCMInputSampleRate = 16;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCMInputSampleSize (default 44100Hz 16bit stereo) -R
|
||||||
|
/// </summary>
|
||||||
|
private SampleRateFrequency mRawPCMInputSampleSize = SampleRateFrequency.Hz_44100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM swap input bytes -X
|
||||||
|
/// </summary>
|
||||||
|
private bool mRawPCMSwapInputBytes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set title to X --title X
|
||||||
|
/// </summary>
|
||||||
|
private string mTitle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set track to X (number/total) --track X
|
||||||
|
/// </summary>
|
||||||
|
private string mTrack;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a) -w
|
||||||
|
/// </summary>
|
||||||
|
private bool mWrapAACDataInMp4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set writer to X --writer X
|
||||||
|
/// </summary>
|
||||||
|
private string mWriter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set year to X --year X
|
||||||
|
/// </summary>
|
||||||
|
private int mYear = int.MinValue;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the input files.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The input files.</value>
|
||||||
|
public string[] InputFiles
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mInfiles == null)
|
||||||
|
return new string[] {};
|
||||||
|
return mInfiles;
|
||||||
|
}
|
||||||
|
set { mInfiles = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Quantinizer Quality -q [quality]
|
||||||
|
/// </summary>
|
||||||
|
public int QuantinizerQuality
|
||||||
|
{
|
||||||
|
get { return mQuantinizerQuality; }
|
||||||
|
set { mQuantinizerQuality = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// BitRate -b [bitrate]
|
||||||
|
/// </summary>
|
||||||
|
public int Bitrate
|
||||||
|
{
|
||||||
|
get { return mBitrate; }
|
||||||
|
set { mBitrate = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bandwidth in Hz -c [freq]
|
||||||
|
/// </summary>
|
||||||
|
public SampleRateFrequency Bandwidth
|
||||||
|
{
|
||||||
|
get { return mBandwidth; }
|
||||||
|
set { mBandwidth = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output filename (only for one input file) -o [filename]
|
||||||
|
/// </summary>
|
||||||
|
public string OutputFilename
|
||||||
|
{
|
||||||
|
get { return mOutputFilename; }
|
||||||
|
set { mOutputFilename = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use RAW AAC output file -r
|
||||||
|
/// </summary>
|
||||||
|
public bool RawAACOutputFile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input mode (default 44100Hz 16bit stereo) -P
|
||||||
|
/// </summary>
|
||||||
|
public bool RawPCMInputMode
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputMode; }
|
||||||
|
set { mRawPCMInputMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCMInputSampleSize -R
|
||||||
|
/// </summary>
|
||||||
|
public SampleRateFrequency RawPCMInputSampleSize
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleSize; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleSize = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input rate (default 16) -B
|
||||||
|
/// </summary>
|
||||||
|
public int RawPCMInputSampleRate
|
||||||
|
{
|
||||||
|
get { return mRawPCMInputSampleRate; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMInputSampleRate = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM input channels -C
|
||||||
|
/// </summary>
|
||||||
|
public ChannelMode RawInputChannels
|
||||||
|
{
|
||||||
|
get { return mRawInputChannels; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawInputChannels = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw PCM swap input bytes -X
|
||||||
|
/// </summary>
|
||||||
|
public bool RawPCMSwapInputBytes
|
||||||
|
{
|
||||||
|
get { return mRawPCMSwapInputBytes; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mRawPCMSwapInputBytes = value;
|
||||||
|
RawPCMInputMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrap AAC data in MP4 container. (default for *.mp4 and *.m4a)
|
||||||
|
/// </summary>
|
||||||
|
public bool WrapAACDataInMp4
|
||||||
|
{
|
||||||
|
get { return mWrapAACDataInMp4; }
|
||||||
|
set { mWrapAACDataInMp4 = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set artist to X
|
||||||
|
/// </summary>
|
||||||
|
public string Artist
|
||||||
|
{
|
||||||
|
get { return mArtist; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mArtist = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set writer to X
|
||||||
|
/// </summary>
|
||||||
|
public string Writer
|
||||||
|
{
|
||||||
|
get { return mWriter; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mWriter = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set title to X
|
||||||
|
/// </summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get { return mTitle; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mTitle = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set genre to X
|
||||||
|
/// </summary>
|
||||||
|
public string Genre
|
||||||
|
{
|
||||||
|
get { return mGenre; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mGenre = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set album to X
|
||||||
|
/// </summary>
|
||||||
|
public string Album
|
||||||
|
{
|
||||||
|
get { return mAlbum; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mAlbum = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set compilation
|
||||||
|
/// </summary>
|
||||||
|
public string Compilation
|
||||||
|
{
|
||||||
|
get { return mCompilation; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mCompilation = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set track to X (number/total)
|
||||||
|
/// </summary>
|
||||||
|
public string Track
|
||||||
|
{
|
||||||
|
get { return mTrack; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mTrack = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set disc to X (number/total)
|
||||||
|
/// </summary>
|
||||||
|
public string Disc
|
||||||
|
{
|
||||||
|
get { return mDisc; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mDisc = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set year to X
|
||||||
|
/// </summary>
|
||||||
|
public int Year
|
||||||
|
{
|
||||||
|
get { return mYear; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mYear = value;
|
||||||
|
if (value != int.MinValue)
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load cover art from filename
|
||||||
|
/// </summary>
|
||||||
|
public string CoverArtFilename
|
||||||
|
{
|
||||||
|
get { return mCoverArtFilename; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mCoverArtFilename = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Quantinizer Quality -q [quality]
|
||||||
|
/// </summary>
|
||||||
|
public string Comment
|
||||||
|
{
|
||||||
|
get { return mComment; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mComment = value;
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
WrapAACDataInMp4 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representing the command line arguments specified by the properties in the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override string GetCommandLineArguments()
|
||||||
|
{
|
||||||
|
var stringBuilder = new StringBuilder();
|
||||||
|
if (mQuantinizerQuality != int.MinValue)
|
||||||
|
stringBuilder.Append(" -q " + mQuantinizerQuality);
|
||||||
|
if (mBitrate != int.MinValue)
|
||||||
|
stringBuilder.Append(" -b " + mBitrate);
|
||||||
|
if (mBandwidth != SampleRateFrequency.Hz_0)
|
||||||
|
stringBuilder.Append(" -c " + SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mBandwidth));
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(mOutputFilename))
|
||||||
|
{
|
||||||
|
if (mOutputFilename.Trim() == "-")
|
||||||
|
stringBuilder.Append(" -o-");
|
||||||
|
else
|
||||||
|
stringBuilder.Append(" -o " + GetQuotedCommandLineArgument(mOutputFilename));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stringBuilder.Append(" -o-");
|
||||||
|
|
||||||
|
if (mRawPCMInputMode)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" -P ");
|
||||||
|
if (mRawPCMInputSampleSize != SampleRateFrequency.Hz_44100)
|
||||||
|
stringBuilder.Append(" -R " +
|
||||||
|
SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mRawPCMInputSampleSize));
|
||||||
|
if (mRawPCMInputSampleRate != 16)
|
||||||
|
stringBuilder.Append(" -B " + mRawPCMInputSampleRate);
|
||||||
|
int chanelMode = ChannelModeUtility.GetChannelModeInt(mRawInputChannels);
|
||||||
|
if (chanelMode != 2)
|
||||||
|
stringBuilder.Append(" -C " + chanelMode);
|
||||||
|
if (mRawPCMSwapInputBytes)
|
||||||
|
stringBuilder.Append(" -X ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mWrapAACDataInMp4)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(" -w ");
|
||||||
|
if (!string.IsNullOrEmpty(mArtist))
|
||||||
|
stringBuilder.Append(" --artist " + mArtist);
|
||||||
|
if (!string.IsNullOrEmpty(mWriter))
|
||||||
|
stringBuilder.Append(" --writer " + mWriter);
|
||||||
|
if (!string.IsNullOrEmpty(mTitle))
|
||||||
|
stringBuilder.Append(" --title " + mTitle);
|
||||||
|
if (!string.IsNullOrEmpty(mGenre))
|
||||||
|
stringBuilder.Append(" --genre " + mGenre);
|
||||||
|
if (!string.IsNullOrEmpty(mAlbum))
|
||||||
|
stringBuilder.Append(" --album " + mAlbum);
|
||||||
|
if (!string.IsNullOrEmpty(mCompilation))
|
||||||
|
stringBuilder.Append(" --compilation " + mCompilation);
|
||||||
|
if (!string.IsNullOrEmpty(mTrack))
|
||||||
|
stringBuilder.Append(" --track " + mTrack);
|
||||||
|
if (!string.IsNullOrEmpty(mDisc))
|
||||||
|
stringBuilder.Append(" --disc " + mDisc);
|
||||||
|
if (mYear != int.MinValue)
|
||||||
|
stringBuilder.Append(" --year " + mYear);
|
||||||
|
if (!string.IsNullOrEmpty(mCoverArtFilename))
|
||||||
|
stringBuilder.Append(" --cover-art " + mCoverArtFilename);
|
||||||
|
if (!string.IsNullOrEmpty(mComment))
|
||||||
|
stringBuilder.Append(" --comment " + mComment);
|
||||||
|
}
|
||||||
|
if (mInfiles != null && mInfiles.Length > 0)
|
||||||
|
{
|
||||||
|
// use standard input
|
||||||
|
if (mInfiles[0].Trim() == "-")
|
||||||
|
stringBuilder.Append(" -");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (string infile in mInfiles)
|
||||||
|
stringBuilder.Append(" " + GetQuotedCommandLineArgument(infile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stringBuilder.Append(" -");
|
||||||
|
|
||||||
|
|
||||||
|
return stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
public class ProcessArguments
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representing the command line arguments specified by the properties in the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual string GetCommandLineArguments()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string GetQuotedCommandLineArgument(string argument)
|
||||||
|
{
|
||||||
|
if (argument.Contains(" ") || argument.Contains("\t"))
|
||||||
|
{
|
||||||
|
return "\"" + argument + "\"";
|
||||||
|
}
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,361 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A generic encoder. Creates an external process, sends it argument options,
|
||||||
|
/// and acts as a wrapper for streaming reads and writes
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ProcessStreamWrapper : IDisposable
|
||||||
|
{
|
||||||
|
#region Protected Variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much data to buffer when reading and writing
|
||||||
|
/// </summary>
|
||||||
|
protected const int mBufferLength = 1000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output stream writer. If it is null, it is assumed
|
||||||
|
/// that the process will take care of output itself.
|
||||||
|
/// </summary>
|
||||||
|
protected StreamWriter mOutputStreamWriter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The process
|
||||||
|
/// </summary>
|
||||||
|
protected Process mProcess;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The arguments to use for the process
|
||||||
|
/// </summary>
|
||||||
|
protected ProcessArguments mProcessArguments;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Progress call-back, for status updates outside this class.
|
||||||
|
/// </summary>
|
||||||
|
protected IProgressCallback mProgressCallback = new DoNothingProgressCallback();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the progress callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The progress callback.</value>
|
||||||
|
public IProgressCallback ProgressCallback
|
||||||
|
{
|
||||||
|
get { return mProgressCallback; }
|
||||||
|
set { mProgressCallback = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the process executable filename, such as "LAME.EXE", "FAAC.EXE", etc.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The process executable filename.</value>
|
||||||
|
protected abstract string ProcessExecutableFilename { get; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ProcessStreamWrapper"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encOpt">The enc opt.</param>
|
||||||
|
public ProcessStreamWrapper(ProcessArguments encOpt) : this(encOpt, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ProcessStreamWrapper"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encOpt">The enc opt.</param>
|
||||||
|
/// <param name="outputStream">Output to this stream</param>
|
||||||
|
public ProcessStreamWrapper(ProcessArguments encOpt, Stream outputStream)
|
||||||
|
{
|
||||||
|
mProcessArguments = encOpt;
|
||||||
|
|
||||||
|
mProcess = CreateProcess(mProcessArguments, ProcessExecutableFilename);
|
||||||
|
if (outputStream != null)
|
||||||
|
{
|
||||||
|
mOutputStreamWriter = new StreamWriter(outputStream, Encoding.Default);
|
||||||
|
mProcess.StartInfo.RedirectStandardOutput = true;
|
||||||
|
mProcess.StartInfo.StandardOutputEncoding = Encoding.Default;
|
||||||
|
}
|
||||||
|
mProcess.StartInfo.RedirectStandardError = true;
|
||||||
|
|
||||||
|
mProcess.Exited += Process_Exited;
|
||||||
|
mProcess.Start();
|
||||||
|
if (mOutputStreamWriter != null)
|
||||||
|
{
|
||||||
|
var thread = new Thread(GetStandardOutput);
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
var standardErrorThread = new Thread(GetStandardError);
|
||||||
|
standardErrorThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Static methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a process given an executable and some process arguments
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="processArguments">The enc opt.</param>
|
||||||
|
/// <param name="executable">The executable filename.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static Process CreateProcess(ProcessArguments processArguments, string executable)
|
||||||
|
{
|
||||||
|
var process = new Process();
|
||||||
|
process.StartInfo.RedirectStandardInput = true;
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.FileName = executable;
|
||||||
|
process.StartInfo.Arguments = processArguments.GetCommandLineArguments();
|
||||||
|
process.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
|
||||||
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
|
||||||
|
process.EnableRaisingEvents = true;
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event handlers
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the Exited event of the Process.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The source of the event.</param>
|
||||||
|
/// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
|
||||||
|
private void Process_Exited(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText("Process_Exited");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Utility methods
|
||||||
|
|
||||||
|
private static int GetPercentDone(long previousLeft, long currentLeft, long currentDone, int lastDone)
|
||||||
|
{
|
||||||
|
// if currentLeft > previousLeft - lastDone,
|
||||||
|
// addedLeft = previousLeft - lastDone - currentLeft
|
||||||
|
// totalLength = previousLeft + currentDone + addedLeft
|
||||||
|
|
||||||
|
long totalLength = currentLeft;
|
||||||
|
if (currentLeft != previousLeft)
|
||||||
|
{
|
||||||
|
long leftDelta = previousLeft - lastDone - currentLeft;
|
||||||
|
totalLength = previousLeft + currentDone + leftDelta;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Convert.ToInt32((currentDone/(double) totalLength)*100);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the data to the underlying process through its input stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The data to encode</param>
|
||||||
|
/// <param name="count">How many characters to write</param>
|
||||||
|
/// <param name="startIndex">The index to begin writing from</param>
|
||||||
|
public void ProcessInput(char[] buffer, int startIndex, int count)
|
||||||
|
{
|
||||||
|
mProcess.StandardInput.Write(buffer, startIndex, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the data from the input stream to the process
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputStream"></param>
|
||||||
|
public void ProcessInput(Stream inputStream)
|
||||||
|
{
|
||||||
|
if (!inputStream.CanRead)
|
||||||
|
throw new ArgumentException("Can't read from inputStream");
|
||||||
|
|
||||||
|
mProgressCallback.SetText("ProcessInput: StreamReader sr");
|
||||||
|
|
||||||
|
long inputCount = inputStream.Length;
|
||||||
|
long previousInputCount = inputStream.Length;
|
||||||
|
long wroteCount = 0;
|
||||||
|
int percentageComplete = 0;
|
||||||
|
|
||||||
|
var sr = new StreamReader(inputStream, Encoding.Default);
|
||||||
|
//using (StreamReader sr = new StreamReader(inputStream, Encoding.Default))
|
||||||
|
{
|
||||||
|
mProgressCallback.Begin(0, 100);
|
||||||
|
mProgressCallback.SetText(mProcessArguments.GetCommandLineArguments());
|
||||||
|
|
||||||
|
var buffer = new char[mBufferLength];
|
||||||
|
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
int readLength = sr.Read(buffer, 0, mBufferLength);
|
||||||
|
ProcessInput(buffer, 0, readLength);
|
||||||
|
|
||||||
|
// update progress
|
||||||
|
wroteCount += readLength;
|
||||||
|
previousInputCount = inputCount;
|
||||||
|
inputCount = inputStream.Length;
|
||||||
|
int currentPercentageComplete = GetPercentDone(previousInputCount, inputCount, wroteCount,
|
||||||
|
readLength);
|
||||||
|
if (currentPercentageComplete != percentageComplete)
|
||||||
|
{
|
||||||
|
percentageComplete = currentPercentageComplete;
|
||||||
|
mProgressCallback.StepTo(percentageComplete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mInputDone = true;
|
||||||
|
mProgressCallback.SetText("ProcessInput: Done. " + String.Format("Wrote: {0}", wroteCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open this file and encode it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename"></param>
|
||||||
|
public void ProcessInput(string filename)
|
||||||
|
{
|
||||||
|
using (FileStream inputStream = File.OpenRead(filename))
|
||||||
|
{
|
||||||
|
ProcessInput(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Threaded methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TEMP: this should be removed once GetStandardOutput is working
|
||||||
|
/// </summary>
|
||||||
|
private bool mInputDone;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collects all the data from Process.StandardOutput and sends it to the outputstream writer
|
||||||
|
/// </summary>
|
||||||
|
private void GetStandardOutput()
|
||||||
|
{
|
||||||
|
int readTotal = 0;
|
||||||
|
var writeBuffer = new char[mBufferLength];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!mProcess.StandardOutput.EndOfStream)
|
||||||
|
//while (mProcess.StandardOutput.Peek() > -1)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText("- Before read");
|
||||||
|
int readLength = mProcess.StandardOutput.Read(writeBuffer, 0, writeBuffer.Length);
|
||||||
|
mProgressCallback.SetText("- After read: " + readLength);
|
||||||
|
mOutputStreamWriter.Write(writeBuffer, 0, readLength);
|
||||||
|
if (mInputDone)
|
||||||
|
mProgressCallback.SetText(" StandardOutput: " + new string(writeBuffer, 0, readLength));
|
||||||
|
readTotal += readLength;
|
||||||
|
mProgressCallback.SetText("Read total = " + readTotal);
|
||||||
|
|
||||||
|
//mProcess.StandardInput.Flush();
|
||||||
|
//mProcess.StandardOutput.BaseStream.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText(ex.ToString());
|
||||||
|
}
|
||||||
|
// mOutputStreamWriter.Flush();
|
||||||
|
mProgressCallback.SetText("GetStandardOutput() " + "Done!" + " StandardOutput.EndOfStream = " +
|
||||||
|
mProcess.StandardOutput.EndOfStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Asynchronous implementation of GetStandardOutput
|
||||||
|
//int mReadTotal = 0;
|
||||||
|
//private byte[] mBuffer = new byte[mBufferLength];
|
||||||
|
//private void GetStandardOutputAsync()
|
||||||
|
//{
|
||||||
|
// mProcess.StandardOutput.BaseStream.BeginRead(mBuffer, 0, mBufferLength, GetStandardOutputCallback, 0);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private void GetStandardOutputCallback(IAsyncResult asyncResult)
|
||||||
|
//{
|
||||||
|
// mProgressCallback.SetText("- Before read:");
|
||||||
|
// int readLength = mProcess.StandardOutput.BaseStream.EndRead(asyncResult);
|
||||||
|
// mProgressCallback.SetText("- After read:" + readLength);
|
||||||
|
// mOutputStreamWriter.BaseStream.Write(mBuffer, 0, readLength);
|
||||||
|
// mReadTotal += readLength;
|
||||||
|
// mProgressCallback.SetText("Read total = " + mReadTotal);
|
||||||
|
// mProcess.StandardOutput.BaseStream.BeginRead(mBuffer, 0, mBufferLength, GetStandardOutputCallback, 0);
|
||||||
|
//}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collects all the data from Process.StandardError and sends it to the progress callback
|
||||||
|
/// </summary>
|
||||||
|
private void GetStandardError()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!mProcess.StandardError.EndOfStream)
|
||||||
|
{
|
||||||
|
string line = mProcess.StandardError.ReadLine();
|
||||||
|
mProgressCallback.SetText("GetStandardError() " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
mProgressCallback.SetText(ex.ToString());
|
||||||
|
}
|
||||||
|
mProgressCallback.SetText("GetStandardError() " + "Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
mProgressCallback.SetText("Dispose()");
|
||||||
|
while (mProcess != null && !mProcess.HasExited)
|
||||||
|
{
|
||||||
|
mProcess.WaitForExit(2);
|
||||||
|
if (count++ > mBufferLength && !mProcess.HasExited)
|
||||||
|
{
|
||||||
|
mProcess.Kill();
|
||||||
|
mProgressCallback.SetText("!!! Process.Kill()");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mProgressCallback.SetText("Writing EOF");
|
||||||
|
mProcess.StandardInput.Write(new string(new[] {(char) 0x1A, '\n'}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mProgressCallback.SetText("Dispose() with exit code " + mProcess.ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+63
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.1
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace m3uTool.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("m3uTool.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace m3uTool
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum Redirect
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Do not redirect anything
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Redirect standard input
|
||||||
|
/// </summary>
|
||||||
|
StandardInput = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Redirect standard output
|
||||||
|
/// </summary>
|
||||||
|
StandardOutput = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Redirect standart error
|
||||||
|
/// </summary>
|
||||||
|
StandardError = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 824 B |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,238 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Win32;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tests for the BridgeStream class.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class BridgeStreamTests
|
||||||
|
{
|
||||||
|
#region Private Variables
|
||||||
|
/// <summary>
|
||||||
|
/// Bridge stream object to use for multi-threaded read/write testing.
|
||||||
|
/// </summary>
|
||||||
|
private BridgeStream mBridgeStream;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The string read from a threaded read process.
|
||||||
|
/// </summary>
|
||||||
|
private string mReadString = "";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The total length of writes for a threaded writing process.
|
||||||
|
/// </summary>
|
||||||
|
private int mTotalWriteLength = -1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Some non-random text data to test with.
|
||||||
|
/// </summary>
|
||||||
|
private const string mTestString = @"BEOWOLF: THE AUTHOR AND HIS TIMES Who wrote Beowulf--the oldest known epic poem written in English--is a question that has mystified readers for centuries. It's generally thought that the poem was performed orally by the poet before a live audience, and that in this way it eventually passed down to readers and listeners. Another theory is that the poem was recited by memory by a scop, a traveling entertainer who went from court to court, singing songs and telling stories, until it was finally written down at the request of a king who wanted to hear it again. Because there are three major battle scenes in the poem, some readers believe that Beowulf was composed by three different authors. Other readers claim that the sections that take place in Denmark and the sections that occur after Beowulf returns to Geatland were the work of different authors. The majority of critics agree that because of the unified structure of the poem, with its interweaving of historical information into the flow of the main narrative, the poem was most likely composed by one person. As you read the poem try to imagine yourself in the banquet hall of a large castle, eating and drinking with your friends. The court entertainer--much like a stand-up comedian in a nightclub--begins telling his story. Your presence in the hall means that you're probably a member of the aristocratic class, either a descendant of the founder of a particular tribe or one of your king's followers. (Anglo-Saxon society was divided into two main classes: the aristocracy and the proletariat. Beowulf, as you'll see, gives us very little information about the life of the average person in Anglo-Saxon society, but concerns itself exclusively with life in the court and on the battlefield.) Most of the stories were written and recited during this time to entertain and instruct the members of the aristocratic class. The scop assumed that his audience was familiar with the stories of ancient times. It was his job to make them as interesting and as vivid as possible.";
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Tests
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void ReadWriteSingleThreadTests()
|
||||||
|
{
|
||||||
|
mBridgeStream = new BridgeStream();
|
||||||
|
WriteThread();
|
||||||
|
ReadThread();
|
||||||
|
Assert.AreEqual(mTestString, mReadString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests the BridgeStream by reading and writing in separate threads.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void ReadWriteMultiThreadTests()
|
||||||
|
{
|
||||||
|
mBridgeStream = new BridgeStream();
|
||||||
|
|
||||||
|
Thread readThread = new Thread(new ThreadStart(ReadThread));
|
||||||
|
Thread writeThread = new Thread(new ThreadStart(WriteThread));
|
||||||
|
readThread.Start();
|
||||||
|
writeThread.Start();
|
||||||
|
|
||||||
|
writeThread.Join();
|
||||||
|
readThread.Join();
|
||||||
|
Assert.AreEqual(mTestString, mReadString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests the BridgeStream by reading and writing in separate threads.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void ReadWriteWithSeveralStreamsMultiThreadTests()
|
||||||
|
{
|
||||||
|
// Test with block on
|
||||||
|
mBridgeStream = new BridgeStream();
|
||||||
|
mBridgeStream.MaxBufferLength = 1026;
|
||||||
|
mBridgeStream.BlockLastReadBuffer = true;
|
||||||
|
|
||||||
|
Thread readThread = new Thread(new ThreadStart(ReadThread));
|
||||||
|
Thread writeThread = new Thread(new ThreadStart(WriteWithSeveralStreamsThread));
|
||||||
|
readThread.Start();
|
||||||
|
writeThread.Start();
|
||||||
|
|
||||||
|
writeThread.Join();
|
||||||
|
readThread.Join();
|
||||||
|
Assert.AreEqual(mTotalWriteLength, mReadString.Length);
|
||||||
|
|
||||||
|
// Test with block off
|
||||||
|
mBridgeStream = new BridgeStream();
|
||||||
|
mBridgeStream.BlockLastReadBuffer = false;
|
||||||
|
|
||||||
|
readThread = new Thread(new ThreadStart(ReadThread));
|
||||||
|
writeThread = new Thread(new ThreadStart(WriteWithSeveralStreamsThread));
|
||||||
|
readThread.Start();
|
||||||
|
writeThread.Start();
|
||||||
|
|
||||||
|
writeThread.Join();
|
||||||
|
readThread.Join();
|
||||||
|
|
||||||
|
// this next method is non-deterministic - it may end up reading the entire buffer,
|
||||||
|
// but I wouldn't bet on it.
|
||||||
|
Debug.WriteLine(String.Format("mTotalWriteLength={0}, mReadString.Length={1}", mTotalWriteLength, mReadString.Length));
|
||||||
|
//Assert.AreNotEqual(mTotalWriteLength, mReadString.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Thread methods
|
||||||
|
/// <summary>
|
||||||
|
/// Read function for the multithread test
|
||||||
|
/// </summary>
|
||||||
|
private void ReadThread()
|
||||||
|
{
|
||||||
|
StreamReader sr = new StreamReader(mBridgeStream);
|
||||||
|
mReadString = ReadStringFromStreamReader(sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write function for the multithread test
|
||||||
|
/// </summary>
|
||||||
|
private void WriteThread()
|
||||||
|
{
|
||||||
|
using (StreamWriter sw = new StreamWriter(mBridgeStream))
|
||||||
|
{
|
||||||
|
WriteDataToStreamWriter(sw, mTestString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteWithSeveralStreamsThread()
|
||||||
|
{
|
||||||
|
mTotalWriteLength = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
using (StreamWriter sw = new StreamWriter(mBridgeStream))
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 20; j++ )
|
||||||
|
mTotalWriteLength += WriteDataToStreamWriter(sw, mTestString);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mBridgeStream.BlockLastReadBuffer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Read and Write Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the string from the passed in stream reader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sr">The stream reader.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string ReadStringFromStreamReader(StreamReader sr)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
char[] buffer = new char[80];
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
int readLength = sr.Read(buffer, 0, buffer.Length);
|
||||||
|
sb.Append(buffer, 0, readLength);
|
||||||
|
//Debug.WriteLine("Reading...");
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the string to stream writer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sw">The sw.</param>
|
||||||
|
/// <param name="str">The STR.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private int WriteDataToStreamWriter(StreamWriter sw, string str)
|
||||||
|
{
|
||||||
|
int writeSize = 127;
|
||||||
|
for (int i = 0; i < str.Length; i += writeSize)
|
||||||
|
{
|
||||||
|
// select a substring of characters from the input string
|
||||||
|
string substring = str.Substring(i, (i + writeSize < str.Length) ? writeSize : str.Length - i);
|
||||||
|
sw.Write(substring.ToCharArray(), 0, substring.Length);
|
||||||
|
}
|
||||||
|
return str.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Time Trial Testing
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// <summary>
|
||||||
|
/// Compare the length of time to use BridgeStream vs MemoryStream.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TimeComparisonTest()
|
||||||
|
{
|
||||||
|
int iterations = 11024;
|
||||||
|
int arraySize = 11024;
|
||||||
|
byte[] bytes = new byte[arraySize];
|
||||||
|
byte[] readBytes = new byte[arraySize];
|
||||||
|
|
||||||
|
HiPerfTimer h = new HiPerfTimer();
|
||||||
|
|
||||||
|
h.Start();
|
||||||
|
BridgeStream bs = new BridgeStream();
|
||||||
|
for (int i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
bs.Write(bytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
bs.Read(readBytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
h.Stop();
|
||||||
|
Debug.WriteLine(h.Duration);
|
||||||
|
|
||||||
|
h = new HiPerfTimer();
|
||||||
|
h.Start();
|
||||||
|
Stream s = new MemoryStream();
|
||||||
|
for (int i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
s.Write(bytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
s.Read(readBytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
h.Stop();
|
||||||
|
Debug.WriteLine(h.Duration);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for CreateM3uTest.
|
||||||
|
/// </summary>
|
||||||
|
public class CreateM3uTests
|
||||||
|
{
|
||||||
|
public void CreateM3uTest()
|
||||||
|
{
|
||||||
|
var c = new M3uCreate(new DirectoryInfo(@"C:\mp3\"));
|
||||||
|
// c.OutputFilename = @"c:\mym3u.m3u";
|
||||||
|
Debug.WriteLine(c.OutputFilename);
|
||||||
|
c.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateSubM3uTest()
|
||||||
|
{
|
||||||
|
var rootDir = new DirectoryInfo(@"C:\mp3\");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
foreach (DirectoryInfo subDir in rootDir.GetDirectories())
|
||||||
|
{
|
||||||
|
var c = new M3uCreate(subDir);
|
||||||
|
|
||||||
|
Debug.WriteLine(c.OutputFilename);
|
||||||
|
c.Create();
|
||||||
|
|
||||||
|
if (count++ > 10)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// c.OutputFilename = @"c:\mym3u.m3u";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,55 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Win32
|
||||||
|
{
|
||||||
|
internal class HiPerfTimer
|
||||||
|
{
|
||||||
|
private readonly long freq;
|
||||||
|
private long startTime, stopTime;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public HiPerfTimer()
|
||||||
|
{
|
||||||
|
startTime = 0;
|
||||||
|
stopTime = 0;
|
||||||
|
|
||||||
|
if (QueryPerformanceFrequency(out freq) == false)
|
||||||
|
{
|
||||||
|
// high-performance counter not supported
|
||||||
|
throw new Win32Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Duration
|
||||||
|
{
|
||||||
|
get { return (stopTime - startTime)/(double) freq; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
private static extern bool QueryPerformanceCounter(
|
||||||
|
out long lpPerformanceCount);
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
private static extern bool QueryPerformanceFrequency(
|
||||||
|
out long lpFrequency);
|
||||||
|
|
||||||
|
// Start the timer
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
// lets do the waiting threads there work
|
||||||
|
Thread.Sleep(0);
|
||||||
|
|
||||||
|
QueryPerformanceCounter(out startTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the timer
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
QueryPerformanceCounter(out stopTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the duration of the timer (in seconds)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class LongestCommonSequenceTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void FunctionalityTest()
|
||||||
|
{
|
||||||
|
List<string> substring = LongestCommonSubstrings.GetLongestSubstring("ABAB", "BABA");
|
||||||
|
Assert.AreEqual(2, substring.Count);
|
||||||
|
Assert.IsTrue(substring.Contains("ABA"));
|
||||||
|
Assert.IsTrue(substring.Contains("BAB"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using id3;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for MP3HeaderTests.
|
||||||
|
/// </summary>
|
||||||
|
public class MP3HeaderTests
|
||||||
|
{
|
||||||
|
private string mp3File1 = "001-22.mp3";
|
||||||
|
private string mp3File2 = "001-44.mp3";
|
||||||
|
|
||||||
|
public void MP3HeaderTest()
|
||||||
|
{
|
||||||
|
string mp3Filename = mp3File1;
|
||||||
|
MP3Header mp3hdr = new MP3Header();
|
||||||
|
bool boolIsMP3 = mp3hdr.ReadMP3Information(mp3Filename);
|
||||||
|
if(boolIsMP3)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(mp3hdr.strFileName);
|
||||||
|
Debug.WriteLine(mp3hdr.lngFileSize.ToString());
|
||||||
|
Debug.WriteLine(mp3hdr.intBitRate.ToString());
|
||||||
|
Debug.WriteLine(mp3hdr.intFrequency.ToString());
|
||||||
|
Debug.WriteLine(mp3hdr.strMode);
|
||||||
|
Debug.WriteLine(mp3hdr.strLengthFormatted);
|
||||||
|
Debug.WriteLine(mp3hdr.intLength.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInfo fFileInfo = new FileInfo(mp3Filename); // Creating this FileInfo so I don't have to change my generic class
|
||||||
|
MP3 mp3ID3 = new MP3(fFileInfo.DirectoryName, fFileInfo.Name); //fFile.DirectoryName, fFile.Name);
|
||||||
|
FileCommands.readMP3Tag(ref mp3ID3);
|
||||||
|
|
||||||
|
Debug.WriteLine(mp3ID3.id3Title);
|
||||||
|
Debug.WriteLine(mp3ID3.id3Artist);
|
||||||
|
Debug.WriteLine(mp3ID3.id3Album);
|
||||||
|
Debug.WriteLine(mp3ID3.id3TrackNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace m3uTool.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class Mp3EncoderTests : ProgressCallbackTestBase
|
||||||
|
{
|
||||||
|
private static void FilesAreEqual(FileInfo file1, FileInfo file2)
|
||||||
|
{
|
||||||
|
//Assert.AreEqual(file1.Length, file2.Length);
|
||||||
|
|
||||||
|
int filePosition = 0;
|
||||||
|
using (FileStream outputOptionFs = file1.OpenRead())
|
||||||
|
using (var outputOptionSr = new StreamReader(outputOptionFs))
|
||||||
|
using (FileStream streamingFs = file2.OpenRead())
|
||||||
|
using (var streamingSr = new StreamReader(streamingFs))
|
||||||
|
{
|
||||||
|
var outputOptionBuffer = new char[4096];
|
||||||
|
var streamingBuffer = new char[4096];
|
||||||
|
|
||||||
|
while (!outputOptionSr.EndOfStream)
|
||||||
|
{
|
||||||
|
int outputOptionReadLength = outputOptionSr.Read(outputOptionBuffer, 0, outputOptionBuffer.Length);
|
||||||
|
int streamingReadLength = streamingSr.Read(streamingBuffer, 0, streamingBuffer.Length);
|
||||||
|
|
||||||
|
Assert.AreEqual(outputOptionReadLength, streamingReadLength);
|
||||||
|
Assert.AreEqual(outputOptionBuffer, streamingBuffer, "offset : " + filePosition);
|
||||||
|
filePosition += outputOptionBuffer.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this method from the worker thread to increase the progress
|
||||||
|
/// counter by a specified value.
|
||||||
|
/// </summary>
|
||||||
|
public override void StepTo(int val)
|
||||||
|
{
|
||||||
|
if (val%10 == 0)
|
||||||
|
base.StepTo(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests this instance.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void StreamingTest()
|
||||||
|
{
|
||||||
|
String inputWav = "44_16_s.wav";
|
||||||
|
string encodedMp3 = "encodedMp3.mp3";
|
||||||
|
String decodedWav = "decodedWav.wav";
|
||||||
|
String reencodedMp3 = "reencodedMp3.mp3";
|
||||||
|
|
||||||
|
using (var fileStream = new FileStream(encodedMp3, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
var encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(inputWav);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.WriteLine("Finished writing " + encodedMp3);
|
||||||
|
|
||||||
|
Debug.WriteLine("Begin writing " + decodedWav);
|
||||||
|
using (var fileStream = new FileStream(decodedWav, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
var wavOpts = new Mp3EncodingOptions();
|
||||||
|
wavOpts.Infile = "-";
|
||||||
|
wavOpts.Outfile = "-";
|
||||||
|
// wavOpts.MonoDownmixing = true;
|
||||||
|
wavOpts.Mp3Input = true;
|
||||||
|
wavOpts.DecodeWav = true;
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(wavOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(encodedMp3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.WriteLine("Finished writing " + decodedWav);
|
||||||
|
|
||||||
|
using (var fileStream = new FileStream(reencodedMp3, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
var encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(decodedWav);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var reencodedProperties = new Mp3FileProperties(reencodedMp3);
|
||||||
|
var encodedProperties = new Mp3FileProperties(encodedMp3);
|
||||||
|
Assert.AreEqual(encodedProperties.FileLength, reencodedProperties.FileLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void StreamingVsOutputMp3DecodingTest()
|
||||||
|
{
|
||||||
|
String input = "44_16_s.mp3";
|
||||||
|
String outputOptionDecoded = "outputOptionDecoded.wav";
|
||||||
|
String streamingDecoded = "streamingDecode.wav";
|
||||||
|
|
||||||
|
var encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
encOpts.Mp3Input = true;
|
||||||
|
encOpts.DecodeWav = true;
|
||||||
|
|
||||||
|
using (var fileStream = new FileStream(streamingDecoded, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fileStream))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encOpts.Outfile = outputOptionDecoded;
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputOptionFileInfo = new FileInfo(outputOptionDecoded);
|
||||||
|
var streamingFileInfo = new FileInfo(streamingDecoded);
|
||||||
|
|
||||||
|
FilesAreEqual(outputOptionFileInfo, streamingFileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void StreamingVsOutputMp3EncodingTest()
|
||||||
|
{
|
||||||
|
//String inputWav = "44_16_s.wav";
|
||||||
|
String inputWav = "test1.wav";
|
||||||
|
String outputOptionEncodedMp3 = "outputOptionEncodedMp3.mp3";
|
||||||
|
String streamingEncodedMp3 = "streamingEncodedMp3.mp3";
|
||||||
|
|
||||||
|
var encOpts = new Mp3EncodingOptions();
|
||||||
|
encOpts.Outfile = "-";
|
||||||
|
encOpts.Infile = "-";
|
||||||
|
|
||||||
|
using (var fs = new FileStream(streamingEncodedMp3, FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts, fs))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(inputWav);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encOpts.Outfile = outputOptionEncodedMp3;
|
||||||
|
|
||||||
|
using (ProcessStreamWrapper enc = new Mp3Encoder(encOpts))
|
||||||
|
{
|
||||||
|
enc.ProgressCallback = this;
|
||||||
|
enc.ProcessInput(inputWav);
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputOptionProperties = new Mp3FileProperties(outputOptionEncodedMp3);
|
||||||
|
var streamingProperties = new Mp3FileProperties(streamingEncodedMp3);
|
||||||
|
Assert.AreEqual(outputOptionProperties.LengthInSeconds, streamingProperties.LengthInSeconds);
|
||||||
|
|
||||||
|
// FilesAreEqual(outputOptionFileInfo, streamingFileInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user