tim copperfield Posted November 6, 2021 Posted November 6, 2021 (edited) I have written a plugin for a domestic radio service which has multiple PIDs with audio and a data PID with current-playing song/artist information. Since this information changes every time a new song plays, I'd like to reflect this in EPG window while listening to radio. I've considered two ways to implement it: 1) Generate EIT p/f (well, p only in this case) and inject the resulting ts packet(s) from the plugin back into DVBViewer as PID 0x12 2) When I opened the project and looked at the SDK header, I saw MSG_SETEPG and thought if maybe that would be an easier way to do it. Anyway, I'm open to either of these methods, but I don't see any documentation for (2), and I'm not actually sure if I could return additional packets for implementing (1) from a plugin ( I know i can do start/stop filter for PIDs and I'm doing that) but I don't see a way to inject stuff. So uh,,, my question is, if I was to do (2), what's the details of the structure I need to send with this message and if I was to do (1), how can I inject arbitrary TS packets back to DVBViewer (they would be strictly generated inside my plugin, the feed does NOT have this PID at all). Thanks. edit: background of why I'm doing this was in this post, where i didn't get much help, either https://www.DVBViewer.tv/forum/topic/60773-best-way-to-inject-epg-from-non-standard-stream/ Edited November 6, 2021 by tim copperfield Quote
Griga Posted November 8, 2021 Posted November 8, 2021 On 11/6/2021 at 3:33 PM, tim copperfield said: a domestic radio service which has multiple PIDs with audio and a data PID with current-playing song/artist information. Data streams like this are handled in DVBViewer as radio text, if they can be detected in the PMT and if the format (the kind of packaging in a TS/PES) is known. DVBViewer converts such data to EPG data when it receives internet radio streams containing Shoutcast metadata. So if the radio channel in question can be received in this way, you can probably achieve the desired result without having to code it. On 11/6/2021 at 3:33 PM, tim copperfield said: Generate EIT p/f (well, p only in this case) and inject the resulting ts packet(s) from the plugin back into DVBViewer as PID 0x12 Not possible. A plugin can only read and change TS packets, but not inject additional packets. On 11/6/2021 at 3:33 PM, tim copperfield said: When I opened the project and looked at the SDK header, I saw MSG_SETEPG and thought if maybe that would be an easier way to do it. MSG_SETEPG can be used to let DVBViewer import EPG data. LPARAM must be the address of the following data structure: TEPGSetData = packed record //byte alignment Data: Pointer; //points to a data block containing EPG data Size: Integer; //size of the data block (32 bit integer) end; Within this data structure, Data points to a memory block containing the to be imported EPG data. It must be allocated and deallocated by the caller. FormatVersion: Word; //16 bit integer, set it to 0x0101 TimeZone: Double; //TDateTime, 64 bit floating point value used to store date/time (see below) //set to 0 if StartTime values are stored as UTC, //otherwise to the used (local) time zone bias (see DVBViewer EPG settings) while not EndOfData do { ServiceID: Word; TransportStreamID: Word; OriginalNetworkID: Word; //OriginalNetworkID can be undefined (= 0) when exporting to DVBViewer, //but should be specified if possible TunerType: Byte; //0 = undefined, 1 = cable, 2 = satellite, 3 = terrestrial, 4 = ATSC //Tunertype can be undefined (= 0) when exporting to DVBViewer, //but should be specified if possible. Reserved: Byte; //= 0 EventID: Word; //see ETSI EN 300 468, 5.2.4 Event Information Table EventIDExtension: Word; //may be used for 32 bit Event IDs in imported data StartTime: Double; //TDateTime, 64 bit floating point value used to store date/time (see below) Duration: Double; //TDateTime Title: String; Subheading: String; Description: String; CharSet: Byte; //set it to 0xFF for UTF-8 Content: Byte; //See ETSI EN 300 468, 6.2.9, Content Descriptor AdditionalDataLength: Integer; //32 bit integer for future extensions, set it to 0 } Within this data, strings are stored in the following way: TString = packed record //byte alignment Length: Integer; //32 bit integer Text: array[0..Length-1] of Char; //8 bit character codes end; For TDateTime values see https://docwiki.embarcadero.com/Libraries/Sydney/en/System.TDateTime I hope this helps. I've never used/tested this EPG import mechanism, so let's see how it works in practice.... Quote
tim copperfield Posted November 9, 2021 Author Posted November 9, 2021 (edited) > Data streams like this are handled in DVBViewer as radio text, if they can be detected in the PMT and if the format (the kind of packaging in a TS/PES) is known. DVBViewer converts such data to EPG data when it receives internet radio streams containing Shoutcast metadata. So if the radio channel in question can be received in this way, you can probably achieve the desired result without having to code it. This is for a domestic satellite radio station which is 1) encrypted + requires a CAM 2) the song/performer info is also encrypted as well so chances of DVBViewer directly supporting it "just for me" are pretty thin. On to the WM_SETEPG implementation: I used pragma pack(1) for the structs, just in case. I think I got things correct, here's where we're at: I post message with the address + length of this structure, and nothing happens (I don't see any changes in EPG etc). Where do I look from here? Some questions: 1) I have only current playing song ID. So my Event ID is going to be fixed. Yes? 2) Start time is in UTC, i think I got the math for delphi conversions correct. 3) Duration is still double, is the seconds -> double the correct way to handle it? 4) I don't know which of Title/SubHeading/Description goes where, so I did song title -> Title, performer/artist -> Description. OK? 5) TSID/ONID are fixed (since this plugin is for my specific service). 6) Service ID matches. 7) Title/Description are faux TStrings w/utf8 data. However, I'm not getting anything in the EPG grid / main window. Should this be "instant" upon posting the EPG data? Possible TODO things i'm considering: 1) Generate EventID by hashing song + performer string Edited November 9, 2021 by tim copperfield Quote
Griga Posted November 10, 2021 Posted November 10, 2021 Just two hints: StartTime looks correct, but Duration = 52.000 are 52 days. A duration of let's say 30 minutes must be calculated as 30 * 1 / MinutesPerDay or 1800 * 1 / SecondsPerDay. The TDateTime type is akward, I hate it, but that's what we have to work with... For an empty string just write Length = 0x00000000 to the output and no text at all, not even 0x0. Quote
tim copperfield Posted November 10, 2021 Author Posted November 10, 2021 4 hours ago, Griga said: StartTime looks correct, but Duration = 52.000 are 52 days. A duration of let's say 30 minutes must be calculated as 30 * 1 / MinutesPerDay or 1800 * 1 / SecondsPerDay. The TDateTime type is akward, I hate it, but that's what we have to work with... I've adjusted it to be: epg.event[0].Duration = duration / 86400.0; Since my duration is in seconds. No difference. I'm assuming by " while not EndOfData do " in your previous reply you mean a structure of the type of: typedef struct TEPGImport { uint16_t FormatVersion; /* 16 bit integer, set it to 0x0101 */ double TimeZone; /* TDateTime, 64 bit floating point value used to store date/time (see below) */ /* set to 0 if StartTime values are stored as UTC, otherwise to the used (local) time zone bias (see DVBViewer EPG settings) */ TEPGEntry event[1]; } TEPGImport; Right? Since I only have 1 event I have no plans to submit more than one, so I made it [1] instead of [0] and dynamically allocating the struct (its now static, and updated as song/details change). So, still no update in EPG on channel change, despite me debugging and stepping through the code and the correct structure getting filled with data. sizeof() struct is 68 bytes. data looks like this: Are the TStrings in the struct POINTERS to TString or are actual passed by value copies? I.e. should my event struct look like TString foo or TString *foo ? I've tried both ways btw and still doesn't work so . Quote
Griga Posted November 11, 2021 Posted November 11, 2021 A tested and working example attached. PluginTest.dpr is the Delphi source code, PluginTest.dll the compiled binary. On each tuning in the DVBViewer main window it creates/updates an EPG entry for a French radio channel, that does not provide a native EPG. The result looks like this: For getting the same result the DLL must be stored in the Plugins sub-directory of the DVBViewer program directory. Additionally a channel entry must be present/created in the DVBViewer Channel Editor with Service ID= 9155, (Transport)Stream ID = 1094, Network ID = 1, tuner type = Satellite. These four values constitute a 64 bit EPG channel ID that is used by DVBViewer internally to assign EPG data to channels. Just discovered: EPG data that gets imported in this way is handled as if belonging to the MHW (Media Highway) category. That's why the Channel Editor -> EPG Button -> MHW menu item must be checked for the channel in question (it is by default), otherwise the imported EPG is not displayed. Plugin Test.zip Quote
tim copperfield Posted November 11, 2021 Author Posted November 11, 2021 2 hours ago, Griga said: A tested and working example attached. PluginTest.dpr is the Delphi source code, PluginTest.dll the compiled binary. On each tuning in the DVBViewer main window it creates/updates an EPG entry for a French radio channel, that does not provide a native EPG. The result looks like this: Thanks, understanding that submitted memory block was an actual sequential dump of data and not a structure made everything work. I now have EPG matching currently playing song, including the duration bar properly advancing: Thanks, considering this closed. Quote
Griga Posted November 11, 2021 Posted November 11, 2021 3 minutes ago, tim copperfield said: understanding that submitted memory block was an actual sequential dump of data and not a structure made everything work Originally it was a binary import/export file format, re-used for direct transfer. It is still possible to write the stuff to a temporary file and then let DVBViewer read it (MSG_EPGLOAD). Quote
tim copperfield Posted November 11, 2021 Author Posted November 11, 2021 Ah, but we have a bug, I think. The duration is 4 minutes 15 seconds, however the slider bar on the bottom of DVBViewer doesn't show seconds: Actually I think it rounds up or down to nearest : minute because next song was 4.88 minutes (293 seconds) long, but it shows up as 05:00 in the slider. The actual progress seems to be correct, so weird things are happening. Quote
Griga Posted November 11, 2021 Posted November 11, 2021 5 hours ago, tim copperfield said: The duration is 4 minutes 15 seconds, however the slider bar on the bottom of DVBViewer doesn't show seconds: DVBViewer rounds EPG times to minutes. Displaying seconds doesn't make sense for TV/Radio programmes and may even be disturbing. Unfortunately this isn't what you want to achieve, as I can see. You want a duration display like the one for music file playback, right? Quote
tim copperfield Posted November 12, 2021 Author Posted November 12, 2021 5 hours ago, Griga said: You want a duration display like the one for music file playback, right? More or less, yeah. I don't think it really matters, since its just a visual thing. I think this is also why sometimes I get delayed update of the song title even tho the PES data already arrived. if I register EPG to start at 08:00:45, is it going to wait until 08:01:00 to publish it? Quote
Griga Posted November 12, 2021 Posted November 12, 2021 vor 5 Stunden schrieb tim copperfield: if I register EPG to start at 08:00:45, is it going to wait until 08:01:00 to publish it? Yes, I think so. The rounding is done when the data arrives, before it is added to the EPG data collection. The original start time and duration are not preserved. For displaying what is currently running, DVBViewer checks the rounded start time. I'm not really happy with this. I think rounding should only be done for a hh:mm display in the UI, but not for a hh:mm:ss display. However, every basic change in a code monster like DVBViewer raises the question how many unexpected side effects it will cause. In the past years (since I took over) I've learned to handle such things very conservatively. Quote
tim copperfield Posted November 15, 2021 Author Posted November 15, 2021 On 11/12/2021 at 3:04 PM, Griga said: Yes, I think so. The rounding is done when the data arrives, before it is added to the EPG data collection. The original start time and duration are not preserved. For displaying what is currently running, DVBViewer checks the rounded start time. Yeah, just confirmed it. New song started at around HH:MM:50, I know my plugin sent notification, previous EPG disappeared (since same event ID + new time was already submitted), but the song name was not displayed in the channel title/EPG grid until exactly HH:MM+1:00. It would be kinda cool if that was fixed at some point, but as per your previous comments I'm not really holding my breath. Quote
Griga Posted November 15, 2021 Posted November 15, 2021 BTW: Please take note of this: https://www.dvbviewer.tv/forum/topic/65662-channel-list-editor-various-ux-issues/?do=findComment&comment=498501 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.