Jump to content

Get streams/Info - Kill process


bakes82

Recommended Posts

bakes82

@chef Do you know how to get the current streams from the plugin API?  I want to bang out this plugin real fast to kill the stream if it meets some conditions.  I think it should be fairly simple, run it as a 5min scheduled task.

Link to comment
Share on other sites

1 hour ago, bakes82 said:

@chef Do you know how to get the current streams from the plugin API?  I want to bang out this plugin real fast to kill the stream if it meets some conditions.  I think it should be fairly simple, run it as a 5min scheduled task.

Is it under SessionManager? 

Link to comment
Share on other sites

Just now, bakes82 said:

Idk aren’t you the plug-in wizard lol?  I figured I ask you and you be like shablam magic code.

Lol. I'm not sure why, but my code brain has been completely stifled from lockdown. 🤦‍♂️

I think the work flow would be, 

SessionManager.Sessions

Each session NowPlayingItem (which is baseItem)

Check stream quality, then use remote command  to stop the stream.

I might have a snippet. One second, I'll check.  I'm definitely failing. {cringe}

 

Link to comment
Share on other sites

bakes82

@Luke Where do I get a set of valid commands to send to comands end point?  Im trying to stop a stream, it doesnt look like that is built in?  Or can I just not kill my own streams from the dashboard?

 

await SessionManager.SendGeneralCommand(sessionManagerSession.Id, sessionManagerSession.Id,
    new GeneralCommand() { }, new CancellationToken());
Link to comment
Share on other sites

bakes82
5 minutes ago, Luke said:

You would just use the stop command. I would take a look at this:

https://github.com/MediaBrowser/Emby/wiki/Remote-control

This look right to you?  (Obviously I can do other checks for 4k like width/height)  But on the SendPlayStateCommand there is a "controllingSesssionId" do I need to set that to something other than the ID of the stream of the user?  its also a variable on the PlayStateRequest.

foreach (var sessionManagerSession in SessionManager.Sessions)
{
    foreach (var mediaStream in sessionManagerSession.NowPlayingItem.MediaStreams)
    {
        if (mediaStream.DisplayTitle.ToLower().Contains("4k"))
        {
            await SessionManager.SendMessageToUserDeviceSessions(sessionManagerSession.DeviceId,
                sessionManagerSession.UserName, $"Your stream is transcoding: {string.Join(", ", sessionManagerSession.TranscodingInfo.TranscodeReasons)}", new CancellationToken());

            await SessionManager.SendPlaystateCommand(sessionManagerSession.Id, sessionManagerSession.Id,
                new PlaystateRequest(){Command = PlaystateCommand.Stop}, new CancellationToken());
        }
    }
}
Link to comment
Share on other sites

55 minutes ago, bakes82 said:

This look right to you?  (Obviously I can do other checks for 4k like width/height)  But on the SendPlayStateCommand there is a "controllingSesssionId" do I need to set that to something other than the ID of the stream of the user?  its also a variable on the PlayStateRequest.


foreach (var sessionManagerSession in SessionManager.Sessions)
{
    foreach (var mediaStream in sessionManagerSession.NowPlayingItem.MediaStreams)
    {
        if (mediaStream.DisplayTitle.ToLower().Contains("4k"))
        {
            await SessionManager.SendMessageToUserDeviceSessions(sessionManagerSession.DeviceId,
                sessionManagerSession.UserName, $"Your stream is transcoding: {string.Join(", ", sessionManagerSession.TranscodingInfo.TranscodeReasons)}", new CancellationToken());

            await SessionManager.SendPlaystateCommand(sessionManagerSession.Id, sessionManagerSession.Id,
                new PlaystateRequest(){Command = PlaystateCommand.Stop}, new CancellationToken());
        }
    }
}

This looks correct, but I think you can also set the "controllingSession.Id" to null if you want.

I have found, in certain instances, sending session commands from from the same controlling session as the session to control, will have unexpected outcomes. Not always... but sometimes. 

 

Also, I have found that grabbing the Admin user for the Controlling UserId in the Playstate command, might be best.

new PlaystateRequest(){ Command = PlaystateCommand.Stop, ControllingUserId = UserManager.Users.FirstOrDefault(user => user.Policy.IsAdministrator).Id.ToString()}

 

I'm sure it doesn't really matter who controls the playstate command... but... if events propagate for Admin Users only (in the future), this might be a good idea... 

Edited by chef
Link to comment
Share on other sites

bakes82
27 minutes ago, chef said:

This looks correct, but I think you can also set the "controllingSession.Id" to null if you want.

I have found, in certain instances, sending session commands from from the same controlling session as the session to control, will have unexpected outcomes. Not always... but sometimes. 

 

Also, I have found that grabbing the Admin user for the Controlling UserId in the Playstate command, might be best.


new PlaystateRequest(){ Command = PlaystateCommand.Stop, ControllingUserId = UserManager.Users.FirstOrDefault(user => user.Policy.IsAdministrator).Id.ToString()}

 

I'm sure it doesn't really matter who controls the playstate command... but... if events propagate for Admin Users only (in the future), this might be a good idea... 

Yup that was it.  Is there a way to prompt a okay box to a user?  IE: Do you want to continue watching, yes/no.  (This is more for another feature hahaha)

 

