Jump to content

virtualTvExample question


VicMoore

Recommended Posts

1 minute ago, VicMoore said:

@Lukeand @SamESany progress on fixing the players so they will advance to the next video when the current one finishes

Vic

I gave an update above, right?

Link to comment
Share on other sites

  • 1 month later...
VicMoore
Posted (edited)

 

@LukeI know you are busy, and I really do appreciate the time you have given me.  I have spent a great deal of time trying to figure out why the Emby server doesn't fetch the next channel in your "virtualTVexample code.  When a program is selected to play (by clicking it in the EPG) it always starts at the beginning. It's interesting that the duration timer at the bottom of the Emby client shows the correct playing time. Also, when the program ends (and again when the duration timer ends) the following error is thrown.

*** Error Report ***

Version: 4.8.3.0

Command line: C:\Users\vic\AppData\Roaming\Emby-Server\system\EmbyServer.dll -noautorunwebapp

Operating system: Microsoft Windows 10.0.22621

Framework: .NET 6.0.27

OS/Process: x64/x64

Runtime: C:/Users/vic/AppData/Roaming/Emby-Server/system/System.Private.CoreLib.dll

Processor count: 4

Data path: C:\Users\vic\AppData\Roaming\Emby-Server\programdata

Application path: C:\Users\vic\AppData\Roaming\Emby-Server\system

System.NullReferenceException: System.NullReferenceException: Object reference not set to an instance of an object.

