24 January 2014

At home, I’m using a Raspberry Pi as media center with XBMC. It’s simple, works well, a bit slow, but for a Raspberry it’s not too bad (and the release 13 looks pretty good). Since the start, I’m using it with remotes like XBMC clients on iOS, Android or webapp. It’s great, but, not brilliant. Because you need many steps before to access to the commands. If you’re using your phone, you have to change app, wait the connection then do what you want… too much steps: not ergonomic at all.

The need of a proper remote was there. Unfortunately I couldn’t use the remote of my TV via HDMI. My TV is not powerful enough for this kind of things.

For Christmas, I went back home, and something reminded me I had a Wiimote. After few searches, yes! I can use it via Bluetooth to control my Raspbmc. I followed some tutorials, the thing doesn’t seems complicated. 20 minutes later, it’s working!

Actually, the XBMC distribution is ready to use a Wiimote, it’s using a package called WiiUse, a briliant library to use a Wiimote.

The problem, because there’s always a problem. After 6-8 hours, your batteries are dead. I loved too much this solution, so I had to investigate and find a solution. Google didn’t helped me about that, well, at first I had to discover they were using this library. Many searches without results, then a keyword bring me to a piece of code from this library. That was a comment about the function DisableMotionSensing. At that point, I realised the Wiimote was constantely sending motion sensor informations, it explains why the battery is flat after few hours. In our case, we just want the button actions, we don’t mind about the accelerometer or the IR sensor.

I had what I needed, a reason, and a part of solution (: DisableMotionSensing). Let’s have a look to the code and add this function just after connection:

Wiimote_Wiiuse.cpp