Logger.Info($"Count of streams {SessionManager.Sessions.Count()}");
foreach (var sessionManagerSession in SessionManager.Sessions)
{
    if (sessionManagerSession?.PlayState.PlayMethod == PlayMethod.Transcode && sessionManagerSession?.NowPlayingItem.Height == 2160 && sessionManagerSession?.NowPlayingItem.Width == 3840)
    {
        Logger.Info("Inside Kill Loop");
        Logger.Info($"Device Id {sessionManagerSession.DeviceId} - UserName {sessionManagerSession.UserName} - ID {sessionManagerSession.Id}");

        await SessionManager.SendPlaystateCommand(null, sessionManagerSession.Id,
            new PlaystateRequest {Command = PlaystateCommand.Stop, ControllingUserId = UserManager.Users.FirstOrDefault(user => user.Policy.IsAdministrator)?.Id.ToString()}, new CancellationToken());
        
        await SessionManager.SendMessageCommand(null, sessionManagerSession.Id, new MessageCommand(){Header = "Stream Transcoding", Text = "Stream stopped because of transcoding.  Reason(s): "+ string.Join(", ", sessionManagerSession.TranscodingInfo.TranscodeReasons), TimeoutMs = 10000},
            new CancellationToken());
    }
}

 

image.png.7d5a5839d9ffb4358c5808c02848221f.png

Link to comment
Share on other sites

			await SessionManager.SendMessageCommand(session.Id, session.Id,
                        new MessageCommand
                        {
                            Header = message.Header,
                            Text   = message.Text,
			    TimeoutMs = 1000 //Leave this out to have a modal style "Got it" Message box.
                        }, CancellationToken.None);

 

I don't know about an "OK",  "Cancel" popup on clients, but the code above will send a message to clients.

 

 

Edited by chef
Link to comment
Share on other sites

bakes82
4 minutes ago, chef said:

			await SessionManager.SendMessageCommand(session.Id, session.Id,
                        new MessageCommand
                        {
                            Header = message.Header,
                            Text   = message.Text,
			    TimeoutMs = 1000 //Leave this out to have a modal style "Got it" Message box.
                        }, CancellationToken.None);

 

I don't know about an "OK",  "Cancel" popup on clients, but the code above will send a message to clients.

 

 

Go it, the header is ignored when you have the timeout set it looks like ;)   Ill see what the modal popup looks like.  It be nice to have a semi nag feature for those who might set a the playback to a lower bitrate instead of using auto or a higher one to direct play.  Maybe at 25/50/75% throw them nag warning to be like you should change your settings lol.

Link to comment
Share on other sites

of how long it's been paused? no. you'd have to keep track of the time when you see the pause event come through.

Link to comment
Share on other sites

9 minutes ago, bakes82 said:

@Luke @chef There a way to get pause duration?

A threaded stopwatch might be inorder. Actually if this plugin kills paused playback instance that are "camping" (or left paused for long periods of time) then that is awesome! I have to text my friend every week to remind him not to el leave a disney movie paused for his kid for hours. 😂🤣

Edited by chef
Link to comment
Share on other sites

bakes82
23 minutes ago, chef said:

A threaded stopwatch might be inorder.

Seriously?  Hows that work with a scheduled task, I guess I could move this one to a diff sched task

Link to comment
Share on other sites

53 minutes ago, bakes82 said:

Seriously?  Hows that work with a scheduled task, I guess I could move this one to a diff sched task

Oh sorry, I meant you could start a stopwatch when a session pauses, then kill the session on a stopwatch event, after a period of time passes. 

Edited by chef
Link to comment
Share on other sites

bakes82
1 minute ago, chef said:

Oh sorry, I meant you could start a stopwatch when a session pauses, then kill the session on a stopwatch event, after a period of time passes. 

Is that some other magic thing I would need to implement? :P  I honestly would of thought you could just run a task every 1min check if its paused when it started, do a diff on time then kill stream.

Link to comment
Share on other sites

1 hour ago, bakes82 said:

Is that some other magic thing I would need to implement? :P  I honestly would of thought you could just run a task every 1min check if its paused when it started, do a diff on time then kill stream.

Yeah, you re probably right to use schedule task. Start the task when the session is paused. Check all sessions for paused state, keeping track of multiple sessions at once.

Link to comment
Share on other sites

bakes82
16 minutes ago, chef said:

Yeah, you re probably right to use schedule task. Start the task when the session is paused. Check all sessions for paused state, keeping track of multiple sessions at once.

To store the sessions and time where do you put them?  I assume the config?  Then pull them out next run.

 

Also doe messages only work on web browser?  Doesnt seem to do anything on the shield.

Link to comment
Share on other sites

bakes82

Looks like shield only displays messages when the timeoutMS isnt set.........  Even using the message from the dashboard to a shield never gets displayed.  @Luke How are messages suppose to work across devices, doesnt seem like its universal.  Documentation plz.

Edited by bakes82
Link to comment
Share on other sites

16 minutes ago, bakes82 said:

Looks like shield only displays messages when the timeoutMS isnt set.........  Even using the message from the dashboard to a shield never gets displayed.  @Luke How are messages suppose to work across devices, doesnt seem like its universal.  Documentation plz.

Yes I believe android devices only show the popup message from the side if the screen at the bottom.

Link to comment
Share on other sites

23 minutes ago, bakes82 said:

Looks like shield only displays messages when the timeoutMS isnt set.........  Even using the message from the dashboard to a shield never gets displayed.  @Luke How are messages suppose to work across devices, doesnt seem like its universal.  Documentation plz.

You could use config.

 

What about a dictionary<Stopwatch, string>?

Where string is the session.Id

Set the entry when the session is paused, and that instance of stopwatch will remove its  entry and kill the session when it hits it's max value. An  unpause event will remove the entry based on the session.Id value.

 

I wonder if that is possible... Having a key in a dictionary be an object which can remove itself?? 😳

Edited by chef
Link to comment
Share on other sites

bakes82
12 minutes ago, chef said:

Yes I believe android devices only show the popup message from the side if the screen at the bottom.

The issue isnt that, the issue is if you call with a TimeoutMs set on the MessageCommand you dont see the message at all.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...