Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
OpenHome renderer question
10-01-2015, 09:18 PM (This post was last modified: 10-01-2015 09:19 PM by Josef.)
Post: #1
OpenHome renderer question
Hi,

I'm trying to understand OpenHome API by building a 'dummy' C++ renderer: All properties/actions are 'enabled' and actions simply print '<action name> called'.

Good news is this 'dummy' renderer appears fine in Kinsky (which I use for testing) so that's good!

However, I'm stuck at my first test case: Double-clicking a track should result in Kinsky moving the track to Playlist and start playing.
What happens instead is that an 'icon' is indeed moved but its label reads 'Empty' and while play button has changed from arrow to box (I call Play from SekkIndex as suggested in docs) time is not being updated and everything just stays still with no calls to any of Info or Time services...?

I looked at Pete Manchester Java sample code and found two confusing things: There are some events defined for Time services but I do not see those mentioned in OH docs - Are there any mandatory undocumented events for Time service or how should it work?

I also see Pete has "UpnpAv" service defined in his Product:SourceXML - Are DvAvOpenhomeOrgRenderingControl1 & DvAvOpenhomeOrgAVTransport1 required to be implemented as well even if target is only Kinsky and not 'old' upnp controllers? (I have 'only' OH Product, Time, Info & Playlist defined)

Cheers,
Josef
Find all posts by this user
11-01-2015, 02:01 PM
Post: #2
RE: OpenHome renderer question
Well, to answer myself, for both questions answer seems to be 'No' Smile

Docs say: "When a track is being played, this service delivers an event every second..." which I took service has its own timer and that is not the case. If renderer has a timer and updates Time properties then time events are indeed sent to Control Point and everything seems to work fine Smile

There is still one problem though: I can see the currently playing track meta data (name, artwork etc) correctly in upper left part of screen, however the Playlist window on right side only shows "1. Empty" for that same track (after track was double-clicked in left pane and playback has started).

I figure playlist window is populated by Playlist::ReadList and that Metadata needs to have XML characters escaped within <TrackList> XML response but even if I do that and put it in proper <TrackList> format it still says "1. Empty".
(Generated <TrackList> XML looks OK if opened in i.e. Internet Explorer)

Is there something special that needs to be done with ReadList?
Find all posts by this user
11-01-2015, 04:40 PM
Post: #3
RE: OpenHome renderer question
(10-01-2015 09:18 PM)Josef Wrote:  I'm trying to understand OpenHome API by building a 'dummy' C++ renderer: All properties/actions are 'enabled' and actions simply print '<action name> called'.

Good news is this 'dummy' renderer appears fine in Kinsky (which I use for testing) so that's good!

However, I'm stuck at my first test case: Double-clicking a track should result in Kinsky moving the track to Playlist and start playing.
What happens instead is that an 'icon' is indeed moved but its label reads 'Empty' and while play button has changed from arrow to box (I call Play from SekkIndex as suggested in docs) time is not being updated and everything just stays still with no calls to any of Info or Time services...?

I looked at Pete Manchester Java sample code and found two confusing things: There are some events defined for Time services but I do not see those mentioned in OH docs - Are there any mandatory undocumented events for Time service or how should it work?

If you want information on or progress through the current track, you need to update state variables in the Info and Time services. Implementing these is optional but you'll provide the best user experience if you can do this. You can find docs for these or all other OpenHome srevices linked from here.

(10-01-2015 09:18 PM)Josef Wrote:  I also see Pete has "UpnpAv" service defined in his Product:SourceXML - Are DvAvOpenhomeOrgRenderingControl1 & DvAvOpenhomeOrgAVTransport1 required to be implemented as well even if target is only Kinsky and not 'old' upnp controllers? (I have 'only' OH Product, Time, Info & Playlist defined)

I haven't looked through Pete's code but think you mean a UpnpAv source? This is only required if you want your device to be used with a basic UPnP:AV control point. It is not required for use with ohMedia controllers such as Linn's Kinsky or Kazoo.
Find all posts by this user
11-01-2015, 06:21 PM
Post: #4
RE: OpenHome renderer question
(11-01-2015 04:40 PM)simonc Wrote:  If you want information on or progress through the current track, you need to update state variables in the Info and Time services. Implementing these is optional but you'll provide the best user experience if you can do this. You can find docs for these or all other OpenHome srevices linked from here.

Thanks Simon for getting back!

Yes, as I mentioned in my second post I figured out OpenHome framework does not provide a timer on it's own as I misunderstood the Docs you quoted - Perhaps an idea to add what you just said to docs to prevent others falling into a same trap? Smile

(11-01-2015 04:40 PM)simonc Wrote:  I haven't looked through Pete's code but think you mean a UpnpAv source? This is only required if you want your device to be used with a basic UPnP:AV control point. It is not required for use with ohMedia controllers such as Linn's Kinsky or Kazoo.