int connectWiimote(wiimote** wiimotes) // line 115
{
  int found = 0;
  int connected = 0;
  wiimote* wm;
  ...
  if (connected)
  {
    EventClient.SendHELO(\"Wii Remote\", ICON_PNG, NULL);.
    wiiuse_set_leds(wm, WIIMOTE_LED_1);
    wiiuse_rumble(wm, 1);
    wiiuse_set_orient_threshold(wm,1);
    <strong>DisableMotionSensing(wm);</strong>
    #ifndef WIN32
      usleep(200000);
    #else
      Sleep(200);
    #endif
    wiiuse_rumble(wm, 0);

    return 1;
  }
  return 0;
}

int main(int argc, char** argv) // line 195
{
  ...
  for (int i = 0; i < MAX_WIIMOTES; ++i)
  //MAX_WIIMOTES hardcoded at 1.
  {
    <strong>DisableMotionSensing(wm);</strong>
    switch (wiimotes[i]->event).
    {
    case WIIUSE_EVENT:

      controller.get_keys(wm);  //Load up the CWiiController
      controller.handleKeyPress();
      if (!controller.m_buttonHeld && (controller.m_holdableHeld || controller.m_repeatableHeld))
      {
        //Prepare to repeat or hold. Do this only once.
        timeout = getTicks();
        <strong>// EnableMotionSensing(wm);</strong>
        controller.m_abs_roll = 0;
        controller.m_abs_pitch = 0;
        controller.m_start_roll = 0;
        controller.m_start_pitch = 0;
      }
      if (controller.m_buttonReleased)
      {
        DisableMotionSensing(wm);
        controller.m_currentAction = ACTION_NONE;
      }
    ...
}

After that you can recompile, restart, connect your Wiimote. I’ve mention no particular issues, it’s seems to work well, and the batteries last longer.

If you had the same problem, I hope I helped you. Contact me if you have any questions.

permalink

30 December 2013

Arte is a franco-german TV channel, not one of the most popular in France but certainly the most interesting one, my favorite. The problem is now, I live in London, so I cannot watch this channel anymore. Even if in France I wasn’t watching it on TV but on demand on my computer. The problem is, like the BBC player for british people, outsite of the territory you cannot watch your TV shows because of geographic restrictions. This famous: “This video is not available in your country”.

I do not like that, and nobody does.

The thing is, I know the position checking is never made by the video stream connection. I can guess the mess to manage that with RTMP connections, ouch! So something might be doable on the client side. In the worst case: with a proxy.

After some analysis of the arte player, I found what I was looking for: the geolocalisation.js script. This is loaded at the start via https and respond bloc of functions. These methods are returning data about the client : ip address, time restriction, request date and the geographic zone codes.

geolocalisation.js

function arte_geoip_ip() {
  return 'XXX.XXX.XXX.XXX';
}

function arte_geoip_country_code() {
  return 'GB';
}

function arte_geoip_country_name() {
  return 'United Kingdom';
}

function arte_geoip_zone_codes() {
  return new Array('SAT', 'ALL');
}

function arte_time_time() {
  return 'Tue, 31 Dec 2013 18:44:11 CET';
}

function arte_time_timestamp() {
  return 1388511851631;
}

function arte_time_protection() {
  return 'youth';
}

My first thought was : “Oh come on, that’s too easy, it’s not possible”. My idea was to make this request from french IP address to see the differences (at that point you say thanks to your French nerdy friends, yay I’m too lazy to do it via a proxy). Not surprising, the array returned by arte_geoip_zone_codes contain more keys.

Time to test! I put a simple breakpoint at the end of geolocalisation.js with devtools. Refresh the page. Inject the code from the french request, then continue. Ta-daahh! The player is workAt the moment, that was great, I could watch the latest ‘Tracks’ (a brilliant program from Arte). But if I have to do that all the time, for every video… no. As developer, I’m a lazy ass. If I have to repeat the same task, I build the thing which will automise everything. So that was the best occasion to try to make a Chrome extension. It’s not that complicated, really powerful, and I don’t need to push the app to their store to let people use it. My only mistake was to inject a script after geolocalisation.js in every player DOM via a script link. I didn’t know the page had script origin restriction, but fortunately no one on inline scripts. So I’ve updated my code and the magic came.

You can have a look on plussept to see the code, even if it’s small and far to be a good example. You can also check https://extensionizr.com/ to begin to build your own extension.

permalink

19 December 2013

I’m using more and more nodejs as webserver. So easy to use and so lightweight. But when you need to execute a piece of script for a frequent request, you have to be performant.

My concerns were about the data verification from user. To explain, in my project, at some point the server is just a data relay between two machines. But to avoid any wrong use, I check if the data transmitted is correct. This data arrive as a json string, representing an object with a specific structure, it never change (and I don’t want any malicious code or bad values included).

So I was wondering, what would be the most performant to check? Using a RegExp to check the json, or parse the json and check if the content is valid?

To test, I wrote the piece of code below. It’s quite simple, it execute 20000 times both sceniarios. One half with correct data, an other one with invalid data. Then console.time help to display the execution time of each scripts.

/**
 * Perf test
 *
 */

// 0. Init
var i;
var correct_data = '{\"foo\":\"trololo\",\"bar\":42}';
var wrong_data = '{\"foo\":\"trololo\",\"bar\":42.0}';

// 1. The regexp
console.time('Regexp process');

var regexp_key = /^\\{\"foo\":\"[a-zA-Z]*\",\"bar\":[0-9]+\\}$/;
var regexp_obj = new RegExp(regexp_key);

for (i = 0; i < 10000; i++) {
  // regexp_obj = new RegExp(regexp_key);
  regexp_obj.test(correct_data);
}
for (i = 0; i < 10000; i++) {
  // regexp_obj = new RegExp(regexp_key);
  regexp_obj.test(wrong_data);
}

console.timeEnd('Regexp process');

// 2. The JSON parsing
console.time('JSON parsing process');

var jsonObj;
function checkObj(obj) {
  if (!obj) return false;
  if (!obj.foo || typeof obj.foo !== 'string') return false;
  if (!obj.bar || typeof obj.bar !== 'number') return false;
  return true;
}

for (i = 0; i < 10000; i++) {
  jsonObj = JSON.parse(correct_data);
  checkObj(jsonObj);
}
for (i = 0; i < 10000; i++) {
  try {
    jsonObj = JSON.parse(wrong_data);
    checkObj(jsonObj);
  }
  catch(e) {}
}

console.timeEnd('JSON parsing process');

You can try this code with Chrome, it’s easy. Copy the code, open the ‘Tools for developers’, go to the tab ‘Console’, then paste the code and press Enter. The script will be executed and you’ll see the output underneath.

On my machine, I got this. (results may vary between machines)

Regexp process: 17.889ms
JSON parsing process: 37.171ms

We can see the RegExp is quicker to execute. But there’s a problem. In my case, we just create one instance of this RegExp, and it might not be the case in reality, it depends of the implementation. So let’s make an other try with a new RegExp instance for each test (uncomment line 18 and 22).

Regexp process: 223.234ms
JSON parsing process: 39.507ms

Boom!

Here we are, the game has changed, and json parsing become the winner, by far!

Finally, always being careful of the context, it can change everything. And gosh damn! I didn’t know creating RegExp was so heavy!

permalink

24 November 2013

Sometime I try to understand the choices of html5 implementation. Simply because of a function, which makes me laugh, it’s ‘canPlayType’. This method is made to check if the browser can read a specific video codec. It sounds useful, especially when the most popular format is not open source. The problem is what we get: three possibilities : “”, “maybe” or “probably”. Yay! That’s very helpful, very helpful.

videoTag = document.createElement('video');
videoTag.canPlayType('video/webm; codecs="vp8.0, vorbis"');
> "probably"
permalink

16 November 2013

This weekend, I’ve decided to repair my YLOD PlayStation 3, for the third time. I was seeing it taking the dust, weeks after weeks, and I couldn’t force myself to throw it away. Especially when you know that just one component is not working. So let’s take few hours and let’s begin the surgery.

Electronic board for touch buttons (power and eject)

To explain the problem a YLOD (Yellow Light Of Death) is a problem on first generation PS3 (around 0.5%). The CPU and/or GPU is desoldering from the motherboard. Result, the console switch to secure mode and block the the system. When you turn it on, you have a triple bip and a yellow led blinking, then back to sleep. Love and joy. No I’m kidding, at that point you scream bad things about Sony Corporation.

Unfortunately this time, I had no heat gun. Giving me only one solution : the oven. Yes, the oven. The idea is simple, here is the recepe:

YLOD PlayStation 3 Serve 1-4 (depends of your games and amount of controllers) 2-4 hours Suitable for vegetarians

Ingredients:

  • 1 YLOD PS3
  • 1 Oven
  • Foil
  • Thermal paste
  • Good choice of general screwdrivers

Dismantle your PlayStation, be careful to group all the blocks and screws to recover it later, and feel free to say ‘sh*t!’ everytime you break something. Of course the motherboard is the last item, otherwise it would be too easy. I recommend you to go on ifixit for further help. Once you have the masterpiece in your hands, clean the CPUs and cover sensitive plastic parts with foil, like the optical drive connector, to protect it from direct heat. I think it’s useless, it’s just psychological. Now you can preheat your oven at 240°C for 10 minutes, then put your motherboard in it for 12 minutes. Once you can smell the delicious perfume of toxic plastic, it’s time to stop the oven. Open the oven door to let the motherboard cool for 30 minutes. Warning, do not move the cake, let it cool in the oven, or you could damage it. Now you can apply a new thermal paste on the CPUs, then recover the PS3.

Plug-it, pray, turn it on.

If a green led appear and the display on your TV is ok: congratulation, your PlayStation is alive.

If you see an explosion and flames coming out of the PS3: you might have forgot or missed a step. Please unplug safely then begin to think about your mistake. I also recommend to take care of the flames first, before to tweet anything about it.

For the record, mine is working but I’m thinking about a good system to keep it cool before to use it, otherwise it will break quickly. I’ll put an update for when it will break.

permalink