Chromecast custom receiver without media - google-cast

I want to show a webpage using Chromecast. Currently the page is very simple (just "Hello World!"), but I am hoping to make it more complex and possibly interactive with a second screen. However, I have found that if I don't create a media manager (new cast.receiver.MediaManager(window.mediaElement)) the session immediately expires on my sender (function sessionUpdateListener(false) is called). The page is still displayed, but I can no longer interact with it, including stopping the app.
I'm wondering if this is by design, a bug, or am I doing something wrong?
Here is the code to my custom receiver...
<html>
<head>
<title>Hello World Chromecast App</title>
<style type="text/css">
*
{
color: white;
}
</style>
</head>
<body>
<div>Hello World!</div>
<script src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
<script type="text/javascript">
window.onload = function () {
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
window.castReceiverManager.start();
}
</script>
</body>
</html>

The trick is that you need to call start after creating a message bus. Once you do that then the session will stay alive on the sender.
<script type="text/javascript">
(function () {
var mgr;
var bus;
window.onload = function () {
mgr = cast.receiver.CastReceiverManager.getInstance();
bus = mgr.getCastMessageBus('urn:x-cast:com.sample.hello');
mgr.start();
}
})();
</script>

In order to exchange messages between sender and receiver, you need to define a communication channel and protocol (namespace) to do so.
You can use MediaManager to do this for you when the protocol to use is media related (LOAD, PLAY, PAUSE...) or you can create your own. MediaManager creates a CastMessageBus under the hood.
To create your own communication channel and protocol, you need to get either a CastMessageBus or a CastChannel.
If you do not register any communication channel and protocol (namespace), then the sender is going to be unable to communicate with your application.
For a sample receiver look at TicTacToe. As you can see it creates its own CastMessageBus to exchange JSON messages:
TicTacToe.PROTOCOL = 'urn:x-cast:com.google.cast.demo.tictactoe';
this.castMessageBus_ =
this.castReceiverManager_.getCastMessageBus(TicTacToe.PROTOCOL,
cast.receiver.CastMessageBus.MessageType.JSON);
The protocol is just a unique string, starting with 'urn:x-cast:' that you can define and must be used by the receiver and the sender to identify the protocol.

This is by design. You have two options:
1) Create a media manager.
window.mediaElement = document.getElementById('receiverVideoElement');
window.mediaManager = new cast.receiver.MediaManager(window.mediaElement);
OR ...
2) Create a custom namespace for message bus.
// create a CastMessageBus to handle messages for a custom namespace
window.messageBus =
window.castReceiverManager.getCastMessageBus(
'urn:x-cast:com.google.cast.sample.firework');
Otherwise your receiver terminate sender session. Note that casting action still works without either of the above conditions being met but there is no way for sender to communicate further with receiver.

Related

PubNub keeps receiving one message over and over

