c++ DMS with subtitle support on LG smart tv with platinium library - c++

I'm trying to implement a simple DMS that can provide subtitle information to the DMR -LG SmartTV - using platinium library.
I already succeeded to render video on the DMR and i already found where the DMR receive the information of the subtitle associated to the video file.
Sample request from the DMR:
POST /upnp/services/ContentDirectory/control HTTP/1.1
HOST: 192.168.1.3:54444
CONTENT-LENGTH: 735
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"
USER-AGENT: Linux/2.6.39.4.ps-110224-lg1152 UPnP/1.0 DLNADOC/1.50 INTEL_NMPR/2.0 LGE_DLNA_SDK/1.6.0
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
<ObjectID>ea06</ObjectID>
<BrowseFlag>BrowseDirectChildren</BrowseFlag>
<Filter>#id,#parentID,#restricted,#childCount,dc:title,dc:creator,upnp:artist,upnp:class,dc:date,upnp:album,upnp:genre,res,res#size,res#duration,res#protection,res#bitrate,res#resolution,res#protocolInfo,res#nrAudioChannels,res#sampleFrequency,upnp:albumArtURI,upnp:albumArtURI#dlna:profileID, res#dlna:cleartextSize</Filter>
<StartingIndex>0</StartingIndex>
<RequestedCount>24</RequestedCount>
<SortCriteria></SortCriteria>
</u:Browse>
</s:Body>
</s:Envelope>
now the response from a valid DMS that support subtitle display is:
HTTP/1.1 200 OK
SERVER: WINDOWS/5.1 UPnP/1.0 DLNADOC/1.50 Nero-MediaHome/4.5.20.145
CONTENT-TYPE: text/xml; charset=utf-8
EXT:
DATE: Mon, 14 Jan 2013 22:12:35 GMT
TRANSFER-ENCODING: chunked
CONNECTION: Keep-Alive
...
<item id="ea13" parentID="ea06" restricted="1">
<dc:date>2012-10-25</dc:date>
<dc:title>video.avi</dc:title>
<upnp:album>Filmes</upnp:album>
<upnp:class>object.item.videoItem.movie</upnp:class>
<res
bitrate="257570" duration="1:37:32" nrAudioChannels="6"
protocolInfo="http-get:*:video/avi:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000"
resolution="720x304" sampleFrequency="48000" size="1507196928">http://192.168.1.3:54444/server/80402875-CA74-4CCE-B7E0-D81CEF1913A2/D5E59F25/ea13?unknown-id</res>
<res protocolInfo="http-get:*:text/srt:*">http://192.168.1.3:54444/server/80402875-CA74-4CCE-B7E0-D81CEF1913A2/3A2C7131/ea13?sub=video.srt</res>
</item>
Now i'm trying to implement the same in my custom DMS, can anyone point me in the right direction or show any sample that implements subtitle info stored in res element as: srt_URL (content-type of response is text/srt)
Thanks

To add a SRT resource tag to UPnP item in Platinum, you should do at least the following. I don't claim the list being functional, complete or tested. It's just my best guess at what needs to be changed. If it doesn't immediately work as expected, i may not be able to help you more specifically. It's a navigation hint, not a driving assistance.
put your SRT file in the same folder as the media file, named the same way in some sensible way which would be easy for you to distinguish afterwards.
in PltMimeType.cpp add "srt","text/srt" to PLT_HttpFileRequestHandler_DefaultFileTypeMap. Platinum doesn't know SRT out of the box.
PltFileMediaServer.cpp is kinda dumb, it by default shows up all files found in a directory. It's an example, after all. You need to filter out SRTs from the visible listing by implementing PltFileMediaServer::ProcessFile filter.
still in PltFileMediaServer.cpp there is a method PLT_FileMediaServerDelegate::BuildFromFilePath. Here comes filepath which is the path of your media file (and ONLY that). Out of the filepath, you need to look in the folder whether there is a properly named subtitle file (with some NPT_File methods, look it up).
if there is, you must add extra PLT_MediaItemResource to the PLT_MediaObject* object. There is already one resource instance, but that's used exclusively for the media resource itself. Don't reuse it. You need to add another one, and IMO you need to set only resource.m_Uri (with BuildResourceUri) and resource.m_ProtocolInfo.
for m_ProtocolInfo, you need to call PLT_ProtocolInfo::GetProtocolInfo with parameter false so that the protocolInfo of your newly added <res> is not clobbered with DLNA profile id.