at Emby.LiveTV.LiveTvManager.RefreshEmbyChannelsInternal(IProgress`1 progress, CancellationToken cancellationToken)

Source: Emby.LiveTV

TargetSite: Void MoveNext()

 

From my novice knowledge I assume that this error was caused by the server failing to find the next program to play.  To remedy the problem the server fetches channels again. I am sure the server is doing this because it believes it's out of channel data. 

 

2024-03-08 08:37:20.518 Info PseudoTVTuner: ======embyTv====== Ensure Channel Schedule - tuner Channel Id = 2

2024-03-08 08:37:20.518 Info PseudoTVTuner: ======embyTv====== Ensure Channel Schedule - newSchedule = False

2024-03-08 08:37:20.518 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - tuner Channel Id = 2

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - tuner = {"Id":"7e34041bfda64e9e9baa230c10822abb","Type":"pseudotvtuner","ImportFavoritesOnly":false,"PreferEpgChannelImages":true,"PreferEpgChannelNumbers":false,"AllowHWTranscoding":true,"AllowMappingByNumber":true,"ImportGuideData":true,"TunerCount":0,"ProviderOptions":"{\"UserId\":\"fb01ce97647f48a9ae4067b4c0adb172\",\"ChannelNames\":[\"Channel\",\"Channel2\",\"Channel3\"],\"ChannelNumbers\":[\"1\",\"2\",\"3\"],\"Types\":[\"TV\",\"TV\",\"TV\"],\"EpgActions\":[\"New\",\"New\",\"New\"],\"Ids\":

---- I removed data here to save space ---

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - ChannelNames = ["Channel","Channel2","Channel3"]

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - ChannelTypes = ["TV","TV","TV"]

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - ProgramIds = [["775","35368","224416","32","1032773","224417","775","35369","224403","32","1032774","224405","775","35370","224404","32","1032775","224406","775","35371","224407","32","1032776","224408","775","35372","224409","32","1032777","224410"],["1012022","1056400","1012023","1056643","1012024","1056966","1012025","1056941","1012026","1056655","1012027","1056735","1012028","1057062","1012029","1056519","1012030","1056718","1012031","1056670","1012032","1056820","1012033","1056884","1012034","1056945","1012035","1056954","1012036","1056518","1012037","1056970","1012038","1056722","1012039","1056749","1012040","1056774","1012041","1056974","1012042","1056984","1012043","1056810","1012044","1056550","1012045","1057059","1012046","1056726","1012047","1056709","1012048","1056617","1012049","1056684","1012050","1056656","1012051","1056840","1012052","1057008","1012053","1056622","1012054","1056854","1012055","1056523","1012056","1056872","1012057","1056466","1012058","1056501","1012059","1056437","1012060","1056452","1012061","1056403","1012062","1056517","1012063","1056730","1012064","1056745","1012065","1056980","1012066","1056491","1012067","1056791","1012068","1056940","1012069","1056589","1012070","1056717","1012071","1056932","1012072","1056946","1012073","1056991","1012074","1056603","1012075","1056984","1012076","1056592","1012077","1056438","1012078","1056620","1012079","1056518","1012080","1056385","1012081","1056754","1012082","1056731","1012083","1056614","1012084","1056477","1012085","1056905"],["146","1056419","150","1056641","144","1056907","157","1056715","148","1056562","155","1056395","143","1056445","160","1056661","158","1056925","151","1056693","137","1056631","153","1056589","162","1057044","159","1056987","163","1056763","164","1056720","177","1057031","165","1056781","171","1057042","173","1056854","170","1056727","161","1057035"]]

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - Channel Ids = ["146","1056419","150","1056641","144","1056907","157","1056715","148","1056562","155","1056395","143","1056445","160","1056661","158","1056925","151","1056693","137","1056631","153","1056589","162","1057044","159","1056987","163","1056763","164","1056720","177","1057031","165","1056781","171","1057042","173","1056854","170","1056727","161","1057035"]

2024-03-08 08:37:20.589 Info LiveTV: Loading live tv data from C:\Users\vic\AppData\Roaming\Emby-Server\programdata\data\livetv\seriestimers

2024-03-08 08:37:20.590 Info TaskManager: Refresh Guide Completed after 0 minute(s) and 1 seconds

2024-03-08 08:37:25.265 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(SeriesPresentationUniqueKey)

2024-03-08 08:37:25.703 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(AlbumId)

2024-03-08 08:37:40.352 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(SeriesPresentationUniqueKey)

2024-03-08 08:37:41.397 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(AlbumId)

2024-03-08 08:42:37.315 Info Server: http/1.1 POST http://localhost:8096/emby/LiveTv/TunerHosts?X-Emby-Client=Emby Web&X-Emby-Device-Name=Microsoft Edge Windows&X-Emby-Device-Id=e65aab42-985c-44f6-ae8f-bd965291d929&X-Emby-Client-Version=4.8.3.0&X-Emby-Token=x_secret1_x&X-Emby-Language=en-us&reqformat=json. UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0

2024-03-08 08:42:37.319 Info TaskManager: Queueing task RefreshChannelsScheduledTask

2024-03-08 08:42:37.319 Info TaskManager: Executing Refresh Guide

2024-03-08 08:42:37.319 Info Server: http/1.1 Response 200 to ::1. Time: 5ms. POST http://localhost:8096/emby/LiveTv/TunerHosts?X-Emby-Client=Emby Web&X-Emby-Device-Name=Microsoft Edge Windows&X-Emby-Device-Id=e65aab42-985c-44f6-ae8f-bd965291d929&X-Emby-Client-Version=4.8.3.0&X-Emby-Token=x_secret1_x&X-Emby-Language=en-us&reqformat=json

2024-03-08 08:42:37.320 Error LiveTvManager: Error getting channels

*** Error Report ***

Version: 4.8.3.0

Command line: C:\Users\vic\AppData\Roaming\Emby-Server\system\EmbyServer.dll -noautorunwebapp

Operating system: Microsoft Windows 10.0.22621

Framework: .NET 6.0.27

OS/Process: x64/x64

Runtime: C:/Users/vic/AppData/Roaming/Emby-Server/system/System.Private.CoreLib.dll

Processor count: 4

Data path: C:\Users\vic\AppData\Roaming\Emby-Server\programdata

Application path: C:\Users\vic\AppData\Roaming\Emby-Server\system

System.NullReferenceException: System.NullReferenceException: Object reference not set to an instance of an object.

at Emby.LiveTV.LiveTvManager.RefreshEmbyChannelsInternal(IProgress`1 progress, CancellationToken cancellationToken)

Source: Emby.LiveTV

TargetSite: Void MoveNext()

 

