Skip to content

Commit

Permalink
updated BrowserHost to work with Remotes and use MediaPortal Keybindi…
Browse files Browse the repository at this point in the history
…ngs (thx Jason and Brownard)
  • Loading branch information
offbyoneBB committed Jan 30, 2014
1 parent 57bfeb5 commit 4b89706
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 105 deletions.
5 changes: 4 additions & 1 deletion OnlineVideos.MediaPortal1/OnlineVideos.MediaPortal1.csproj
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down Expand Up @@ -66,6 +66,9 @@
<HintPath>$(ProgramFiles)\Team MediaPortal\MediaPortal\log4net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RemotePlugins">
<HintPath>$(ProgramFiles)\Team MediaPortal\MediaPortal\RemotePlugins.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Design" />
Expand Down
11 changes: 6 additions & 5 deletions OnlineVideos.MediaPortal1/Player/WebBrowserVideoPlayer.cs
Expand Up @@ -7,6 +7,7 @@
using MediaPortal.Player;
using OnlineVideos.Helpers;
using OnlineVideos.Sites;
using MediaPortal.InputDevices;

namespace OnlineVideos.MediaPortal1.Player
{
Expand Down Expand Up @@ -86,12 +87,11 @@ public override bool Play(string strFile)
// Hide MediaPortal
if (_browserProcess.Start())
{
ProcessHelper.SetForeground(_browserProcess.MainWindowHandle);
SuspendMP(true);
Redirect(_browserProcess.StandardError);
}

ProcessHelper.SetForeground(_browserProcess.MainWindowHandle);


return true;
}

Expand Down Expand Up @@ -157,13 +157,14 @@ void SuspendMP(bool suspend)

if (suspend) //suspend and hide MediaPortal
{
//InputDevices.Stop();
InputDevices.Stop(); //stop input devices so they don't interfere when the browser player starts listening

// hide mediaportal and suspend rendering
GUIGraphicsContext.BlankScreen = true;
GUIGraphicsContext.form.Hide();
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.SUSPENDING;
// Hide the window
ProcessHelper.SetWindowState("mediaportal", ProcessHelper.WINDOW_STATE.SW_MINIMIZE);
_mpWindowHandle = ProcessHelper.SetWindowState("mediaportal", ProcessHelper.WINDOW_STATE.SW_HIDE);
_mpWindowHidden = true;
}
Expand All @@ -172,7 +173,7 @@ void SuspendMP(bool suspend)

// Restore the window
ProcessHelper.RestoreWindow(_mpWindowHandle);
//InputDevices.Init();
InputDevices.Init();

// Resume Mediaportal rendering
GUIGraphicsContext.BlankScreen = false;
Expand Down
11 changes: 4 additions & 7 deletions OnlineVideos.WebAutomation.BrowserHost/App.config
@@ -1,9 +1,6 @@
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="PlayKey" value="P"/>
<add key="PauseKey" value="SPACE"/>
<add key="StopKey" value="B"/>
<add key="DebugMode" value="false"/>
</appSettings>
</configuration>
<appSettings>
<add key="DebugMode" value="false" />
</appSettings>
</configuration>
147 changes: 109 additions & 38 deletions OnlineVideos.WebAutomation.BrowserHost/BrowserForm.cs
Expand Up @@ -13,11 +13,23 @@
using System.Diagnostics;
using System.Configuration;
using OnlineVideos.Sites.Base;
using MediaPortal.GUI.Library;
using MediaPortal.InputDevices;
using Action = MediaPortal.GUI.Library.Action;

namespace OnlineVideos.Sites.WebAutomation.BrowserHost
{
public partial class BrowserForm : Form
{
/// <summary>
/// Which was the last of the 2 events fired between play/pause. We'll use this to handle the media key as that's a single play/pause button.
/// </summary>
private enum PlayPauseToggle
{
Play,
Pause
}

public bool ForceClose { get; private set; }

private string _connectorType;
Expand All @@ -26,15 +38,13 @@ public partial class BrowserForm : Form
private string _password;
private BrowserUtilConnector _connector;

private Keys? _playKey;
private Keys? _pauseKey;
private Keys? _stopKey;

private bool _debugMode = false; // Allow for the form to be resized/lose focus in debug mode

private Keys _lastKeyPressed;
private int _lastKeyPressed;
private DateTime _lastKeyPressedTime;

private PlayPauseToggle _lastPlayPauseState = PlayPauseToggle.Play;

/// <summary>
/// This form is used to play a video - we use separate exe as there is no reliable way to dispose of the web browser between sessions
/// and this seemed to cause issues when playing multiple videos
Expand All @@ -50,15 +60,20 @@ public BrowserForm(string connectorType, string videoInfo, string userName, stri
_videoInfo = videoInfo;
_userName = userName;
_password = password;
_playKey = GetKeyForAction("PlayKey");
_pauseKey = GetKeyForAction("PauseKey");
_stopKey = GetKeyForAction("StopKey");
_debugMode = false;

var configValue = ConfigurationManager.AppSettings["DebugMode"];
if (!string.IsNullOrEmpty(configValue) && configValue.ToUpper() == "TRUE")
_debugMode = true;

//Load keyboard mappings
ActionTranslator.Load();

//Load remote mappings
InputDevices.Init();

//Some remotes will fire this event directly
GUIGraphicsContext.OnNewAction += OnNewAction;
}

/// <summary>
Expand Down Expand Up @@ -97,7 +112,6 @@ private void BrowserForm_Load(object sender, EventArgs e)
}
catch (Exception ex)
{
//MediaPortal.Common.Utils.Logger.CommonLogger.Instance.Error(MediaPortal.Common.Utils.Logger.CommonLogType.Error, ex);
Log.Error(ex);
ForceQuit();
}
Expand All @@ -119,7 +133,7 @@ public bool ForceQuitting()
/// <param name="e"></param>
private void BrowserForm_KeyDown(object sender, KeyEventArgs e)
{
HandleKeyPress(e.KeyCode);
HandleKeyPress(e.KeyValue);
}

/// <summary>
Expand All @@ -129,28 +143,99 @@ private void BrowserForm_KeyDown(object sender, KeyEventArgs e)
/// <param name="e"></param>
private void webBrowser_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
HandleKeyPress(e.KeyCode);
HandleKeyPress(e.KeyValue);
}

//Used to pass messages to remotes. Lifted from MediaPortal.cs
protected override void WndProc(ref Message msg)
{
Action action;
char key;
Keys keyCode;
if (InputDevices.WndProc(ref msg, out action, out key, out keyCode))
{
//If remote doesn't fire event directly we manually fire it
if (action != null && action.wID != Action.ActionType.ACTION_INVALID)
{
OnNewAction(action);
}

if (keyCode != Keys.A)
{
var ke = new KeyEventArgs(keyCode);
OnKeyDown(ke);
}
return; // abort WndProc()
}
base.WndProc(ref msg);
}

/// <summary>
/// Event sink for key press
/// </summary>
/// <param name="keyPressed"></param>
private void HandleKeyPress(Keys keyPressed)
private void HandleKeyPress(int keyPressed)
{
// Ignore duplicate presses within 1 second (happens because sometimes both the browser and form fire the event)
if (_lastKeyPressed == keyPressed && _lastKeyPressedTime.AddSeconds(1) > DateTime.Now) return;
// Ignore duplicate presses within 0.5 seconds (happens because sometimes both the browser and form fire the event)
if (_lastKeyPressed == keyPressed && _lastKeyPressedTime.AddSeconds(0.5) > DateTime.Now) return;
_lastKeyPressed = keyPressed;
_lastKeyPressedTime = DateTime.Now;

if (keyPressed == Keys.Escape)
ForceQuit();
if (_playKey.HasValue && keyPressed == _playKey)
_connector.Play();
if (_stopKey.HasValue && keyPressed == _stopKey)
ForceQuit();
if (_pauseKey.HasValue && keyPressed == _pauseKey)
_connector.Pause();
Action action = new Action();
//Try and get corresponding Action from key.
//Some actions are mapped to KeyDown others to KeyPressed, try and handle both
if (ActionTranslator.GetAction(-1, new Key(0, keyPressed), ref action))
{
OnNewAction(action);
}
else
{
//See if it's mapped to KeyPressed instead
if (keyPressed >= (int)Keys.A && keyPressed <= (int)Keys.Z)
keyPressed += 32; //convert to char code
if (ActionTranslator.GetAction(-1, new Key(keyPressed, 0), ref action))
OnNewAction(action);
else
{
// Handle the mesdia keys (toggle the play/pause as they are one button in this instance)
switch (keyPressed)
{
case (int)Keys.MediaPlayPause:
if (_lastPlayPauseState == PlayPauseToggle.Play)
OnNewAction(new Action(Action.ActionType.ACTION_PAUSE, 0, 0));
else
OnNewAction(new Action(Action.ActionType.ACTION_PLAY, 0, 0));
break;
case (int)Keys.MediaStop:
OnNewAction(new Action(Action.ActionType.ACTION_STOP, 0, 0));
break;
}
}
}
}