Related

upload data with HTTP method POST or PUT

I'm working with STM32-microcontroller and C-languege and want to send to and receive the data from my website. I can receive the .txt file with the "GET" method from website via this code:
static const char http_request[] = "GET "WEBSITE_SUB_ADDRESS" HTTP/1.1\r\nHost: "WEBSITE_ADDRESS"\r\n\r\n";
net_sock_send(socket, (uint8_t *) http_request, len);
net_sock_recv(socket, (uint8_t *) buffer + read, NET_BUF_SIZE - read);
Now I want to send or upload the data to the website in a file with http-method (POST or PUT, ...). How can I do it?
You first need to decide if you want to use POST or PUT.
The PUT method completely replaces whatever currently exists at the target URL with something else. With this method, you can create a new resource or overwrite an existing one given you know the exact Request-URI. ...In short, the PUT method is used to create or overwrite a resource at a particular URL that is known by the client.
The HTTP POST method is used to send user-generated data to the web server. For example, a POST method is used when a user comments on a forum or if they upload a profile picture. A POST method should also be used if you do not know the specific URL of where your newly created resource should reside. ...In short, the POST method should be used to create a subordinate (or child) of the resource identified by the Request-URI.
from https://www.keycdn.com/support/put-vs-post
While connected to the server you would send a HTTP header just as you have done with the GET request that would look somthing like this:
POST /test HTTP/1.1\r\n
Host: www.myServer.com\r\n
Content-Type: text/plain\r\n
Content-Lenght: 8\r\n
Accept: */*\r\n
\r\n
someData
You might also want to check if the server recived the message by looking at the header that is sent back to you, it should include HTTP/1.1 200 OK.
Edit: to get it into a file try /test/mytext.txt but i dont have a way of testing if this works
A good place to test the request is Post Test Server V2. hope this helps
#Flynn Harrison
I tested your method as follows:
static const char http_request[] = "POST "SUB_ADDRESS" HTTP/1.1\r\n"
"Host: "HOST_ADDRESS"\r\n\r\n"
"Content-Type: text/plain\r\n"
"Content-Lenght: 13\r\n"
"Accept: */*\r\n"
"\r\n"
"Data for Write Test";
and then:
net_sock_setopt(socket, "tls_server_name", (uint8_t*)HOST_ADDRESS, sizeof(HOST_ADDRESS));
net_sock_open(socket, HOST_ADDRESS, TIME_SOURCE_HTTP_PORT, 0);
net_sock_send(socket, (uint8_t *) http_request, len);
net_sock_recv(socket, (uint8_t *) buffer + read, NET_BUF_SIZE - read);
When I tried "/test.txt" at SUB_ADDRESS, I get the HTTP / 1.1 200 OK message but immediately after receiving the file contents, in the same buffer, I receive the HTTP / 1.1 400 Bad Request message and I do not see any changes to the file. My response from server is as follows:
HTTP/1.1 200 OK
.
.
.
This is a Test.... (Text-File Content)
HTTP/1.1 400 Bad Request\r\nDate: Fri, 09 Aug 2019 09:03:56
.
.
.
In the site you mentioned, the POST method works well but its mechanism is not clear which I can use. I tried to test the POST method with this site and my device but got error "411 Length Required".

How to include Zumo API version header in rest client

