Saturday, December 29, 2012

Pairing Bluetooth Keyboard on Windows and Linux using the same receiver

Found a solution on the web with authenticated connections here (the original description is far more detailed).

Short description (so that it is still available for me ;) ):

  1. Pair with (each) Linux
  2. Pair with Windows
  3. Extract authentication key from Windows from windows registry (stored in Windows/System32/config/system) using libhivex-bin
    hivexml system | perl -ane 's/</\n</g; print' | grep -i 'key="YOUR BLUETOOTH ID WITHOUT : "' 
  4. Decode the content of xml-entity with Base64
  5. Replace Linux authentication key with the extracteted version Linux /var/lib/bluetooth/RECEIVERID/linkkeys
  6. Restart Bluetooth service
    sudo service bluetooth restart

I can confirm that this works using Ubuntu 12.10 and Windows 8 with a Apple Wireless Keyboard.

Alternative solution without authentication (I WOULD NOT RECOMMEND THIS FOR A KEYBOARD) can be found here.

UPDATE: Still works with 13.04

Friday, December 28, 2012

HTML JS publish click-events to all childs

I have tables with one radio button per cell and its quite annoying to aim at the radio button completely...
<td onclick="for (var i in this.childNodes) 
if(typeof this.childNodes[i].click === 'function') 
    this.childNodes[i].click();">
  Just clickable text
  <input type="radio" />
</td>

Thursday, December 20, 2012

CSipSimple - Getting started to hack it (tailor to my needs)


Just one or two things I need to remember about CSipSimple:

Infrastructure
  • SipStack runs in background (communication via Parcable interface). It interacts with PJSIP.
    Important there is a watchdog timer (about 5s)!
  • pjsua.java, pjsuaConstants is the SWIG generated interface to PJSIP
  • Native functions never return boolean, check for pjSuaConstants.PJ_SUCCESS
  • Be aware of string exchange with the native stack: PjSipService.pjStrToString(...)
  • UAStateReceiver.java does the call creation and everything related to SipStack
  • PjSipService.java is deeply integrated with UAStateReceiver.java (for example does recording...)

UI
  • CustomDistribution.java defines some things for fast modifying the behavior
  • Main screen is created in SipHome.java (incl. the slidable tabs)
    To remove tabs, just disable tab.add (except for the warning tab and the message tab [message disable in CustomDistribution.java]: may be triggered from outside)
  • Notifications are handled in SipNotifications.java (but from Sip-Thread)
  • DialerFragment.java is the dialer incl. call button and account switcher...
    Here the re-dial functionality is missing... (press the call button twice without number should redial previous number)
  • InCallActivity.java :)
    Important call setup is done BEFORE launching the InCallActivity via SipManager.ACTION_SIP_CALL_UI from UAStateReceiver.launchCallHandler(...).
    There is even a activity start delay of 2000ms (UAStateReceiver.LAUNCH_TRIGGER_DELAY).
    I think it's not nice!!!! Because a user may hear sound of before the UI is ready, but there is might be a problem with race conditions...
  • InCallControls.java is the ui element on the bottom of InCallActivity to control Bluetooth and loudspeaker etc. (Deeply integrated with InCallActivity: sadly NO MVC...)
  • InCall.java is also related to Dialer

Saturday, November 17, 2012

Bluetooth Remote Control for Windows Media Center

After years of using my Bluetooth mouse to control Windows Media Center (WMC) from my couch - I figured out that I needed a proper remote control (actually I visited a friend who used the IR remote of WMC). After endless time of searching I found the PS3 remote (Sony employs Bluetooth *yeah*) and it works with WMC using a small program that translates the game controller HID events to actual keystrokes.

It is called PS3BluMote (SRC via github) and written by Ben Barron.
As Ben's website was not reachable, I compiled from using VS2012 - took me about 2min.

And it works perfectly - I only need to figure out good keymapping (WMC key shortcuts are available here). In fact, I recommend to use for play/pause, skip and volume control the windows events (in PS3BlueMote: Media_) and not the WMC shortcuts - in this way also VLC and other players can be controlled.