/// <summary>
/// Handle actions
/// </summary>
/// <param name="action"></param>
void OnNewAction(Action action)
{
switch (action.wID)
{
case Action.ActionType.ACTION_PLAY:
case Action.ActionType.ACTION_MUSIC_PLAY:
_connector.Play();
_lastPlayPauseState = PlayPauseToggle.Play;
break;
case Action.ActionType.ACTION_PAUSE:
_connector.Pause();
_lastPlayPauseState = PlayPauseToggle.Pause;
break;
case Action.ActionType.ACTION_STOP:
case Action.ActionType.ACTION_PREVIOUS_MENU:
ForceQuit();
break;
}
}

/// <summary>
Expand All @@ -174,22 +259,8 @@ private void ForceQuit()
private void tmrKeepOnTop_Tick(object sender, EventArgs e)
{
ProcessHelper.SetForeground(Process.GetCurrentProcess().MainWindowHandle);
}

/// <summary>
/// Lookup the key code for the specified action name
/// </summary>
/// <param name="actionName"></param>
/// <returns></returns>
private Keys? GetKeyForAction(string actionName)
{
var configValue = ConfigurationManager.AppSettings[actionName];
if (string.IsNullOrEmpty(configValue)) return null;

if (System.Enum.GetNames(typeof(Keys)).Where(x => x.ToUpper() == configValue).Count() > 0)
return (Keys)System.Enum.Parse(typeof(Keys), configValue, true);

return null;
this.Activate();
this.Focus();
}

/// <summary>
Expand Down
Expand Up @@ -55,6 +55,14 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Core">
<HintPath>$(ProgramFiles)\Team MediaPortal\MediaPortal\Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RemotePlugins">
<HintPath>$(ProgramFiles)\Team MediaPortal\MediaPortal\RemotePlugins.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
Expand Down Expand Up @@ -111,15 +119,15 @@
<ProjectReference Include="..\OnlineVideos\OnlineVideos.csproj">
<Project>{e0d9d390-cdd6-4b98-86f3-6eb04a958882}</Project>
<Name>OnlineVideos</Name>
<Private>True</Private>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="build.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy "$(TargetPath)" "%25programfiles(x86)%25\Team MediaPortal\MediaPortal\plugins\Windows\OnlineVideos" /Y /E /I
xcopy "$(TargetPath).config" "%25programfiles(x86)%25\Team MediaPortal\MediaPortal\plugins\Windows\OnlineVideos" /Y /E /I</PostBuildEvent>
<PostBuildEvent>xcopy "$(TargetPath)" "%25programfiles(x86)%25\Team MediaPortal\MediaPortal\plugins\windows\onlinevideos\" /Y /E /I
xcopy "$(TargetPath).config" "%25programfiles(x86)%25\Team MediaPortal\MediaPortal\plugins\windows\onlinevideos\" /Y /E /I</PostBuildEvent>
</PropertyGroup>
<!-- 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.
Expand Down
3 changes: 3 additions & 0 deletions OnlineVideos.WebAutomation.BrowserHost/Program.cs
Expand Up @@ -32,6 +32,9 @@ static void Main(string[] args)
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

// Set the BaseDirectory of the app domain to the mediaportal root, otherwise the inputdevices can't initialise (due to Configuration.Config using this path)
// The other option is to run this exe in the root of the media portal dir, which I wasn't too keen on
currentDomain.SetData("APPBASE", _assemblyPath);

var result = args[2];
var host = new BrowserHost();
Expand Down

0 comments on commit 4b89706

Please sign in to comment.