I have an Azure Mobile App backend working web service. I am trying to carry out basic crud operations. I understand that you can use a url like myapp/tables/object?zumo-api-version=2.0.0 and this works fine when I am getting data. However, when I want to put, delete etc it requires an id. If I type myapp/tables/object/dsjkfhsdjkfjsdfjkkdjf?zumo-api-version=2.0.0 for example where the string is the id I can carry out the operation. Similarly, if I enter an id in Swagger, I can also carry out the put operation. However, I am unsure as to how to go about adding the zumo-api-version details on the client side. How can I include the zumo version header in my project?
See Header Specification here:
https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-client-and-server-versioning/
The key ZUMO-API-VERSION may be specified in either the HTTP header or the query string. The value is a version string in the form x.y.z.
For example:
GET https://service.azurewebsites.net/tables/TodoItem
HEADERS: ZUMO-API-VERSION: 2.0.0
POST https://service.azurewebsites.net/tables/TodoItem?ZUMO-API-VERSION=2.0.0
So you could do:
$ curl -sv -H "ZUMO-API-VERSION: 2.0.0" \
http://{mobileapp}.azurewebsites.net/tables/todoitem
> GET /tables/todoitem HTTP/1.1
> Host: {mobileapp}.azurewebsites.net
> User-Agent: curl/7.49.1
> Accept: */*
> ZUMO-API-VERSION: 2.0.0
>
< HTTP/1.1 200 OK
[...]
[{
"id":"40b996d6-ec7f-4188-a310-0f02808e7093",
"createdAt":"2016-08-31T11:30:11.955Z",
"updatedAt":"2016-08-31T11:30:11.971Z",
"version":"AAAAAAAAG5s=",
"deleted":false,
"Yo_mobileapp":"Sup"
}]
Note ZUMO-API-VERSION: 2.0.0 passed in as Header.
If you're asking "Which is better?", there's no better. They do the same thing. That being said, it's probably easier and cleaner to send a Header for most use cases.

How to post a reply to a Team Discussion thread using webservice?

I'm trying to post a reply in a Team Discussion in SharePoint using the Lists webservice. I have tried the AddDiscussionBoardItem operation. Since the message parameter should be MIME, I create the thread by posting a message like:
Message-ID: <1343576290.0.1409922592343.JavaMail.foouser#foocomputer>
Subject: Test thread
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Thread-Index: Ac/JCq4D1Jh6s4l1SLGY/7pz8XIN2Q==
Body of test thread.
This works. But then I try to create a reply. Note the Thread-Index which is required according the webservice specification.
Message-ID: <1708591960.0.1409922780765.JavaMail.foouser#foocomputer>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Thread-Index: Ac/JCq4D1Jh6s4l1SLGY/7pz8XIN2QAAHBNL
Body of thread reply.
This gets posted, but instead of ending up as a reply, a new thread named "(no title)" is created. I thought the Thread-Index was the key, I have tried to implement it according ConversationIndex Property specification. To sum it up, the first 22 bytes (unencoded) should be same in the thread, with an extra 5 bytes extra for every level down. (An odd thing is that you post it base64-encoded, but get it back in hex.)
So, what's missing or is there another way of doing it?
I'm programming in Java but I don't think the challenge is language-specific.

Setting a cookie using JavaFX's WebEngine/WebView

I cannot seem to find any way to set a cookie programatically using WebEngine / WebView in JavaFX. The API doesn't give any idea as to how to obtain an HttpRequest-like object to modify the headers (which is what I use in the app for XML-RPC), or any sort of cookie manager.
No questions on this page seem to touch on the issue either - there is this but it just disables cookies when in applet to fix a bug, my app is on desktop btw.
The only way I image I could do it is by requesting the first page (which requires a cookie with a sessionID to load properly), getting an "access denied"-style message, executing some javascript in the page context which sets the cookie and then refreshing. This solution would be a horrible user experience though.
How do I set a cookie using WebEngine?
Update: Taking a clue from a question linked above, I tried digging around for some examples of using CookieManager and related APIs. I found this code, which I then tried to incorporate into my app, with weird results;
MyCookieStore cookie_store = new MyCookieStore();
CookieManager cookie_manager = new CookieManager(cookie_store, new MyCookiePolicy());
CookieHandler.setDefault(cookie_manager);
WebView wv = new WebView();
Now lets say we do this:
String url = "http://www.google.com/";
wv.getEngine.go(url);
Debugging in Eclipse after this request has been made shows that the cookie store map holds a cookie:
{http://www.google.com/=[NID=67=XWOQNK5VeRGEIEovNQhKsQZ5-laDaFXkzHci_uEI_UrFFkq_1d6kC-4Xg7SLSB8ZZVDjTUqJC_ot8vaVfX4ZllJ2SHEYaPnXmbq8NZVotgoQ372eU8NCIa_7X7uGl8GS, PREF=ID=6505d5000db18c8c:FF=0:TM=1358526181:LM=1358526181:S=Nzb5yzBzXiKPLk48]}
THAT IS AWESOME
WebEngine simply uses the underlying registered cookie engine! But wait, is it really? Lets try adding a cookie, prior to making the request...
cookie_store.add(new URL(url).toURI(), new HttpCookie("testCookieKey", "testCookieValue"));
Then I look at the request in Wireshark...
GET / HTTP/1.1
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/535.14 (KHTML, like Gecko) JavaFX/2.2 Safari/535.14
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Cache-Control: no-cache
Pragma: no-cache
Host: www.google.com
Connection: keep-alive
No cookie for me :(
What am I doing wrong?
I have managed to solve this issue with the help of Vasiliy Baranov from Oracle. Vasiliy wrote to me:
Try putting the cookie into java.net.CookieHandler.getDefault() after
the WebView is instantiated for the first time and before the call to
WebEngine.load, e.g. as follows:
WebView webView = new WebView();
URI uri = URI.create("http://mysite.com");
Map<String, List<String>> headers = new LinkedHashMap<String, List<String>>();
headers.put("Set-Cookie", Arrays.asList("name=value"));
java.net.CookieHandler.getDefault().put(uri, headers);
webView.getEngine().load("http://mysite.com");
This will place the cookie into the store permanently, it should be sent out on every subsequent request (presumably provided that the server doesn't unset it).
Vasiliy also explained that WebView will install it's own implementation of the CookieHandler, while retaining cookies put into the default one.
Lastly, he mentions something quite intriguing:
Do not waste your time trying to use java.net.CookieManager, and
java.net.CookieStore. They are likely to cause problems with many
sites because they implement the wrong standard.
I tried googling after this but it doesn't seem to be common knowledge. If anyone is able to provide more details I would be grateful. It seems weird, since it seems CookieStore and CookieManager are used by a lot of software out there.
Solution for java.net.CookieManager
Cookies serialization:
List<HttpCookie> httpCookies = cookieManager.getCookieStore().getCookies();
Gson gson = new GsonBuilder().create();
String jsonCookie = gson.toJson(httpCookies);
Cookies deserialization:
Gson gson = new GsonBuilder().create();
List<HttpCookie> httpCookies = new ArrayList<>();
Type type = new TypeToken<List<HttpCookie>>() {}.getType();
httpCookies = gson.fromJson(json, type); // convert json string to list
for (HttpCookie cookie : httpCookies) {
cookieManager.getCookieStore().add(URI.create(cookie.getDomain()), cookie);
}

Getting "WSE003: The input was not a valid SOAP message" on every call to an WSE 2.0 SoapHttpRouter

I already tried some different SOAP-messages, even one which has an empty header and body, but without success to get into my SoapHttpRouter-derived class :-(
Also, when I hit the .asmx-URL with the browser it comes to that error.. here detailed stack trace of the error:
[NotSupportedException: WSE003: The input was not a valid SOAP message.]
Microsoft.Web.Services2.Messaging.SoapHttpRouter.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object asyncState) +134
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8677954
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
I hope that someone is out there who had the same problem. I would appreciate your help very much!
Typically when I get that message it's because there is a server side error and it's sending the default HTML error page back instead of the properly formatted SOAP message.
I would try stepping through the server-side code (if possible) to make sure there aren't any problems.
Were you aware that WSE 2.0 is extremely obsolete? Even more so than WSE 3.0.
I recently ran into this issue. The solution for me was to add the SOAPAction HttpHeader to the request, so that the request header looked something like this:
POST <web service url> HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: <action url>
Host: <host>
Content-Length: xxx