@Luke Can I modify the "Ensure Channel Schedule" code in the "VirtualTvExample" so it will provide to Emby the next program to play.  For example, as a temporary fix, can I reload the channel data at the proper point to start playing the next program and then tell Emby to start playing it?  If this idea is worthless, please give me some pointers on what I can do. 

Any success I have, I will share with @pünktchenand he is always welcome to use freely any of my code in any way that he chooses.    

Vic

 

 

Edited by VicMoore
Link to comment
Share on other sites

Quote

Can I modify the "Ensure Channel Schedule" code in the "VirtualTvExample" so it will provide to Emby the next program to play. 

No, this comes from the EPG. It will just start playing the channel at the current time, meaning whatever is currently on the channel.

Link to comment
Share on other sites

VicMoore
Posted (edited)

@Luke I discovered this a short while earlier today.  

Is the problem in the server code? I ask this because the error log says the server was not able to find the next program to play.

Should I abandon this project?  Will a fix be available anytime soon? 

Vic

Edited by VicMoore
Link to comment
Share on other sites

VicMoore
Posted (edited)

@Luke I read it in the Emby log.  I will try and recreate the event and send you the log.  I have been watching via log messages each time the server calls anything in the Tuner code trying to understand why the next channel is found OK in Chrom but not with Android. Sometimes even Edge goes to the next program OK.  As a temporary fix I was considering sending a playlist to the client when a program is requested.  I know @pünktchenhas this working.   I am only interested in this solution for my own use.  Do you have any ballpark idea when this problem will be solved?

Vic

Edited by VicMoore
  • Thanks 1
Link to comment
Share on other sites

VicMoore

@LukeWhile waiting for the problems associated with playing programs in the virtualTvExample code, I decided to try a simple work around. One similar to what @pünktchenis doing. In the GetChannelStreamMediaSources task I added a small program that builds a playlist from the schedule info and then I send that playlist to the client with a "Play Now" command. I have tested this idea and it works. I have experienced one strange problem when clicking a movie to be played. The client plays the playlist OK, but it adds trailers for the movies to the front of the playlist.  TV shows are played OK.  All of the code is below. Now programs start at the proper time and programs in the schedule play sequentially.

Do you have any suggestions on how to improve this idea?  Of course, when the changes for the virtualTvCode is ready I will remove this code.

Vic

 

        protected override Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, BaseItem dbChannnel, ChannelInfo tunerChannel, CancellationToken cancellationToken)
        {
            this.Logger.Info("======embyTv=====> Get channel stream media sources");

            var tunerChannelId = this.GetTunerChannelIdFromEmbyChannelId(tuner, tunerChannel.Id);

            var options = this.GetProviderOptions<ProviderTunerOptions>(tuner);

            this.Logger.Info("======embyTv====== tuner channel Id " + tunerChannelId);

            // get the program that is currently airing
            var query = new InternalItemsQuery()
            {
                ParentIds = new[] { dbChannnel.InternalId },
                IsAiring = true,
                IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
                Limit = 1
            };

            var program = this.libraryManager.GetItemList(query).FirstOrDefault();

            if (program == null)
            {
                this.Logger.Info("======embyTv====== Program not found, query = " + query.ParentIds[0]);

                throw new ResourceNotFoundException("Program not found.");
            } else
            {
                this.Logger.Info("======embyTv====== (DbId) Program playing Id = " + program.GetProviderId("DbId"));
            };
            //-----------------------------------------------------------------------------------
            //
            // use the provider id we added to the program to locate the original library item
            //
            var programPlayingId = program.GetProviderId("DbId");
            var item = this.libraryManager.GetItemById( programPlayingId );

            //-----------------------------------------------------------------------------------
            RunPlaylistTest(tuner, options, tunerChannelId, cancellationToken);
            //-----------------------------------------------------------------------------------

            if (item == null)
            {
                this.Logger.Info("======embyTv====== Playing item = null");
                return Task.FromResult(new List<MediaSourceInfo>());
            }

            this.Logger.Info("======embyTv====== Playing item name = " + item.Name);
            this.Logger.Info("======embyTv====== Playing presentation unique key = " + item.Id);
            this.Logger.Info("======embyTv====== Playing display parent = " + item.DisplayParent);

            //-----------------------------------------------------------------------------------
            // pass null for the user and false for the other options such as path substitution.
            // this is an internal method to get media sources, which normally would not call mediaSourceManager.GetPlayackMediaSources.
            // the user and path substitution options will end up getting applied by the outer consumer of this, which is why they don't need to be passed down lower
            return this.mediaSourceManager.GetPlayackMediaSources(item, null, false, false, cancellationToken);
        }