Here are some additional startup options for WMC: I created a shortcut to go to the music section directly.

PS: I use it on Windows 8 Pro with WMC

Friday, November 9, 2012

(Rails3) ActiveRecords: how to implement a constructor and init own attributes

Today I encountered two nasty things during Rails development. My idea was to create a model class (< ActiveRecord:Base) that on creation create the current timestamp.
It is not possible to override initialize (at least it is doing nothing) as it is an ActiveRecord:Base.

I found the callback after_initialize defined by ActiveRecord, which is however not the correct way anymore. You should use it in macro style (source).

The next problem is that ActiveRecord overwrites the accessors and because ruby is not using the accessors by default if you are in the object, it must be called explicitely.

This works for me:

class A < ActiveRecord::Base
  attr_accessible :a
  after_initialize :init
  def init
    @a = "a"
    self[:a] = "b"
  end
end

Wednesday, May 30, 2012

Using GoogleDocs as Team editor for Latex-files

We wrote our last project paper using Latex which creates very nice looking documents, but is absolutely painful to work in teams. Even using a code management system like SVN/GIT won't make it really comfortable as you don't have comments and see changes of other editors live.

So, we put our Latex document in GoogleDocs (simply copied the content into a New GDocs Text Document) and shared it with our team. We also formatted the document by applying GDocs styles to our Latex headings, so the text looks structured and easier to work with.

At first we simply copied the GDocs content to a local file and compiled it. In fact, the copy-and-paste task is really annoying and so we developed a small bash script that automatically downloads the latest GDocs version and compiles it locally. So, in any case you need to setup your latex tools correctly, but don't waste your time in the compilation step.

You only need to enable sharing by URL and from this URL copy the document id, which you need to download the file.

Here is the script:

wget -O soups-article.download "https://docs.google.com/document/export?format=txt&id=PLACE_YOUR_ID_HERE" && \
iconv -c --from-code=UTF-8 --to-code=ISO-8859-1 soups-article.download | sed 's/end{document}*/end{document}/' > myFile.tex && \
pdflatex myFile && \
evince soups-article.pdf &

Asterisk and MessageSend

We are using Asterisk (running on FreeBSD 9.0 port stock version: 10.0.0-rc2) as SIP registrar/proxy. We are using the Android softphone cSipSimple, which also provides SIP SIMPLE messaging functionality. To enable this on Asterisk add to sip.conf: accept_outofcallmessage=yes and outofcall_message=message (the name of the context handler).


However, we had some trouble setting up Asterisk to really do it. In the message-ctx Asterisk provides the information of the current message as variables/function: MESSAGE(to), MESSAGE(from) and MESSAGE(body).

(First problem)
The first problem is that MESSAGE(to) contains the complete address, e.g. sip:PHONENUMBER@SERVERIP. If you try to use this address asterisk sends the message to itself and complains on receive that their is no routing for the incoming message. So, we need to remove the @IP part using the CUT command from the TO and the FROM. Now we can send a message from one phone to another: MESSAGESEND(CUTED_TO, CUTED_FROM).
(Second probleme)
However, we cannot reply as the recipient got as sender address something like sip:UNKNOWN@SERVERIP.
In short use MESSAGESEND(CUTED_TO, CUTED_FROM <CUTED_FROM>) or as example MESSAGESEND(sip:1, SOMEBODY <1>). The first part of the FROM is the name shown to the user and the second part the reply to phone number (without sip:).


Here is our working context for messaging of the extensions.conf:

[message]

exten => _X.,1,Set(TO=${CUT(MESSAGE(to),@,1)})

exten => _X.,n,Set(FROM=${CUT(MESSAGE(from),:,2)})

exten => _X.,n,Set(FROM_PHONE_NUMBER=${CUT(FROM,@,1)})
 exten => _X.,n,MessageSend(${TO}, ${FROM_PHONE_NUMBER}<${FROM_PHONE_NUMBER}>) 
 ;DEBUG Print the status of the MessageSend
exten => _X.,n,Verbose(0, ${TO} ${MESSAGE(from)} ${FROM} ${MESSAGE_SEND_STATUS}) 

Thanks to Nicolas.