Jump to content

How to use MSG_SETEPG message


tim copperfield

Recommended Posts

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 by tim copperfield
Link to comment
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....

 

Link to comment

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

image.thumb.png.7eb5ce76ddf844eb9193a83e1e1ea4b2.png

 

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 by tim copperfield
Link to comment

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.

 

Link to comment
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:

 

image.thumb.png.61128ed3a0060e58e9ad5cbf2e7790f3.png

 

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 .

 

Link to comment

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:

 

Zwischenablage01.png

 

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

Link to comment
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:

image.png.b765e75ee83ccb41d1a303ce55b1724c.png

Thanks, considering this closed.

Link to comment
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).

 

Link to comment

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:

image.png.452172ddc0b2cb24539ad88dad10e1cf.png

 

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.

Link to comment
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?

 

Link to comment
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?

 

Link to comment
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. ;)

 

Link to comment
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.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...