=================================================================================================================================

This is the program I added.

 void RunPlaylistTest(TunerHostInfo tuner, ProviderTunerOptions options, string tunerChannelId, CancellationToken cancellationToken)
        {
            string sessionId = "";
            var sessionData = this.sessionManager.Sessions;
            var sessions = sessionData.GetEnumerator();
            SessionInfo session = new SessionInfo();
            this.Logger.Info("======embyTv====== While Loop ========================");

            while (sessions.MoveNext())
            {
                session = sessions.Current;
                this.Logger.Info("======embyTv====== While Loop - session.Id = " + session.Id + ", DeviceId = " + session.DeviceId + ", UserName = " + session.UserName);
                if (session.UserId == options.UserId)
                {
                    this.Logger.Info("======embyTv====== While Loop - User Found  = " + ", UserName = " + session.UserName);
                    if (sessionId == "")
                    {
                        sessionId = session.Id;
                        this.Logger.Info("======embyTv====== Current Session Id = " + sessionId);
                        this.Logger.Info("======embyTv====== Current Session Id = " + session.PlaylistLength);
                        this.Logger.Info("======embyTv====== Current Session Id = " + session.PlaylistIndex);
                        session.PlaylistLength = 0;
                        session.PlaylistIndex = 0;
                    }
                }
            };
            this.Logger.Info("======embyTv====== End While Loop ====================");


            if (sessionId != "")
            {
                ChannelSchedule schedule = this.GetSavedChannelSchedule(tuner, tunerChannelId);
                schedule.RemoveOldPrograms();
                List<ChannelScheduleItem> Programs = schedule.Programs;
                this.Logger.Info("======embyTv====== Programs = " + this.JsonSerializer.SerializeToString(Programs));

                DateTimeOffset startDate;
                List<long> idList = new List<long>();
                int i;

                for (i = 0; i < 12; i++)
                {
                    ChannelScheduleItem pro = Programs[i];
                    if (pro == null) break;

                    long id = pro.ItemId;
                    if (i == 0) {
                        startDate = pro.StartDate;
                        this.Logger.Info("======embyTv====== Start Time = " + this.JsonSerializer.SerializeToString(startDate));
                    }
                    idList.Add(id);
                };

                long[] mediaIds = idList.ToArray();

                this.Logger.Info("======embyTv====== Media Ids = " + this.JsonSerializer.SerializeToString(mediaIds));

                var nowDate = DateTimeOffset.UtcNow;
                //this.Logger.Info("======embyTv====== Time Now Utc = " + this.JsonSerializer.SerializeToString(nowDate));
                double ms = (nowDate - startDate).TotalMilliseconds;
                var ticks = (long)ms * 10000;
                //this.Logger.Info("======embyTv====== Time Delta in ms = " + this.JsonSerializer.SerializeToString(ms) + ", ticks = " + this.JsonSerializer.SerializeToString(ticks));

                //var command = new PlaystateRequest() { Command = PlaystateCommand.Stop, SeekPositionTicks = 0, ControllingUserId = options.UserId };
                //this.sessionManager.SendPlaystateCommand(sessionId, sessionId, command, cancellationToken);

                var playRequest = new PlayRequest() { PlayCommand = PlayCommand.PlayNow, ItemIds = mediaIds, StartPositionTicks = ticks, StartIndex = 0 };
                this.sessionManager.SendPlayCommand(sessionId, sessionId, playRequest, cancellationToken);

                this.Logger.Info("======embyTv====== =================================== 1");
            };
        }

 

 

 

 

 

 

 

 

 

 

 

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...