VlcUserControl.cs

From VideoLAN Wiki
Revision as of 01:33, 1 January 2007 by Tappen (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
/*****************************************************************************
 * VlcUserControl.cs: VlcUserControl partial class definition
 *****************************************************************************
 * Copyright (C) 2006 Chris Meadowcroft
 *
 * Authors: Chris Meadowcroft
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace VLanControl
{
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.None)]
	public partial class VlcUserControl : UserControl, IPlayer2
	{
		private bool isPaused;
		private NativeLibVlc nativeVlc = new NativeLibVlc();
		private bool useMpegVbrOffset;
		private bool usingPausedPosition;
		private int pausedTime;
		private double pausedPosition;
		private int shuttleSeconds;
		private bool useVlcCrop = false;
		private int cropTop;
		private int cropBottom;
		private int cropLeft;
		private int cropRight;

		const long SavingPostionTimespan = 5000000L;	// .5 seconds in ticks

		public VlcUserControl()
		{
			InitializeComponent();
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			this.nativeVlc.Initialize();
			this.innerVlc.Bounds = this.ClientRectangle;
			this.nativeVlc.VideoOutput = this.innerVlc;
		}

		public void DisplayMessage(String message)
		{
			this.nativeVlc.ShowMessage(message);
		}

		public Size VideoSize
		{
			get
			{
				return this.nativeVlc.VideoSize;
			}
		}

		public void PrecomputeCrop(Size videoSize, int cropLeft, int cropRight, int cropTop, int cropBottom)
		{
			this.cropTop = cropTop;
			this.cropBottom = cropBottom;
			this.cropLeft = cropLeft;
			this.cropRight = cropRight;
			ComputeCrop(videoSize);
		}

		public bool ComputeCrop()
		{
			if(!this.useVlcCrop && this.IsHandleCreated && (this.nativeVlc.VideoOutput != null) && 
				(this.State != PlayerState.None))
			{
				Size vidSize = this.nativeVlc.VideoSize;
				if(!vidSize.IsEmpty)
				{
					ComputeCrop(this.nativeVlc.VideoSize);
					return true;
				}
			}
			return false;
		}

		private void ComputeCrop(Size videoSize)
		{
			Size mySize = ClientSize;
			Debug.WriteLine("Video Sizes = " + videoSize.ToString() + ", " + mySize.ToString());
			this.topBlocker.Visible = false;
			this.bottomBlocker.Visible = false;
			this.leftBlocker.Visible = false;
			this.rightBlocker.Visible = false;

			double myAspect = Convert.ToDouble(mySize.Width) / Convert.ToDouble(mySize.Height);
			if((this.cropTop == 0) && (this.cropBottom == 0) && (this.cropLeft == 0) && (this.cropRight == 0))
			{
				double vlcAspect = Convert.ToDouble(videoSize.Width) / Convert.ToDouble(videoSize.Height);
				if(vlcAspect > myAspect)
				{
					// gray borders on the top and bottom
					int perfectHeight = Convert.ToInt32(mySize.Width / vlcAspect);
					this.innerVlc.Bounds = new Rectangle(new Point(0, (mySize.Height - perfectHeight) / 2),
						new Size(mySize.Width, perfectHeight));
					Debug.WriteLine("vlcAspect > myAspect " + this.innerVlc.Bounds.ToString());
				}
				else
				{
					// gray borders on the left and right
					int perfectWidth = Convert.ToInt32(mySize.Height * vlcAspect);
					this.innerVlc.Bounds = new Rectangle(new Point((mySize.Width - perfectWidth) / 2, 0),
						new Size(perfectWidth, mySize.Height));
					Debug.WriteLine("vlcAspect < myAspect " + this.innerVlc.Bounds.ToString());
				}
			}
			else
			{
				double realVlcAspect = Convert.ToDouble(videoSize.Width - this.cropRight - this.cropLeft) / 
					Convert.ToDouble(videoSize.Height - this.cropTop - this.cropBottom);
				if(realVlcAspect > myAspect)
				{
					// gray borders on the top and bottom, and possible blocking panels
					// first, position and size the innerVlc as if there was no top or bottom cropping
					int videoPixelWidth = videoSize.Width - this.cropRight - this.cropLeft;
					double fakeVlcAspect = Convert.ToDouble(videoPixelWidth) / Convert.ToDouble(videoSize.Height);
					int perfectHeight = Convert.ToInt32(mySize.Width / fakeVlcAspect);

					double widthScaling = Convert.ToDouble(mySize.Width) / Convert.ToDouble(videoPixelWidth);
					int innerVlcLeft = -Convert.ToInt32(Convert.ToDouble(this.cropLeft) * widthScaling);
					int innerVlcWidth = Convert.ToInt32(Convert.ToDouble(videoSize.Width) * widthScaling);

					int videoTop = (mySize.Height - perfectHeight) / 2;
					this.innerVlc.Bounds = new Rectangle(new Point(innerVlcLeft, videoTop),
						new Size(innerVlcWidth, perfectHeight));

					// then, add blocking panels if necessary for the top and bottom cropping
					if(this.cropTop != 0)
					{
						double heightScaling = Convert.ToDouble(perfectHeight) / Convert.ToDouble(videoSize.Height);
						int blockerHeight = Convert.ToInt32(Convert.ToDouble(this.cropTop) * heightScaling);
						this.topBlocker.Bounds = new Rectangle(
							new Point(0, videoTop), 
							new Size(mySize.Width, blockerHeight));
						this.topBlocker.Visible = true;
					}
					if(this.cropBottom != 0)
					{
						double heightScaling = Convert.ToDouble(perfectHeight) / Convert.ToDouble(videoSize.Height);
						int blockerHeight = Convert.ToInt32(Convert.ToDouble(this.cropBottom) * heightScaling);
						this.bottomBlocker.Bounds = new Rectangle(
							new Point(0, mySize.Height - videoTop - blockerHeight),
							new Size(mySize.Width, blockerHeight));
						this.bottomBlocker.Visible = true;
					}
				}
				else
				{
					// gray borders on the left and right, and possible blocking panels
					// first, position and size the innerVlc as if there was no left or right cropping
					int videoPixelHeight = videoSize.Height - this.cropBottom - this.cropTop;
					double fakeVlcAspect = Convert.ToDouble(videoSize.Width) / Convert.ToDouble(videoPixelHeight);
					int perfectWidth = Convert.ToInt32(mySize.Height * fakeVlcAspect);

					double heightScaling = Convert.ToDouble(mySize.Height) / Convert.ToDouble(videoPixelHeight);
					int innerVlcTop = -Convert.ToInt32(Convert.ToDouble(this.cropTop) * heightScaling);
					int innerVlcHeight = Convert.ToInt32(Convert.ToDouble(videoSize.Height) * heightScaling);

					int videoWidth = (mySize.Width - perfectWidth) / 2;
					this.innerVlc.Bounds = new Rectangle(new Point(videoWidth, innerVlcTop),
						new Size(perfectWidth, innerVlcHeight));

					// then, add blocking panels if necessary for the left and right cropping
					if(this.cropLeft != 0)
					{
						double widthScaling = Convert.ToDouble(perfectWidth) / Convert.ToDouble(videoSize.Width);
						int blockerWidth = Convert.ToInt32(Convert.ToDouble(this.cropLeft) * widthScaling);
						this.leftBlocker.Bounds = new Rectangle(
							new Point(videoWidth, 0),
							new Size(blockerWidth, mySize.Height));
						this.leftBlocker.Visible = true;
					}
					if(this.cropRight != 0)
					{
						double widthScaling = Convert.ToDouble(perfectWidth) / Convert.ToDouble(videoSize.Width);
						int blockerWidth = Convert.ToInt32(Convert.ToDouble(this.cropRight) * widthScaling);
						this.rightBlocker.Bounds = new Rectangle(
							new Point(mySize.Width - videoWidth - blockerWidth, 0),
							new Size(blockerWidth, mySize.Height));
						this.rightBlocker.Visible = true;
					}
				}
			}
		}

		public bool SetConfigVariable(String name, String value)
		{
			return this.nativeVlc.SetConfigVariable(name, value) == VlcError.Success;
		}

		public int Time
		{
			get
			{
				try
				{
					return this.nativeVlc.Time;
				}
				catch(Exception)
				{
					return 0;
				}
			}
		}

		public double Position
		{
			get
			{
				return this.nativeVlc.Position;
			}
		}

		public void MoveToPosition(TrackPosition newTrackPosition)
		{
			if((newTrackPosition.position >= 0.0d) && (newTrackPosition.position < 1.0d))
			{
				this.nativeVlc.Position = newTrackPosition.position;
				if(this.IsPaused)
				{
					this.usingPausedPosition = true;
					this.pausedTime = newTrackPosition.time;
					this.pausedPosition = newTrackPosition.position;
					this.shuttleSeconds = 0;
				}
			}
		}

		private TrackPosition CalculateShuttle(int origTime, double origPosition, int offsetSeconds)
		{
			int newTime = origTime + offsetSeconds;

			double positionPerTime;
			if(origPosition > .5d)
			{
				positionPerTime = origPosition / Convert.ToDouble(origTime);
			}
			else
			{
				positionPerTime = (1.0d - origPosition) / 
					Convert.ToDouble(this.nativeVlc.Length - origTime);
			}
			double newPosition = origPosition + Convert.ToDouble(offsetSeconds) * positionPerTime;

			Debug.WriteLine(String.Format("CalculateShuttle time={0} pos={1}", newTime, newPosition));

			return new TrackPosition(newTime, newPosition);
		}

		public TrackPosition Shuttle(int offsetSeconds)
		{
			if(!this.IsPaused)
			{
				TrackPosition newPosition = CalculateShuttle(this.nativeVlc.Time, this.nativeVlc.Position,
					offsetSeconds);
				if(this.useMpegVbrOffset)
				{
					this.nativeVlc.Position = newPosition.position;
				}
				else
				{
					this.nativeVlc.Time = newPosition.time;
				}
				return newPosition;
			}

			if(!this.usingPausedPosition)
			{
				this.usingPausedPosition = true;
				this.pausedTime = this.nativeVlc.Time;
				this.pausedPosition = this.nativeVlc.Position;
				this.shuttleSeconds = 0;
			}

			this.shuttleSeconds += offsetSeconds;
			return CalculateShuttle(this.pausedTime, this.pausedPosition, this.shuttleSeconds);
		}

		public int Volume
		{
			get
			{
				return this.nativeVlc.Volume;
			}
			set
			{
				this.nativeVlc.Volume = value;
			}
		}

		const int MinRate = -2;
		const int MaxRate = 2;
		const int NormalRate = 0;

		public void GetRates(out int minRate, out int maxRate, out int normalRate)
		{
			minRate = MinRate;
			maxRate = MaxRate;
			normalRate = NormalRate;
		}

		public int Rate
		{
			get
			{
				// 1000 is normal, 2000 is half speed, 500 is double speed, etc.
				int bigRate = this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "rate", 1000);
				if(bigRate > 3000)
				{
					return -2;
				}
				if(bigRate > 1500)
				{
					return -1;
				}
				if(bigRate > 750)
				{
					return 0;
				}
				if(bigRate > 400)
				{
					return 1;
				}
				return 2;
			}
			set
			{
				int newRate = NormalRate;
				switch(value)
				{
				case 2:
					newRate = 250;
					break;
				case 1:
					newRate = 500;
					break;
				case 0:
					newRate = 1000;
					break;
				case -1:
					newRate = 2000;
					break;
				case -2:
					newRate = 4000;
					break;
				default:
					throw new ArgumentOutOfRangeException();
				}
				this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "rate", newRate);
			}
		}

		public int Length
		{
			get
			{
				try
				{
					return this.nativeVlc.Length;
				}
				catch(Exception)
				{
					return -1;
				}
			}
			set
			{
				this.nativeVlc.SetArtificialLength(value);
			}
		}

		public double TimeScaling
		{
			get { return this.nativeVlc.TimeScaling; }
			set { this.nativeVlc.TimeScaling = value; }
		}

		public PlayerState State
		{
			get
			{
				int state = this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, 
					"state", (int)InputState.INIT_S);
				switch((InputState)state)
				{
				case InputState.PAUSE_S:
					return PlayerState.Paused;
				case InputState.PLAYING_S:
					return PlayerState.Playing;
				default:
					return PlayerState.None;
				}
			}
		}

		public bool IsPlaying { get { return this.State == PlayerState.Playing; } }

		public bool IsPaused { get { return this.State == PlayerState.Paused; } }

		public bool IsMute { get { return (this.nativeVlc.Volume == 0); } }

		public void ToggleMute()
		{
			this.nativeVlc.ToggleVolumeMute();
		}

		public void DeinterlaceModes(out String[] choices, out String[] choiceText)
		{
			this.nativeVlc.GetVlcVariableChoiceList(ObjectType.VLC_OBJECT_VOUT,
				"deinterlace", out choices, out choiceText);
		}

		public String DeinterlaceMode
		{
			get
			{
				return this.nativeVlc.GetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, "deinterlace", String.Empty);
			}
			set
			{
				this.nativeVlc.SetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, "deinterlace", value);
			}
		}

		public void AspectRatios(out String[] choices, out String[] choiceText)
		{
			this.nativeVlc.GetVlcVariableChoiceList(ObjectType.VLC_OBJECT_VOUT,
				"aspect-ratio", out choices, out choiceText);
		}

		public String AspectRatio
		{
			get
			{
				return this.nativeVlc.GetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, "aspect-ratio", String.Empty);
			}
			set
			{
				this.nativeVlc.SetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, "aspect-ratio", value);
			}
		}

		public void CropModes(out String[] choices, out String[] choiceText)
		{
			this.nativeVlc.GetVlcVariableChoiceList(ObjectType.VLC_OBJECT_VOUT,
				"crop", out choices, out choiceText);
		}

		public String CropMode 
		{
			get
			{
				return this.nativeVlc.GetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, "crop", String.Empty);
			}
			set
			{
				this.nativeVlc.SetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, "crop", value);
			}
		}

		public int CroppingLeft
		{
			get
			{
				if(this.useVlcCrop)
				{
					return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-left", 0);
				}
				else
				{
					return this.cropLeft;
				}
			}
			set
			{
				if(this.useVlcCrop)
				{
					this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-left", value);
				}
				else
				{
					this.cropLeft = value;
					ComputeCrop();
				}
			}
		}

		public int CroppingRight
		{
			get
			{
				if(this.useVlcCrop)
				{
					return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-right", 0);
				}
				else
				{
					return this.cropRight;
				}
			}
			set
			{
				if(this.useVlcCrop)
				{
					this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-right", value);
				}
				else
				{
					this.cropRight = value;
					ComputeCrop();
				}
			}
		}

		public int CroppingTop
		{
			get
			{
				if(this.useVlcCrop)
				{
					return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-top", 0);
				}
				else
				{
					return this.cropTop;
				}
			}
			set
			{
				if(this.useVlcCrop)
				{
					this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-top", value);
				}
				else
				{
					this.cropTop = value;
					ComputeCrop();
				}
			}
		}

		public int CroppingBottom
		{
			get
			{
				if(this.useVlcCrop)
				{
					return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-bottom", 0);
				}
				else
				{
					return this.cropBottom;
				}
			}
			set
			{
				if(this.useVlcCrop)
				{
					this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_VOUT, "crop-bottom", value);
				}
				else
				{
					this.cropBottom = value;
					ComputeCrop();
				}
			}
		}

		public void AudioTracks(out int[] trackIds, out String[] trackNames)
		{
			this.nativeVlc.GetVlcVariableChoiceList(ObjectType.VLC_OBJECT_INPUT,
				"audio-es", out trackIds, out trackNames);
		}

		public int AudioTrack
		{
			get
			{
				return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "audio-es", -1);
			}
			set
			{
				this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "audio-es", value);
			}
		}

		public void SubTitleTracks(out int[] trackIds, out String[] trackNames)
		{
			this.nativeVlc.GetVlcVariableChoiceList(ObjectType.VLC_OBJECT_INPUT,
				"spu-es", out trackIds, out trackNames);
		}

		public int SubTitleTrack
		{
			get
			{
				return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "spu-es", -1);
			}
			set
			{
				this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "spu-es", value);
			}
		}

		public void Programs(out int[] trackIds, out String[] trackNames)
		{
			this.nativeVlc.GetVlcVariableChoiceList(ObjectType.VLC_OBJECT_INPUT,
				"program", out trackIds, out trackNames);
		}

		public int Program
		{
			get
			{
				return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "program", -1);
			}
			set
			{
				this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "program", value);
			}
		}

		public void RotateCropModes()
		{
			this.nativeVlc.PressKey("key-crop");
		}

		public int AudioDelay
		{
			get
			{
				long delay = this.nativeVlc.GetVlcObjectLong(ObjectType.VLC_OBJECT_INPUT, "audio-delay", 0L);
				return Convert.ToInt32(delay / 1000L);

			}
			set
			{
				long delay = Convert.ToInt64(value) * 1000L;
				this.nativeVlc.SetVlcObjectLong(ObjectType.VLC_OBJECT_INPUT, "audio-delay", delay);
			}
		}

		public int SubTitleDelay
		{
			get
			{
				long delay = this.nativeVlc.GetVlcObjectLong(ObjectType.VLC_OBJECT_INPUT, "spu-delay", 0L);
				return Convert.ToInt32(delay / 1000L);

			}
			set
			{
				long delay = Convert.ToInt64(value) * 1000L;
				this.nativeVlc.SetVlcObjectLong(ObjectType.VLC_OBJECT_INPUT, "spu-delay", delay);
			}
		}

		public int ChapterCount
		{
			get
			{
				int[] chapterIds;
				String[] chapterText;
				this.nativeVlc.GetVlcVariableChoiceList(ObjectType.VLC_OBJECT_INPUT,
					"chapter", out chapterIds, out chapterText);
				return (chapterIds.Length > 0) ? chapterIds.Length - 1 : 0;
			}
		}

		public int Chapter
		{
			get
			{
				return this.nativeVlc.GetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "chapter", -1);
			}
			set
			{
				this.nativeVlc.SetVlcObjectInt(ObjectType.VLC_OBJECT_INPUT, "chapter", value);
			}
		}

		private void RepositionAfterPause()
		{
			if(this.usingPausedPosition && (this.shuttleSeconds != 0))
			{
				TrackPosition newPosition = CalculateShuttle(this.pausedTime, this.pausedPosition,
					this.shuttleSeconds);
				if(this.useMpegVbrOffset)
				{
					this.nativeVlc.Position = newPosition.position;
				}
				else
				{
					this.nativeVlc.Time = newPosition.time;
				}
			}
			this.usingPausedPosition = false;
		}

		public void Play()
		{
			this.isPaused = false;
			this.nativeVlc.Play();
			RepositionAfterPause();
		}

		public void ClearPlayList()
		{
			this.usingPausedPosition = false;
			//Debug.WriteLine("ClearPlayList");
			this.nativeVlc.PlaylistClear();
		}

		public int AddToPlayList(String fileName, String title, String[] options)
		{
			this.usingPausedPosition = false;
			int index = 0;
			this.nativeVlc.AddTarget(fileName, options, ref index);
			Debug.WriteLine("Added to Playlist " + fileName);
			Debug.WriteLine("index = " + index.ToString());
			return index;
		}

		public void PlayItem(int itemId)
		{
			this.usingPausedPosition = false;
			this.isPaused = false;

			int currentIndex = this.nativeVlc.PlaylistIndex;
			Debug.WriteLine("PlayItem index = " + itemId.ToString(), " currentIndex = " + currentIndex.ToString());
			if(currentIndex < 0)
			{
				this.nativeVlc.Play();
			}
			else
			{
				//this.nativeVlc.PlaylistPrevious();
				this.nativeVlc.Play(itemId);
			}
		}

		public void Stop()
		{
			this.usingPausedPosition = false;
			this.nativeVlc.Stop();
			this.isPaused = false;
		}

		public void TogglePause()
		{
			bool wasPaused = this.IsPaused;
			this.nativeVlc.Pause();
			if(wasPaused)
			{
				RepositionAfterPause();
			}
			this.isPaused = !wasPaused;
		}

		public void RotateSubtitles()
		{
			this.nativeVlc.PressKey("key-subtitle-track");
		}

		public void RotateAudioTrack()
		{
			this.nativeVlc.PressKey("key-audio-track");
		}

		public void RotateDeinterlaceMode()
		{
			this.nativeVlc.PressKey("key-deinterlace");
		}

		public void RotateAspectRatio()
		{
			this.nativeVlc.PressKey("key-aspect-ratio");
		}

		public void CropTop()
		{
			//this.nativeVlc.PressKey("key-crop-top");
			this.CroppingTop = this.CroppingTop + 1;
		}

		public void UnCropTop()
		{
			//this.nativeVlc.PressKey("key-uncrop-top");
			int crop = this.CroppingTop - 1;
			if(crop >= 0)
			{
				this.CroppingTop = crop;
			}
		}

		public void CropBottom()
		{
			//this.nativeVlc.PressKey("key-crop-bottom");
			this.CroppingBottom = this.CroppingBottom + 1;
		}

		public void UnCropBottom()
		{
			//this.nativeVlc.PressKey("key-uncrop-bottom");
			int crop = this.CroppingBottom - 1;
			if(crop >= 0)
			{
				this.CroppingBottom = crop;
			}
		}

		public void CropLeft()
		{
			//this.nativeVlc.PressKey("key-crop-left");
			this.CroppingLeft = this.CroppingLeft + 1;
		}

		public void UnCropLeft()
		{
			//this.nativeVlc.PressKey("key-uncrop-left");
			int crop = this.CroppingLeft - 1;
			if(crop >= 0)
			{
				this.CroppingLeft = crop;
			}
		}

		public void CropRight()
		{
			//this.nativeVlc.PressKey("key-crop-right");
			this.CroppingRight = this.CroppingRight + 1;
		}

		public void UnCropRight()
		{
			//this.nativeVlc.PressKey("key-uncrop-right");
			int crop = this.CroppingRight - 1;
			if(crop >= 0)
			{
				this.CroppingRight = crop;
			}
		}

		public bool UseMpegVbrOffset
		{
			get { return this.useMpegVbrOffset; }
			set { this.useMpegVbrOffset = value; }
		}

		public void NextDvdTrack()
		{
			this.nativeVlc.PressKey("key-title-next");
		}

		public void PreviousDvdTrack()
		{
			this.nativeVlc.PressKey("key-title-prev");
		}

		public void NextDvdChapter()
		{
			this.nativeVlc.PressKey("key-chapter-next");
		}

		public void PreviousDvdChapter()
		{
			this.nativeVlc.PressKey("key-chapter-prev");
		}

		private void VlcUserControl_Resize(object sender, EventArgs e)
		{
			if(!ComputeCrop())
			{
				this.innerVlc.Bounds = this.ClientRectangle;
			}
		}
	}
}