Just started with PubNub, and seems that I fail to understand even the simplest possible scenario. I created the following test page:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.15.1.js"></script>
<script>
const pubnub = new PubNub({
publishKey : '<guid>',
subscribeKey : '<one more guid>'
});
pubnub.subscribe({channels: ['3']});
pubnub.addListener({
message: v => {
console.log("on message", v);
},
});
function onClick() {
pubnub.publish({channel: '3', message: 'foo'});
}
</script>
</head>
<body>
<button onclick="onClick()">start</button>
</body>
</html>
Opening it with latest Chrome and clicking "start" button will result in test message being received endlessly over and over. I was under impression that after single client receives a message from a bus, this client will not receive it again. why such behaviour? I understand that I can read all the docs and most probably answer is somewhere deep inside, but tutorial + quickstart gives no clues, and rest of docs are quite huge.
Your example code works perfectly for me. The message published is received one time on the channel "3". One way to validate this is to simultaneously have the PubNub Console open (https://www.pubnub.com/docs/console). Make sure you enter your Publish and Subscribe keys into the console, along with the channel "3". After clicking the "Subscribe" button in the PubNub Console, you should see your test message "foo" appearing once in the "messages" section at the bottom each time you click the "start" button on your test page.
I can see that you're using the latest SDK-JS V4 (perfect starting point)
Your code works!
I would like to point you to a bit of a diff way to init PubNub and few functionalities.
(which are available in their docs)
Please look at the attached link to view my PubNub demo
<script type="text/javascript">
console.log('init PubNub.');
pubnub = new PubNub({
publishKey: 'demo',
subscribeKey: 'demo',
uuid: 'myDemo'
})
console.log("addListener..");
pubnub.addListener({
status: function(statusEvent) {
if (statusEvent.category === "PNConnectedCategory") {
console.log("PNConnectedCategory..");
publishSampleMessage();
}
},
message: function(message) {
console.log("New Message!!", message.message);
},
presence: function(presenceEvent) {
//handle presence
}
})
console.log("Subscribing..");
pubnub.subscribe({
channels: ['myDemo']
});
function publishSampleMessage() {
console.log("Since we're publishing on subscribe connectEvent, we're sure we'll receive the following publish.");
var publishConfig = {
channel: "myDemo",
message: "I'm here, I'm alive!!"
}
pubnub.publish(publishConfig, function(status, response) {
console.log(status, response);
})
}
function onClick() {
publishSampleMessage();
}
</script>

Trying to understand Socket.IO - socket and emit

I'm trying to understand Socket.IO, but i need help.
I'am looking at the Socket.IO docs and found this piece of code:
var io = require('socket.io')();
io.on('connection', function(socket){
socket.emit('an event', { some: 'data' });
});
Source: http://socket.io/docs/server-api/#socket#emit(name:string[,-…]):socket
Coming from an Object-oriented programming background, i understand that the first line "imports" the Socket.IO library. Furthermore it "creates an instance" of socket.io which is saved as the variable io.
But what does the the next two lines do? What is this io.on, what is 'connection', what is the origin of the parameter socket, and what does this mean: some: 'data'?
But what does the the next two lines do? What is this io.on, what is
'connection', what is the origin of the parameter socket, and what
does this mean: some: 'data'?
Let's go through your code line by line and explain:
var io = require('socket.io')();
io.on('connection', function(socket){
socket.emit('an event', { some: 'data' });
});
First, the line:
var io = require('socket.io')();
This line does three things. First, it loads the module with require('socket.io'). Second, it calls the constructor on the returned module with the () at the end. Then, it assigns the return result from the constructor to the variable io. Per the socket.io documention, calling the constructor in this way starts up a web server on the default port 80 that is listening for incoming socket.io connections. The return result of the constructor is the socket.io server instance (in the io variable) that can be used for future socket.io operations.
Then, the line:
io.on('connection', function(socket){
The .on() method on the socket.io instance is a generic way of registering event handlers. Once you get to know node.js in more detail, you will recognize this as an EventEmitter interface and, in fact, the socket.io instance is a subclass of EventEmitter. So, with this particular .on() method call, you are registering an event handler for the 'connection' event.
Socket.io will call the connection event any time a new socket.io connection is established with your socket.io server. This is your way of getting notified any time a new client connects. Per the socket.io documentation, the callback you pass for that event will be passed one argument which is the socket object associated with the newly established connection. This event handler allows you to see each new socket.io connection right when they are first connected.
Then, the line:
socket.emit('an event', { some: 'data' });
This says that when a new connection is established, you want to immediately send that new socket a message. In socket.io a message consists of two parts - first, the message name and second some optional message data. In this particular case, the message name is 'an event'. Message names must be a string, but you can make them pretty much any string name you want (I think there may be a few reserved names such as ping and pong, but other than that, this is entirely up to you to make up a message name. In order to receive a message that you server sends , the client on the other end of the connection will just need to listen for the exact same message name that you send here.
The second argument to .emit() is optional and can be some data that you want to send with the message. Here's a simpler example to illustrate:
socket.emit('setColor', 'blue');
This sends the 'setColor' message and sends the data "blue" with it so that the receiving client knows what color it should be set to.
The data can be any Javascript data that can be properly represented in JSON. Because you can't actually send live Javascript objects or arrays over a network, those objects are serialized into the JSON format and then sent as text. The receiving client will deserialize it and turn it back into whatever data type it was supposed to be. So, in your specific example, it was doing this:
socket.emit('an event', { some: 'data' });
That was sending a Javascript object. The { some: 'data' } syntax in Javscript is the declaration of an object literal. In this particular case, this is a Javascript object that has one property with the name some and the value of that property is 'data'. This is obviously just for example purposes as a real application would likely have more meaningful data such as:
socket.emit('format', {fontSize: 16, color: 'blue', type: 'san serif'});
Then, the receiving client would get a Javascript object with all three properties on it fontSize, color and type.
Then, the line:
});
This just closes off the io.on(... line that was started before.
io.on('connection'... basically tells Socket.io to listen on this event. When socket.io establishes a connection, we execute the callback:
function (socket) { ... }
The next line:
socket.emit('an event', { some: 'data' });
tells socket.io to emit, or send an event through the pipeline with the name an event as well as the data { some: 'data' }. If you understand how events work in jQuery or regular old js, then this flow would be familiar. Here's an example in jQuery
// listening for the click event
$('.foo').click(function (e, data) { // data is equal to foo
alert('clicked');
return false;
}
and for triggering (emitting)
$('a').trigger('click', [ 'foo' ]);

Communicating between two chrome extensions

I am trying to communicate between two chrome extensions, but unable to do so.
Any help would be great in resolving this issue.
1st extension sending msg in background.js:
chrome.browserAction.onClicked.addListener(
function(tab)
{
chrome.runtime.onConnect.addListener(function(port)
{
port.postMessage({status:"hello"});
});
2nd extension receiving msg in background.js:
var port = chrome.runtime.connect({name: "lkddmaimhocofkfhngkdhdicmldnfdpn"});
port.onMessage.addListener(function(message,sender)
{
alert('listened bg');
});
It seems you are confused with the sending part and receiving part.
Also, there are some differences between onConnect
which fires when a connection is made from either an extension process or a content script,
and onConnectExternal
which fires when a connection is made from another extension.
Take a look at Message External and you can use the following sample code to communicate between two extensions.
1st extension sending msg in background.js:
chrome.browserAction.onClicked.addListener(function() {
var port = chrome.runtime.connect("lkddmaimhocofkfhngkdhdicmldnfdpn");
port.postMessage(...);
});
2nd extension receiving msg in background.js:
chrome.runtime.onConnectExternal.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// Handle your msg
});
});

How to disable Multiplexing with Socket.io

I am using Socket.io to stream live tweets to my users using Twitter's Streaming API (my implementation is more or less based on this tutorial).
The problem is that every time a connection event is fired by Socket.io the newly connected client causes every other client connected to the server to cease updating. While it would take too long to go through all the hacks that I tried, I will say that I played with it enough that I believe the problem is caused by Socket.io's multiplexing of the connections from multiple clients (enabled by default) as a performance boost to allow multiple clients or connections to share the same underlying socket. In short, I believe this to be the case because I don't think it would be possible for new connections to affect older connections in this manner if not for the connection multiplexing. In other words, if a new, independent connection with its own underlying (TCP) socket were created every time a client connected it would be impossible for this to occur since one connection would know nothing about the other and therefore couldn't affect any other client's state as is currently happening. This also leads me to believe that simply disabling the multiplexing functionality would be the simplest way to get around this problem since I am not concerned about scaling because Node.js already handles all the concurrency I'm likely to need to handle very adequately.
I have gone through Socket.io's documentation but could not see where the ability to "demultiplex" the connections is exposed via the API, so if anyone knows how to do this I'd create appreciate your response.
My code below is pretty standard and simple. But just to be clear, the issue is that whenever a new client connects to Socket.io every other client stops receiving new tweets and updates are no longer pushed to the older client unless I refresh the browser in which case the newly refreshed client will begin to update and receive fresh tweets again, but the other still connected clients will then stop updating.
Server-side Code:
// Code also uses ntwitter (https://github.com/AvianFlu/ntwitter) as an abstraction over Twitter's Streaming API
io.sockets.on('connection', function (socket) {
tweet.stream('statuses/filter', { track : 'new orleans' }, function (stream) {
stream.on('data', function (data) {
// The following lines simply pre-process data sent from Twitter so junk isn't
// unnecessarily sent to the client.
if (data.user) {
tweets = {
text : data.text,
image : data.user.profile_image_url,
user : data.user.name
};
var t = JSON.stringify(tweets);
console.log(t);
socket.send(t);
}
});
});
});
Client-Side Code
// Notice the option that I passed in as the second argument. This supposedly forces every
// new client to create a new connection with the server but it either doesn't work or I'm
// implementing it incorrectly. It is the very last configuration option listed in the
// documentation linked to above.
var socket = io.connect('http://' + location.host, {'force new connection' : true });
socket.on('message', function (tweet) {
var t = JSON.parse(tweet);
if (t.image) {
$('.hero-unit').prepend('<div class="media"><a class="pull-left" href="#"><img class="media-object" alt="64x64" style="width: 64px; height: 64px;" src="' + t.image + '"></a><div class="media-body"><h4 class="media-heading">' + t.user + '</h4>' + t.text + '</div></div>');
}
});
If I am thinking of this incorrectly or if there's something wrong with my code I am definitely open to any suggestions. I'd also be happy to reply with any additional details.
I would try something like this
Serverside:
io.sockets.on('connection', function (socket) {
//Other Connectiony goodness here.
});
});
tweet.stream('statuses/filter', { track : 'new orleans' }, function (stream) {
stream.on('data', function (data) {
// The following lines simply pre-process data sent from Twitter so junk isn't
// unnecessarily sent to the client.
if (data.user) {
tweets = {
text : data.text,
image : data.user.profile_image_url,
user : data.user.name
};
var t = JSON.stringify(tweets);
console.log(t);
io.sockets.emit("tweet", t);
}
});
Client-side:
var socket = io.connect('http://' + location.host, {'force new connection' : true });
socket.on('tweet', function (tweet) {
var t = JSON.parse(tweet);
if (t.image) {
$('.hero-unit').prepend('<div class="media"><a class="pull-left" href="#"><img class="media-object" alt="64x64" style="width: 64px; height: 64px;" src="' + t.image + '"></a><div class="media-body"><h4 class="media-heading">' + t.user + '</h4>' + t.text + '</div></div>');
}
});
Basically have the stream from twitter outside your socket, and then on a new tweet emit a message to all connected.

How send dynamic data from contentscript.js to background.html

I'm trying to write a simple Google chrome extension. But when I try to send some dynamic data from contentscript.js to background.html, I get no result.
There is no problem with sending static data.
here is the background.html:
<html>
<head>
<script>
chrome.extension.onRequest.addListener(function(request) {
alert(request.text);
});
</script>
</head>
</html>
and here is the conentscript.js with static data that works fine:
var req = {"text": "salam"};
chrome.extension.sendRequest(req);
and this is contentscript.js that doesn't work:
var txt = getSelectedText();
var req = {"text": txt};
chrome.extension.sendRequest(req);
any help is welcomed.
When you pass an object via request you don't pass a reference to it, as with regular functions. This object is actually getting serialized into a string before a request, passed as a string, and then assembled back from a string in a background page (that's why you can't pass anything in a request that cannot be serialized). All references are lost in the process.
You probably would need to rethink your extension architecture to accommodate this.

Resources