SHARE
TWEET

MciPlayer

ForeverZer0 May 5th, 2012 121 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Runtime.CompilerServices;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7.  
  8. namespace ForeverZer0.Audio
  9. {      
  10.         public class MciPlayer : IDisposable, IComparable<MciPlayer>
  11.         {
  12.                 #region DLL Imports
  13.  
  14.                 /// <summary>
  15.                 /// Hook for sending MCI commands
  16.                 /// </summary>
  17.                 /// <param name="strCommand">The command to make</param>
  18.                 /// <param name="strReturn">Any data returned by the command</param>
  19.                 /// <param name="iReturnLength">The maximum size of the return data</param>
  20.                 /// <param name="hwndCallback">A handle to a window that will recieve notifications</param>
  21.                 /// <returns>The error code from the command</returns>
  22.                 [DllImport("winmm.dll")]
  23.         private static extern long mciSendString(string strCommand, StringBuilder strReturn,
  24.             int iReturnLength, IntPtr hwndCallback);
  25.  
  26.                 /// <summary>
  27.                 /// Gets error messages associated with MCI error codes
  28.                 /// </summary>
  29.                 /// <param name="errCode">The MCI error code</param>
  30.                 /// <param name="strReturn">Any data returned by the command</param>
  31.                 /// <param name="iReturnLength">The maximum size of the return data</param>
  32.                 /// <returns>Integer that represents true/false if call was successful</returns>
  33.                 [DllImport("winmm.dll")]
  34.                 public static extern int mciGetErrorString(int errCode, StringBuilder strReturn,
  35.                         int iReturnLength);
  36.  
  37.                 #endregion
  38.  
  39.                 #region Constants
  40.  
  41.                 /// <summary>
  42.                 /// The size of the buffer to use for return values
  43.                 /// </summary>
  44.                 public const int BUFFER_SIZE = 128;
  45.  
  46.                 #endregion
  47.  
  48.                 #region Private Properties
  49.  
  50.                 private string _name, _filename, _cmd, _errorMessage;
  51.         private StringBuilder _buffer, _errorBuffer, _log;
  52.                 private IntPtr _windowHandle;
  53.                 private bool _disposed;
  54.  
  55.         #endregion
  56.  
  57.         #region Public Properties
  58.  
  59.                 /// <summary>
  60.                 /// Gets or sets the master volume. Values outside of 0 to 1000 will be automatically corrected.
  61.                 /// </summary>
  62.         public int Volume { get { return GetVolume(); } set { SetVolume(value); } }
  63.  
  64.                 /// <summary>
  65.                 /// Gets or sets the left volume. Values outside of 0 to 1000 will be automatically corrected.
  66.                 /// </summary>
  67.                 public int VolumeLeft { get { return GetVolumeLeft(); } set { SetVolumeLeft(value); } }
  68.  
  69.                 /// <summary>
  70.                 /// Gets or sets the right volume. Values outside of 0 to 1000 will be automatically corrected.
  71.                 /// </summary>
  72.                 public int VolumeRight { get { return GetVolumeRight(); } set { SetVolumeRight(value); } }
  73.  
  74.                 /// <summary>
  75.                 /// Gets or sets the speed of playaback. Values outside of 0 to 2000 will be automatically corrected.
  76.                 /// </summary>
  77.         public int Speed { get { return GetSpeed(); } set { SetSpeed(value); } }
  78.  
  79.                 /// <summary>
  80.                 /// Gets or sets the treble. Values outside of 0 to 2000 will be automatically corrected.
  81.                 /// </summary>
  82.         public int Treble { get { return GetTreble(); } set { SetTreble(value); } }
  83.  
  84.                 /// <summary>
  85.                 /// Gets or sets the bass. Values outside of 0 to 2000 will be automatically corrected.
  86.                 /// </summary>
  87.         public int Bass { get { return GetBass(); } set { SetBass(value); } }
  88.  
  89.                 /// <summary>
  90.                 /// Gets or sets the current millisecond position of playback
  91.                 /// </summary>
  92.         public long Position { get { return GetPosition(); } set { SetPosition(value); } }
  93.  
  94.                 /// <summary>
  95.                 /// Gets the length of the file in milliseconds
  96.                 /// </summary>
  97.         public long Length { get { return GetLength(); } }
  98.  
  99.                 /// <summary>
  100.                 /// Gets or sets the path of the current file.
  101.                 /// </summary>
  102.         public string Filename { get { return _filename; } set { Load(value); } }
  103.  
  104.                 /// <summary>
  105.                 /// Gets or sets repeat mode
  106.                 /// </summary>
  107.                 public bool Repeat { get; set; }
  108.  
  109.                 /// <summary>
  110.                 /// Gets the status of the mixer as a string
  111.                 /// </summary>
  112.                 public MciStatus Status { get { return GetStatus(); } }
  113.  
  114.                 /// <summary>
  115.                 /// Gets or sets the window handle that will receive notifications
  116.                 /// </summary>
  117.                 public IntPtr WindowHandle { get { return _windowHandle; } set { _windowHandle = value; } }
  118.  
  119.                 /// <summary>
  120.                 /// Enables logging functions for the mixer.
  121.                 /// </summary>
  122.                 /// <remarks>Having logging enabled can degrade performance</remarks>
  123.                 public bool LoggingEnabled { get; set; }
  124.  
  125.                 /// <summary>
  126.                 /// Gets the log buffer as a string
  127.                 /// </summary>
  128.                 public string Log { get { return _log.ToString(); } }
  129.  
  130.         #endregion
  131.  
  132.                 #region Construction
  133.  
  134.                 /// <summary>
  135.                 /// Creates and returns a new instance of the mixer
  136.                 /// </summary>
  137.                 /// <param name="name">The alias name of the mixer</param>
  138.                 /// <param name="handle">The handle of the window to recieve notifications from the player</param>
  139.         public MciPlayer(string name, IntPtr handle)
  140.         {
  141.             _name = name;
  142.             _buffer = new StringBuilder(BUFFER_SIZE);
  143.                         _errorBuffer = new StringBuilder(BUFFER_SIZE);
  144.                         _windowHandle = handle;
  145.                         _disposed = false;
  146.                         _log = new StringBuilder();
  147.         }
  148.  
  149.                 /// <summary>
  150.                 /// Creates and returns a new instance of the mixer
  151.                 /// </summary>
  152.                 /// <param name="name">The alias name of the mixer</param>
  153.                 public MciPlayer(string name) : this(name, IntPtr.Zero) { }
  154.  
  155.                 #endregion
  156.  
  157.                 #region Playback Control
  158.  
  159.                 /// <summary>
  160.                 /// Loads a file and readies it for playback
  161.                 /// </summary>
  162.                 /// <param name="filename">The path to the file</param>
  163.                 public void Load(string filename)
  164.         {
  165.                         if (_disposed)
  166.                                 throw new ObjectDisposedException(_name);
  167.                         this.Close();
  168.             _filename = filename;
  169.             _cmd = String.Format("open \"{0}\" type mpegvideo alias {1} notify", _filename, _name);
  170.             LogError(mciSendString(_cmd, null, 0, WindowHandle));
  171.                         OnOpen(new OnOpenEventArgs(_filename));
  172.         }
  173.  
  174.                 /// <summary>
  175.                 /// Begins playback of a loaded file
  176.                 /// </summary>
  177.                 /// <param name="repeat">Flag to repeat playback when file is done playing</param>
  178.                 /// <param name="position">The millisecond to begin playback at</param>
  179.         public void Play(bool repeat, int position)
  180.         {
  181.                         if (_disposed)
  182.                                 throw new ObjectDisposedException(_name);
  183.             if (!File.Exists(_filename))
  184.                 return;
  185.                         Repeat = repeat;
  186.             _cmd = String.Format("seek {0} to {1} notify", _name, position == 0 ? "start" : position.ToString());
  187.             LogError(mciSendString(_cmd, null, 0, WindowHandle));
  188.             _cmd = String.Format("play {0} notify{1}", _name, repeat ? " repeat" : "");
  189.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  190.                         OnPlay(new OnPlayEventArgs(_filename, GetLength()));
  191.         }
  192.  
  193.                 /// <summary>
  194.                 /// Begins playback of a loaded file
  195.                 /// </summary>
  196.                 /// <param name="repeat">Flag to repeat playback when file is done playing</param>
  197.         public void Play(bool repeat) { Play(repeat, 0); }
  198.  
  199.                 /// <summary>
  200.                 /// Begins playback of a loaded file
  201.                 /// </summary>
  202.         public void Play() { Play(false, 0); }
  203.  
  204.                 /// <summary>
  205.                 /// Pause playback while maintaining current position
  206.                 /// </summary>
  207.         public void Pause()
  208.         {
  209.             _cmd = String.Format("pause {0} notify", _name);
  210.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  211.                         OnPause(new OnPauseEventArgs(GetPosition(), false));
  212.         }
  213.  
  214.                 /// <summary>
  215.                 /// Resume playback on a paused mixer
  216.                 /// </summary>
  217.         public void Resume()
  218.         {
  219.             _cmd = String.Format("resume {0} notify", _name);
  220.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  221.                         OnPause(new OnPauseEventArgs(GetPosition(), true));
  222.         }
  223.  
  224.                 /// <summary>
  225.                 /// Sets the millisecond of the current playback position
  226.                 /// </summary>
  227.                 /// <param name="millisecond">The millisecond position</param>
  228.                 public void Seek(long millisecond)
  229.                 {
  230.                         SetPosition(millisecond);
  231.                 }
  232.  
  233.                 /// <summary>
  234.                 /// Stops playback and moves the current position back to the beginning of the file
  235.                 /// </summary>
  236.         public void Stop()
  237.         {
  238.             _cmd = String.Format("seek {0} to start notify", _name);
  239.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  240.             _cmd = String.Format("stop {0} notify", _name);
  241.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  242.                         OnStop(new EventArgs());
  243.         }
  244.  
  245.                 /// <summary>
  246.                 /// Stops playback and destroys the player
  247.                 /// </summary>
  248.                 public void Close()
  249.                 {
  250.                         _cmd = String.Format("close {0} notify", _name);
  251.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  252.                         _filename = null;
  253.                         OnClose(new EventArgs());
  254.                 }
  255.  
  256.                 /// <summary>
  257.                 /// Closes any files opened in the mixer
  258.                 /// </summary>
  259.                 public void Dispose()
  260.                 {
  261.                         if (!_disposed)
  262.                         {
  263.                                 this.Close();
  264.                                 _disposed = true;
  265.                                 GC.SuppressFinalize(this);
  266.                         }
  267.                 }
  268.  
  269.                 /// <summary>
  270.                 /// Begins recording from the input
  271.                 /// </summary>
  272.                 /// <param name="bits">The bits per sample for the recording</param>
  273.                 /// <param name="sampleRate">The sample rate of the recording</param>
  274.                 /// <param name="channels">The number of channels of the recording</param>
  275.         public void Record(int bits, int sampleRate, int channels)
  276.         {
  277.                         this.Close();
  278.                         _cmd = String.Format("open new type waveaudio alias {0}", _name);
  279.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  280.                         _cmd = String.Format("set {0} bitspersample {1}", _name, bits);
  281.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  282.                         _cmd = String.Format("set {0} samplespersec {1}", _name, sampleRate);
  283.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  284.                         _cmd = String.Format("set {0} channels {1}", _name, channels);
  285.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  286.                         _cmd = String.Format("record {0} notify", _name);
  287.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  288.                         OnRecord(new OnRecordEventArgs(bits, sampleRate, channels));
  289.         }
  290.  
  291.                 /// <summary>
  292.                 /// Begins recording from the input
  293.                 /// </summary>
  294.                 /// <param name="bits">The bits per sample for the recording</param>
  295.                 /// <param name="sampleRate">The sample rate of the recording</param>
  296.                 public void Record(int bits, int sampleRate) { Record(bits, sampleRate, 2); }
  297.  
  298.                 /// <summary>
  299.                 /// Begins recording from the input
  300.                 /// </summary>
  301.                 /// <param name="bits">The bits per sample for the recording</param>
  302.                 public void Record(int bits) { Record(bits, 44100, 2); }
  303.  
  304.                 /// <summary>
  305.                 /// Begins recording from the input
  306.                 /// </summary>
  307.                 public void Record() { Record(16, 44100, 2); }
  308.  
  309.                 /// <summary>
  310.                 /// Saves a recorded file to disk in WAV format
  311.                 /// </summary>
  312.                 /// <param name="filename">The path of the file to save</param>
  313.                 /// <remarks>The WAV extension will be added if path does not have it</remarks>
  314.                 public void SaveRecording(string filename)
  315.                 {
  316.                         if (IsRecording())
  317.                                 this.Stop();
  318.                         string ext = Path.GetExtension(filename);
  319.                         if (ext != ".wav")
  320.                         {
  321.                                 filename = Path.Combine(Path.GetDirectoryName(filename),
  322.                                         Path.GetFileNameWithoutExtension(filename) + ".wav");
  323.                         }
  324.                         _cmd = String.Format("save {0} {1}", _name, filename);
  325.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  326.                         _cmd = String.Format("close {0}", _name);
  327.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  328.                 }
  329.  
  330.                 /// <summary>
  331.                 /// Mutes/unmutes all sound while continuing to play
  332.                 /// </summary>
  333.                 /// <param name="on">Flag to enable/disable sound</param>
  334.                 public void Mute(bool on)
  335.                 {
  336.                         _cmd = String.Format("setaudio {0} {1}", _name, on ? "off" : "on");
  337.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  338.                 }
  339.  
  340.                 /// <summary>
  341.                 /// Mutes/unmutes all sound on the left channel while continuing to play
  342.                 /// </summary>
  343.                 /// <param name="on">Flag to enable/disable sound</param>
  344.                 public void MuteLeft(bool on)
  345.                 {
  346.                         _cmd = String.Format("setaudio {0} left {1}", _name, on ? "off" : "on");
  347.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  348.                 }
  349.  
  350.                 /// <summary>
  351.                 /// Mutes/unmutes all sound on the right channel while continuing to play
  352.                 /// </summary>
  353.                 /// <param name="on">Flag to enable/disable sound</param>
  354.                 public void MuteRight(bool on)
  355.                 {
  356.                         _cmd = String.Format("setaudio {0} right {1}", _name, on ? "off" : "on");
  357.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  358.                 }
  359.  
  360.         #endregion
  361.  
  362.         #region Setters
  363.  
  364.                 /// <summary>
  365.                 /// Sets the master volume of the mixer
  366.                 /// </summary>
  367.                 /// <param name="volume">The volume to set. A value between 0 and 1000.
  368.                 /// Values outside this range will be automatically corrected</param>
  369.         public void SetVolume(int volume)
  370.         {
  371.             volume = Clamp<int>(volume, 0, 1000);
  372.             _cmd = String.Format("setaudio {0} volume to {1} notify", _name, volume);
  373.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));  
  374.         }
  375.  
  376.                 /// <summary>
  377.                 /// Sets the left volume of the mixer
  378.                 /// </summary>
  379.                 /// <param name="volume">The volume to set. A value between 0 and 1000.
  380.                 /// Values outside this range will be automatically corrected</param>
  381.                 public void SetVolumeLeft(int volume)
  382.                 {
  383.                         volume = Clamp<int>(volume, 0, 1000);
  384.                         _cmd = String.Format("setaudio {0} left volume to {1} notify", _name, volume);
  385.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  386.                 }
  387.  
  388.                 /// <summary>
  389.                 /// Sets the right volume of the mixer
  390.                 /// </summary>
  391.                 /// <param name="volume">The volume to set. A value between 0 and 1000.
  392.                 /// Values outside this range will be automatically corrected</param>
  393.                 public void SetVolumeRight(int volume)
  394.                 {
  395.                         volume = Clamp<int>(volume, 0, 1000);
  396.                         _cmd = String.Format("setaudio {0} right volume to {1} notify", _name, volume);
  397.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  398.                 }
  399.  
  400.                 /// <summary>
  401.                 /// Sets the playback speed of the mixer
  402.                 /// </summary>
  403.                 /// <param name="volume">The speed ratio to set. A value between 0 and 2000, where 1000 is normal.
  404.                 /// Values outside this range will be automatically corrected</param>
  405.         public void SetSpeed(int speed)
  406.         {
  407.             speed = Clamp<int>(speed, 0, 2000);
  408.             _cmd = String.Format("set {0} speed {1} notify", _name, speed);
  409.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  410.         }
  411.  
  412.                 /// <summary>
  413.                 /// Sets the treble of the mixer
  414.                 /// </summary>
  415.                 /// <param name="volume">The treble value to set. A value between 0 and 2000, where 1000 is normal.
  416.                 /// Values outside this range will be automatically corrected</param>
  417.         public void SetTreble(int treble)
  418.         {
  419.             treble = Clamp<int>(treble, 0, 1000);
  420.                         _cmd = String.Format("setaudio {0} treble to {1} notify", _name, treble);
  421.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  422.         }
  423.  
  424.                 /// <summary>
  425.                 /// Sets the bass of the mixer
  426.                 /// </summary>
  427.                 /// <param name="volume">The bass value to set. A value between 0 and 2000, where 1000 is normal.
  428.                 /// Values outside this range will be automatically corrected</param>
  429.         public void SetBass(int bass)
  430.         {
  431.             bass = Clamp<int>(bass, 0, 1000);
  432.             _cmd = String.Format("setaudio {0} bass to {1} notify", _name, bass);
  433.             LogError(mciSendString(_cmd, null, 0,  WindowHandle));
  434.         }
  435.  
  436.                 /// <summary>
  437.                 /// Sets the millisecond of the current playback position
  438.                 /// </summary>
  439.                 /// <param name="position">The millisecond position</param>
  440.         public void SetPosition(long position)
  441.         {
  442.                         long current = GetPosition();
  443.             position = Clamp<long>(position, 0, this.GetLength());
  444.             _cmd = String.Format("{0} {1} from {2} notify", IsPlaying() ? "play" : "seek", _name, position);
  445.                         LogError(mciSendString(_cmd, null, 0, WindowHandle));
  446.                         OnSeek(new OnSeekEventArgs(current, position));
  447.         }
  448.  
  449.         #endregion
  450.  
  451.         #region Getters
  452.  
  453.                 /// <summary>
  454.                 /// Gets the master volume (0 - 1000)
  455.                 /// </summary>
  456.                 /// <returns>The master volume</returns>
  457.         public int GetVolume()
  458.         {
  459.             _buffer.Clear();
  460.                         _cmd = String.Format("status {0} volume", _name);
  461.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  462.                         string value = _buffer.ToString();
  463.                         if (String.IsNullOrEmpty(value))
  464.                                 return 0;
  465.                         return Convert.ToInt32(value);
  466.         }
  467.  
  468.                 /// <summary>
  469.                 /// Gets the volume of the left channel only (0 - 1000)
  470.                 /// </summary>
  471.                 /// <returns>The left channel volume</returns>
  472.                 public int GetVolumeLeft()
  473.                 {
  474.                         _buffer.Clear();
  475.                         _cmd = String.Format("status {0} volume left", _name);
  476.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  477.                         string value = _buffer.ToString();
  478.                         if (String.IsNullOrEmpty(value))
  479.                                 return 0;
  480.                         return Convert.ToInt32(value);
  481.                 }
  482.  
  483.                 /// <summary>
  484.                 /// Gets the volume of the right channel only (0 - 1000)
  485.                 /// </summary>
  486.                 /// <returns>The right channel volume</returns>
  487.                 public int GetVolumeRight()
  488.                 {
  489.                         _buffer.Clear();
  490.                         _cmd = String.Format("status {0} volume right", _name);
  491.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  492.                         string value = _buffer.ToString();
  493.                         if (String.IsNullOrEmpty(value))
  494.                                 return 0;
  495.                         return Convert.ToInt32(value);
  496.                 }
  497.  
  498.                 /// <summary>
  499.                 /// Gets the speed of playback (1000 = normal speed)(0 - 2000)
  500.                 /// </summary>
  501.                 /// <returns>The speed of playback</returns>
  502.         public int GetSpeed()
  503.         {
  504.             _buffer.Clear();
  505.                         _cmd = String.Format("status {0} speed", _name);
  506.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  507.                         string value = _buffer.ToString();
  508.                         if (String.IsNullOrEmpty(value))
  509.                                 return 0;
  510.                         return Convert.ToInt32(value);
  511.         }
  512.  
  513.                 /// <summary>
  514.                 /// Gets the treble volume (0 - 2000)
  515.                 /// </summary>
  516.                 /// <returns>The treble volume</returns>
  517.         public int GetTreble()
  518.         {
  519.             _buffer.Clear();
  520.                         _cmd = String.Format("status {0} treble", _name);
  521.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  522.                         string value = _buffer.ToString();
  523.                         if (String.IsNullOrEmpty(value))
  524.                                 return 0;
  525.                         return Convert.ToInt32(value);
  526.         }
  527.  
  528.                 /// <summary>
  529.                 /// Gets the bass volume (0 - 2000)
  530.                 /// </summary>
  531.                 /// <returns>The bass volume</returns>
  532.         public int GetBass()
  533.         {
  534.             _buffer.Clear();
  535.                         _cmd = String.Format("status {0} bass", _name);
  536.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  537.                         string value = _buffer.ToString();
  538.                         if (String.IsNullOrEmpty(value))
  539.                                 return 0;
  540.                         return Convert.ToInt32(value);
  541.         }
  542.  
  543.                 /// <summary>
  544.                 /// Gets the current position of playback in milliseconds
  545.                 /// </summary>
  546.                 /// <returns>The current position</returns>
  547.         public long GetPosition()
  548.         {
  549.             _buffer.Clear();
  550.                         if (IsPlaying() || IsPaused())
  551.                         {
  552.                                 _cmd = String.Format("status {0} position", _name);
  553.                                 LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  554.                                 string value = _buffer.ToString();
  555.                                 if (String.IsNullOrEmpty(value))
  556.                                         return 0L;
  557.                                 return Convert.ToInt64(value);
  558.                         }
  559.                         return 0L;
  560.         }
  561.  
  562.                 /// <summary>
  563.                 /// Gets the length of the currently opened file in milliseconds
  564.                 /// </summary>
  565.                 /// <returns>The number of milliseconds of the file as <paramref name="System.Int64"/></returns>
  566.         public long GetLength()
  567.         {
  568.             _buffer.Clear();
  569.                         _cmd = String.Format("status {0} length", _name);
  570.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  571.                         string value = _buffer.ToString();
  572.                         if (String.IsNullOrEmpty(value))
  573.                                 return 0L;
  574.             return Convert.ToInt64(value);
  575.         }
  576.  
  577.                 /// <summary>
  578.                 /// Gets the volume of the left channel
  579.                 /// </summary>
  580.                 /// <returns>The volume of the left channel as a <paramref name="System.Int32"/></returns>
  581.         public int GetLeftVolume()
  582.         {
  583.             _buffer.Clear();
  584.                         _cmd = String.Format("status {0} left volume", _name);
  585.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  586.                         string value = _buffer.ToString();
  587.                         if (String.IsNullOrEmpty(value))
  588.                                 return 0;
  589.                         return Convert.ToInt32(value);
  590.         }
  591.  
  592.                 /// <summary>
  593.                 /// Gets the volume of the right channel
  594.                 /// </summary>
  595.                 /// <returns>The volume of the right channel as a <paramref name="System.Int32"/></returns>
  596.         public int GetRightVolume()
  597.         {
  598.             _buffer.Clear();
  599.                         _cmd = String.Format("status {0} right volume", _name);
  600.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  601.                         string value = _buffer.ToString();
  602.                         if (String.IsNullOrEmpty(value))
  603.                                 return 0;
  604.                         return Convert.ToInt32(value);
  605.         }
  606.  
  607.         #endregion
  608.  
  609.         #region Status
  610.  
  611.                 /// <summary>
  612.                 /// Gets the "playing" state of the mixer
  613.                 /// </summary>
  614.                 /// <returns>The "plaing" state of the mixer as <paramref name="System.Bool"/></returns>
  615.         public bool IsPlaying()
  616.         {
  617.             return this.GetStatus() == MciStatus.Playing;
  618.         }
  619.  
  620.                 /// <summary>
  621.                 /// Gets the "pause" state of the mixer
  622.                 /// </summary>
  623.                 /// <returns>The "pause" state of the mixer as <paramref name="System.Bool"/></returns>
  624.         public bool IsPaused()
  625.         {
  626.             return this.GetStatus() == MciStatus.Paused;
  627.         }
  628.  
  629.                 /// <summary>
  630.                 /// Gets the "recording" state of the mixer
  631.                 /// </summary>
  632.                 /// <returns>The "recording" state of the mixer as <paramref name="System.Bool"/></returns>
  633.         public bool IsRecording()
  634.         {
  635.             return this.GetStatus() == MciStatus.Recording;
  636.         }
  637.  
  638.                 /// <summary>
  639.                 /// Gets the current status of the mixer
  640.                 /// </summary>
  641.                 /// <returns>The current state of the mixer as a <paramref name="MCI_Player.MciStatus"/></returns>
  642.                 public MciStatus GetStatus()
  643.         {
  644.             _buffer.Clear();
  645.             _cmd = String.Format("status {0} mode", _name);
  646.                         LogError(mciSendString(_cmd, _buffer, BUFFER_SIZE, IntPtr.Zero));
  647.                         switch (_buffer.ToString().Trim())
  648.                         {
  649.                                 case "playing": return MciStatus.Playing;
  650.                                 case "not ready": return MciStatus.NotReady;
  651.                                 case "paused": return MciStatus.Paused;
  652.                                 case "recording": return MciStatus.Recording;
  653.                                 case "seeking": return MciStatus.Seeking;
  654.                                 case "parked": return MciStatus.Parked;
  655.                                 case "open": return MciStatus.Open;
  656.                                 default: return MciStatus.Stopped;
  657.                         }
  658.         }
  659.  
  660.         #endregion
  661.  
  662.                 #region Utilities
  663.  
  664.                 /// <summary>
  665.                 /// IComparable interface. Simply compares alias names used by MCI
  666.                 /// </summary>
  667.                 /// <param name="other">MCIPlayer to compare to</param>
  668.                 /// <returns>Result of comparison</returns>
  669.                 public int CompareTo(MciPlayer other)
  670.                 {
  671.                         return _name.CompareTo(other._name);
  672.                 }
  673.  
  674.                 /// <summary>
  675.                 /// Clamp to values of type T within a defined range
  676.                 /// </summary>
  677.                 /// <typeparam name="T">The <see cref="System.Type"/> of the that will be passed and returned. Must implement the <see cref="System.IComparable"/> interface</typeparam>
  678.                 /// <param name="val">The value to clamp</param>
  679.                 /// <param name="min">The minimum allowed value</param>
  680.                 /// <param name="max">The maximum allowed value</param>
  681.                 /// <returns>The value clamped between the minimum and maximum</returns>
  682.                 public static T Clamp<T>(T val, T min, T max) where T : IComparable<T>
  683.                 {
  684.                         if (val.CompareTo(min) < 0) return min;
  685.                         else if (val.CompareTo(max) > 0) return max;
  686.                         else return val;
  687.                 }
  688.  
  689.                 /// <summary>
  690.                 /// Returns the length of the file as a string formatted as M:SS.
  691.                 /// </summary>
  692.                 /// <returns>The formatted string</returns>
  693.                 public string FormattedLength()
  694.                 {
  695.                         long length = GetLength() / 1000;
  696.                         return String.Format("{0}:{1:d2}", length / 60, length % 60);
  697.                 }
  698.  
  699.                 /// <summary>
  700.                 /// Returns the current postion of playback as a string formatted as M:SS.
  701.                 /// </summary>
  702.                 /// <returns>The formatted string</returns>
  703.                 public string FormattedPosition()
  704.                 {
  705.                         long pos = GetPosition() / 1000;
  706.                         return String.Format("{0}:{1:d2}", pos / 60, pos % 60);
  707.                 }
  708.  
  709.                 /// <summary>
  710.                 /// Evaluates an MCI command and returns any data received
  711.                 /// </summary>
  712.                 /// <param name="command">The <paramref name="System.String"/> MCI command</param>
  713.                 /// <returns>Any data that is returned by result of the command, else an empty string</returns>
  714.                 public string MciEvaluate(string command)
  715.                 {
  716.                         _buffer.Clear();
  717.                         LogError(mciSendString(command, _buffer, BUFFER_SIZE, WindowHandle));
  718.                         return _buffer.ToString();
  719.                 }
  720.  
  721.                 #endregion
  722.  
  723.                 #region Logging
  724.  
  725.                 /// <summary>
  726.                 /// Clears the log buffer.
  727.                 /// </summary>
  728.                 public void ClearLog()
  729.                 {
  730.                         _log.Clear();
  731.                 }
  732.  
  733.                 /// <summary>
  734.                 /// Saves the log to disk
  735.                 /// </summary>
  736.                 /// <param name="filename">The path to the file to writw</param>
  737.                 /// <returns>Flag if save was successful</returns>
  738.                 public bool SaveLog(string filename)
  739.                 {
  740.                         try
  741.                         {
  742.                                 File.WriteAllText(filename, _log.ToString());
  743.                                 return true;
  744.                         }
  745.                         catch { return false; }
  746.                 }
  747.  
  748.                 /// <summary>
  749.                 /// Evaluates and adds an entry to the log
  750.                 /// </summary>
  751.                 /// <param name="error">The MCI error code to evaluate</param>
  752.                 [MethodImpl(MethodImplOptions.NoInlining)]
  753.                 private void LogError(long error)
  754.                 {
  755.                         if (LoggingEnabled && error != 0)
  756.                         {
  757.                                 _errorBuffer.Clear();
  758.                                 mciGetErrorString((int)error, _errorBuffer, BUFFER_SIZE);
  759.                                 _errorMessage = _errorBuffer.ToString();
  760.                                 if (_errorMessage != "The specified command was carried out.")
  761.                                 {
  762.                                         string function = new StackFrame(1, true).GetMethod().Name;
  763.                                         _log.AppendFormat("{0} in \"{1}\"\n{2}\n\n", DateTime.Now, function, _errorMessage);
  764.                                         Console.WriteLine(_errorBuffer.ToString());
  765.                                 }
  766.                         }
  767.                 }
  768.  
  769.                 #endregion
  770.  
  771.                 #region Delegates
  772.  
  773.                 public delegate void OnOpenEventHandler(object sender, OnOpenEventArgs e);
  774.  
  775.                 public delegate void OnPlayEventHandler(object sender, OnPlayEventArgs e);
  776.  
  777.                 public delegate void OnPauseEventHandler(object sender, EventArgs e);
  778.  
  779.                 public delegate void OnStopEventHandler(object sender, EventArgs e);
  780.  
  781.                 public delegate void OnCloseEventHandler(object sender, EventArgs e);
  782.  
  783.                 public delegate void OnSeekEventHandler(object sender, OnSeekEventArgs e);
  784.  
  785.                 public delegate void OnRecordEventHandler(object sender, OnRecordEventArgs e);
  786.  
  787.                 #endregion
  788.  
  789.                 #region Events
  790.  
  791.                 /// <summary>
  792.                 /// Occurs when a file is opened by the player
  793.                 /// </summary>
  794.                 public event OnOpenEventHandler OnOpenEvent;
  795.  
  796.                 /// <summary>
  797.                 /// Occurs when playback begins
  798.                 /// </summary>
  799.                 public event OnPlayEventHandler OnPlayEvent;
  800.  
  801.                 /// <summary>
  802.                 /// Occurs when playback is paused or resumed
  803.                 /// </summary>
  804.                 public event OnPauseEventHandler OnPauseEvent;
  805.  
  806.                 /// <summary>
  807.                 /// Occurs when the player is stopped
  808.                 /// </summary>
  809.                 public event OnStopEventHandler OnStopEvent;
  810.  
  811.                 /// <summary>
  812.                 /// Occurs when the player is closed
  813.                 /// </summary>
  814.                 public event OnCloseEventHandler OnCloseEvent;
  815.  
  816.                 /// <summary>
  817.                 /// Occurs when the seek function is used
  818.                 /// </summary>
  819.                 public event OnSeekEventHandler OnSeekEvent;
  820.  
  821.                 /// <summary>
  822.                 /// Occurs when the player begins recording
  823.                 /// </summary>
  824.                 public event OnRecordEventHandler OnRecordEvent;
  825.  
  826.                 protected virtual void OnOpen(OnOpenEventArgs e)
  827.                 {
  828.                         if (OnOpenEvent != null) OnOpenEvent(this, e);
  829.                 }
  830.  
  831.                 protected virtual void OnPlay(OnPlayEventArgs e)
  832.                 {
  833.                         if (OnPlayEvent != null) OnPlayEvent(this, e);
  834.                 }
  835.  
  836.                 protected virtual void OnPause(EventArgs e)
  837.                 {
  838.                         if (OnPauseEvent != null) OnPauseEvent(this, e);
  839.                 }
  840.  
  841.                 protected virtual void OnStop(EventArgs e)
  842.                 {
  843.                         if (OnStopEvent != null) OnStopEvent(this, e);
  844.                 }
  845.  
  846.                 protected virtual void OnClose(EventArgs e)
  847.                 {
  848.                         if (OnCloseEvent != null) OnCloseEvent(this, e);
  849.                 }
  850.  
  851.                 protected virtual void OnSeek(OnSeekEventArgs e)
  852.                 {
  853.                         if (OnSeekEvent != null) OnSeekEvent(this, e);
  854.                 }
  855.  
  856.                 protected virtual void OnRecord(OnRecordEventArgs e)
  857.                 {
  858.                         if (OnRecordEvent != null) OnRecordEvent(this, e);
  859.                 }
  860.  
  861.                 #endregion
  862.         }
  863.  
  864.         #region Event Arguments
  865.  
  866.         public class OnOpenEventArgs : EventArgs
  867.         {
  868.                 /// <summary>
  869.                 /// Gets the full path to the opened file
  870.                 /// </summary>
  871.                 public string Filepath { get { return _filename; } }
  872.                 /// <summary>
  873.                 /// Gets the name of the file opened
  874.                 /// </summary>
  875.                 public string Filename { get { return Path.GetFileName(_filename); } }
  876.                 /// <summary>
  877.                 /// Gets the name of the file opened without file extension
  878.                 /// </summary>
  879.                 public string FilenameWithouExtension
  880.                 {
  881.                         get { return Path.GetFileNameWithoutExtension(_filename); }
  882.                 }
  883.                 /// <summary>
  884.                 /// Gets the file extension of the opened file
  885.                 /// </summary>
  886.                 public string Extension { get { return Path.GetExtension(_filename); } }
  887.                 /// <summary>
  888.                 /// Gets the directory of the opened file
  889.                 /// </summary>
  890.                 public string Directory { get { return Path.GetDirectoryName(_filename); } }
  891.  
  892.                 private string _filename;
  893.  
  894.                 /// <summary>
  895.                 /// Event arguments for opening a file
  896.                 /// </summary>
  897.                 /// <param name="filename">The path to the file</param>
  898.                 public OnOpenEventArgs(string filename)
  899.                 {
  900.                         _filename = filename;
  901.                 }
  902.         }
  903.  
  904.         public class OnPlayEventArgs : EventArgs
  905.         {
  906.                 /// <summary>
  907.                 /// The path to the file being played
  908.                 /// </summary>
  909.                 public string Filename { get { return _filename; } }
  910.                 /// <summary>
  911.                 /// The length of the file in milliseconds
  912.                 /// </summary>
  913.                 public long Length { get { return _length; } }
  914.  
  915.                 private string _filename;
  916.                 private long _length;
  917.  
  918.                 /// <summary>
  919.                 /// Event arguments for playing
  920.                 /// </summary>
  921.                 /// <param name="filename">The path to the file being played</param>
  922.                 /// <param name="length">The length of the file in milliseconds</param>
  923.                 public OnPlayEventArgs(string filename, long length)
  924.                 {
  925.                         _filename = filename;
  926.                         _length = length;
  927.                 }
  928.         }
  929.  
  930.         public class OnPauseEventArgs : EventArgs
  931.         {
  932.                 /// <summary>
  933.                 /// The current position in milliseconds of playback
  934.                 /// </summary>
  935.                 public long Position { get { return _position; } }
  936.                 /// <summary>
  937.                 /// Flag if file is being paused or resumed
  938.                 /// </summary>
  939.                 public bool Resuming { get { return _resuming; } }
  940.  
  941.                 private long _position;
  942.                 private bool _resuming;
  943.  
  944.                 /// <summary>
  945.                 /// Event arguments for pausing and resuming
  946.                 /// </summary>
  947.                 /// <param name="position">The current position in milliseconds of playback</param>
  948.                 /// <param name="resuming">Flag if file is being paused or resumed</param>
  949.                 public OnPauseEventArgs(long position, bool resuming)
  950.                 {
  951.                         _position = position;
  952.                         _resuming = resuming;
  953.                 }
  954.         }
  955.  
  956.         public class OnSeekEventArgs : EventArgs
  957.         {
  958.                 /// <summary>
  959.                 /// Gets the position in milliseconds of playback before the change
  960.                 /// </summary>
  961.                 public long CurrentPosition { get { return _current; } }
  962.                 /// <summary>
  963.                 /// Gets the position in milliseconds of playback after the change
  964.                 /// </summary>
  965.                 public long TargetPosition { get { return _target; } }
  966.  
  967.                 private long _current;
  968.                 private long _target;
  969.  
  970.                 /// <summary>
  971.                 /// Event arguments for seeking
  972.                 /// </summary>
  973.                 /// <param name="current">The position in milliseconds of playback before the change</param>
  974.                 /// <param name="target">The position in milliseconds of playback after the change</param>
  975.                 public OnSeekEventArgs(long current, long target)
  976.                 {
  977.                         _current = current;
  978.                         _target = target;
  979.                 }
  980.         }
  981.  
  982.         public class OnRecordEventArgs : EventArgs
  983.         {
  984.                 /// <summary>
  985.                 /// Gets the number of bits per sample of the recording
  986.                 /// </summary>
  987.                 public int BitsPerSample { get { return _bitsPerSample; } }
  988.                 /// <summary>
  989.                 /// Gets the samplerate of the recording
  990.                 /// </summary>
  991.                 public int SampleRate { get { return _sampleRate; } }
  992.                 /// <summary>
  993.                 /// Gets the number of channels used for the recording
  994.                 /// </summary>
  995.                 public int Channels { get { return _channels; } }
  996.  
  997.                 private int _bitsPerSample;
  998.                 private int _sampleRate;
  999.                 private int _channels;
  1000.  
  1001.                 /// <summary>
  1002.                 /// Event arguments for recording
  1003.                 /// </summary>
  1004.                 /// <param name="bitsPerSample">The number of bits used per sample</param>
  1005.                 /// <param name="sampleRate">The sample rate</param>
  1006.                 /// <param name="channels">The number of channels used for recording</param>
  1007.                 public OnRecordEventArgs(int bitsPerSample, int sampleRate, int channels)
  1008.                 {
  1009.                         _bitsPerSample = bitsPerSample;
  1010.                         _sampleRate = sampleRate;
  1011.                         _channels = channels;
  1012.                 }
  1013.         }
  1014.  
  1015.         #endregion
  1016.  
  1017.         # region Enums
  1018.  
  1019.         public enum MciNotify
  1020.         {
  1021.                 Notify = 0x03b9,
  1022.                 Success = 0x01,
  1023.                 Superseded = 0x02,
  1024.                 Aborted = 0x04,
  1025.                 Failure = 0x08
  1026.         }
  1027.  
  1028.         public enum MciStatus
  1029.         {
  1030.                 Playing,
  1031.                 Stopped,
  1032.                 Paused,
  1033.                 Recording,
  1034.                 NotReady,
  1035.                 Open,
  1036.                 Parked,
  1037.                 Seeking
  1038.         }
  1039.  
  1040.         #endregion
  1041. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top