1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-04-13 18:15:48 +02:00

Implement video player in TweetDeck

This commit is contained in:
chylex 2017-08-11 11:56:19 +02:00
parent 54d12686af
commit 8b676fe6ce
6 changed files with 126 additions and 11 deletions
Core
Resources/Scripts
TweetDuck.csproj
video/TweetDuck.Video

View File

@ -114,6 +114,10 @@ public void ScreenshotTweet(string html, int width, int height){
form.InvokeAsyncSafe(() => form.OnTweetScreenshotReady(html, width, height));
}
public void PlayVideo(string url){
form.InvokeAsyncSafe(() => form.PlayVideo(url));
}
public void FixClipboard(){
form.InvokeAsyncSafe(WindowsUtils.ClipboardStripHtmlStyles);
}

View File

@ -12,6 +12,7 @@
using TweetDuck.Core.Notification;
using TweetDuck.Core.Notification.Screenshot;
using TweetDuck.Core.Other;
using TweetDuck.Core.Other.Media;
using TweetDuck.Core.Other.Settings;
using TweetDuck.Core.Utils;
using TweetDuck.Plugins;
@ -58,6 +59,7 @@ public bool IsWaiting{
private TweetScreenshotManager notificationScreenshotManager;
private SoundNotification soundNotification;
private VideoPlayer videoPlayer;
public FormBrowser(PluginManager pluginManager, UpdaterSettings updaterSettings){
InitializeComponent();
@ -506,6 +508,19 @@ public void PlayNotificationSound(){
soundNotification.Play(Config.NotificationSoundPath);
}
public void PlayVideo(string url){
if (videoPlayer == null){
videoPlayer = new VideoPlayer(this);
}
if (!string.IsNullOrEmpty(url)){
videoPlayer.Launch(url);
}
else{
videoPlayer.Close();
}
}
public void OnTweetScreenshotReady(string html, int width, int height){
if (notificationScreenshotManager == null){
notificationScreenshotManager = new TweetScreenshotManager(this, plugins);

View File

@ -0,0 +1,70 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
namespace TweetDuck.Core.Other.Media{
class VideoPlayer{
private readonly string PlayerExe = Path.Combine(Program.ProgramPath, "TweetDuck.Video.exe");
private readonly Form owner;
private Process currentProcess;
public VideoPlayer(Form owner){
this.owner = owner;
}
public void Launch(string url){
Close();
try{
if ((currentProcess = Process.Start(new ProcessStartInfo{
FileName = PlayerExe,
Arguments = $"{owner.Handle} \"{url}\"",
UseShellExecute = false,
RedirectStandardOutput = true
})) != null){
currentProcess.EnableRaisingEvents = true;
currentProcess.Exited += process_Exited;
#if DEBUG
currentProcess.BeginOutputReadLine();
currentProcess.OutputDataReceived += (sender, args) => Debug.WriteLine("VideoPlayer: "+args.Data);
#endif
}
}catch(Exception e){
Program.Reporter.HandleException("Video Playback Error", "Error launching video player.", true, e);
}
}
public void Close(){
if (currentProcess != null){
currentProcess.Exited -= process_Exited;
try{
currentProcess.Kill();
}catch{
// kill me instead then
}
currentProcess.Dispose();
currentProcess = null;
}
}
private void process_Exited(object sender, EventArgs e){
switch(currentProcess.ExitCode){
case 2: // CODE_LAUNCH_FAIL
// TODO
break;
case 3: // CODE_MEDIA_ERROR
// TODO
break;
}
currentProcess.Dispose();
currentProcess = null;
}
}
}

View File

@ -789,20 +789,52 @@
}
//
// Block: Setup unsupported video element hook.
// Block: Setup video player hooks.
//
(function(){
var cancelModal = false;
var playVideo = function(url){
$('<div class="ovl" style="display:block"></div>').click(function(){
$TD.playVideo(null);
$(this).remove();
}).appendTo(app);
$TD.playVideo(url);
};
app.delegate(".js-gif-play", "click", function(e){
let src = $(this).closest(".js-media-gif-container").find("video").attr("src");
if (src){
playVideo(src);
}
else{
let parent = $(e.target).closest(".js-tweet").first();
let link = (parent.hasClass("tweet-detail") ? parent.find("a[rel='url']") : parent.find("time").first().children("a")).first();
$TD.openBrowser(link.attr("href"));
}
e.stopPropagation();
});
if (!ensurePropertyExists(TD, "components", "MediaGallery", "prototype", "_loadTweet") ||
!ensurePropertyExists(TD, "components", "BaseModal", "prototype", "setAndShowContainer") ||
!ensurePropertyExists(TD, "ui", "Column", "prototype", "playGifIfNotManuallyPaused"))return;
var cancelModal = false;
TD.components.MediaGallery.prototype._loadTweet = appendToFunction(TD.components.MediaGallery.prototype._loadTweet, function(){
let media = this.chirp.getMedia().find(media => media.mediaId === this.clickedMediaEntityId);
if (media && media.isVideo && media.service !== "youtube"){
$TD.openBrowser(this.clickedLink);
let data = media.chooseVideoVariant();
if (data.content_type === "video/mp4"){
playVideo(data.url);
}
else{
$TD.openBrowser(this.clickedLink);
}
cancelModal = true;
}
});
@ -816,14 +848,6 @@
TD.ui.Column.prototype.playGifIfNotManuallyPaused = function(){};
TD.mustaches["status/media_thumb.mustache"] = TD.mustaches["status/media_thumb.mustache"].replace("is-gif", "is-gif is-paused");
app.delegate(".js-gif-play", "click", function(e){
let parent = $(e.target).closest(".js-tweet").first();
let link = (parent.hasClass("tweet-detail") ? parent.find("a[rel='url']") : parent.find("time").first().children("a")).first();
$TD.openBrowser(link.attr("href"));
e.stopPropagation();
});
})();
//

View File

@ -142,6 +142,7 @@
<Compile Include="Core\Other\FormPlugins.Designer.cs">
<DependentUpon>FormPlugins.cs</DependentUpon>
</Compile>
<Compile Include="Core\Other\Media\VideoPlayer.cs" />
<Compile Include="Core\Other\Settings\Dialogs\DialogSettingsCSS.cs">
<SubType>Form</SubType>
</Compile>

View File

@ -4,6 +4,7 @@
namespace TweetDuck.Video{
static class Program{
// referenced in VideoPlayer
public const int CODE_INVALID_ARGS = 1;
public const int CODE_LAUNCH_FAIL = 2;
public const int CODE_MEDIA_ERROR = 3;