And thanks for confirming that too Smile

Unfortunately the issue described in my second post is still not solved and I'm starting to think it might be a bug in OpenHome?

I have localised the problem down to call to SetPropertyIdArray(). If I remove this function call from Playlist:Insert() then nothing appears in Kinsky's Playlist window. But if I call it e.g. like this SetPropertyIdArray("0001") I get "1. Empty" in playlist window.

Looking at SetPropertyIdArray() in Pete's code I see one big difference to C++ version of OpenHome: In Java SetPropertyIdArray expects a byte array (which is in line with docs: http://www.openhome.org/wiki/Developer:IdArray)

Unfortunately, with C++ std::string is expected which for this ID would result in OH framework initialising this value as 0x30 0x30 0x30 0x31 which is quite a bit different from 0x00 0x00 0x00 0x01 Smile

It seems it is not possible to send actual bytes either as OpenHome's underlying function calls string.length() which obviously would return zero in this case:

bool DvProviderAvOpenhomeOrgPlaylist1Cpp::SetPropertyIdArray(const std::string& aValue)
{
ASSERT(iPropertyIdArray != NULL);
Brn buf((const TByte*)aValue.c_str(), (TUint)aValue.length());

Is this indeed a bug or am I doing it all wrong? Smile

Cheers,
Josef
Find all posts by this user
11-01-2015, 10:53 PM
Post: #5
RE: OpenHome renderer question
(11-01-2015 06:21 PM)Josef Wrote:  Unfortunately the issue described in my second post is still not solved and I'm starting to think it might be a bug in OpenHome?

I have localised the problem down to call to SetPropertyIdArray(). If I remove this function call from Playlist:Insert() then nothing appears in Kinsky's Playlist window. But if I call it e.g. like this SetPropertyIdArray("0001") I get "1. Empty" in playlist window.

Looking at SetPropertyIdArray() in Pete's code I see one big difference to C++ version of OpenHome: In Java SetPropertyIdArray expects a byte array (which is in line with docs: http://www.openhome.org/wiki/Developer:IdArray)

Unfortunately, with C++ std::string is expected which for this ID would result in OH framework initialising this value as 0x30 0x30 0x30 0x31 which is quite a bit different from 0x00 0x00 0x00 0x01 Smile

You need to base64 encode each element of IdArray. See http://www.openhome.org/wiki/Developer:IdArray for details.
Find all posts by this user
11-01-2015, 11:42 PM
Post: #6
RE: OpenHome renderer question
(11-01-2015 10:53 PM)simonc Wrote:  You need to base64 encode each element of IdArray. See http://www.openhome.org/wiki/Developer:IdArray for details.

I was looking at that page whole day but all I see is a standard big-endian integer encoding and no base64 encoded output? (yes I know it's mentioned in text)

But ok, let's try it like this: If first track gets id=1 then base64 says "MQ==" is proper encoding, right?

If so, I tried it with SetPropertyIdArray() but it didn't work either - however, if you say that is how it should be then I'll be happy to go back and look at the code again Smile
Find all posts by this user
12-01-2015, 11:21 AM
Post: #7
RE: OpenHome renderer question
My mistake. IdArray just needs to contain a 4 byte big endian unsigned value for each track. Base64 encoding is necessary for communication over UPnP but will be applied automatically if you're using ohNet.

In an earlier post, you were concerned whether the use of std::string::c_str() precluded use with binary data that may contain nul bytes. I don't think this is the case.

C++11 section 21.4.7.1 basic_string accessors [string.accessors] says that
const charT* c_str() const noexcept;
Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].

which seems to imply that any standards-compliant runtime must have allocated the full contents of a string. The OpenHome::Brn c'tor which is called uses the length provided by the client (std::string::size()) so nul bytes should have no special effect.
Find all posts by this user
12-01-2015, 11:59 AM
Post: #8
RE: OpenHome renderer question
(12-01-2015 11:21 AM)simonc Wrote:  My mistake. IdArray just needs to contain a 4 byte big endian unsigned value for each track. Base64 encoding is necessary for communication over UPnP but will be applied automatically if you're using ohNet.

Ah, that makes more sense, good riddance with base64 Smile

(12-01-2015 11:21 AM)simonc Wrote:  In an earlier post, you were concerned whether the use of std::string::c_str() precluded use with binary data that may contain nul bytes. I don't think this is the case.

C++11 section 21.4.7.1 basic_string accessors [string.accessors] says that
const charT* c_str() const noexcept;
Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].

which seems to imply that any standards-compliant runtime must have allocated the full contents of a string. The OpenHome::Brn c'tor which is called uses the length provided by the client (std::string::size()) so nul bytes should have no special effect.

You're correct, std::string is happy with null bytes if assign(char*, len) is used as then correct length() is reported.
Just tested it all and everything works fine - Thank You! Smile
Find all posts by this user


Forum Jump: