Skinning for Kodi

23 May, 2015

Kodi, formerly known as XBMC is one of the best pieces of software to manage rich media and drive your home theatre PC(HTPC). The list of configurable options is impressive and it is open-source, actively maintained and has a six monthly release cycle.

That said, one aspect of Kodi is the ability to customize the look and feel. There is a very active skinning community that maintains the Wiki dedicated to resources. However, it is very disorganized.

Begin by downloading Kodi

  1. Head on to Kodi's download section and download the version of Kodi based on your OS. This post will focus on a Mac setup.

  2. While I haven't had complete success with the Confluence skin, the official Skinning Wiki recommends it, so I will go along with that.

Modify the keymap

One of the very first things you want to do is add the ability to reload the skin. You will want to refresh the skin to preview changes.

  1. You want to create the keymap.xml file. Place this file in /Users/<your_user_name>/Library/Application Support/Kodi/userdata/ This is where Kodi on Macs reads the key bindings for keyboards and other input devices.

  2. Grab a sample keyboard.xml file from here and paste the contents into the file you created in step 1.

  3. You want to place the key binding to reload the skin in the global node.

1
2
3
4
5
6
7
8
9
<keymap>
  <global>
    <keyboard>
      <f5>ReloadSkin()</f5>
      <!-- Additional keybindings -->
      <!-- ... -->
    </keyboard>
  </global>
</keymap>

Gaming on the PC, the PC way

27 April, 2015

Recently, I upgraded my nVidia 780 Ti to a pair of R9 290Xs.

I purchased a PS3 with my first salary back in 2010, mostly for it's exclusives - God of War 3, Uncharted 2, Killzone 2. Actually, I solely bought it to play the God of War franchise. And now, looking back at the catalog for both the Xbox One and the PS4, I can say that God of War 3 was the Playstation franchise's swan song, at least for me. It was the single player campaign lover's reprieve before the gaming world diffused into the cacophony of MMORPGs and online-only games.

I owned an Xbox One for a couple of months, before being disillusioned by the exorbitant prices for games, the lack of any good first-party titles, the poor graphical prowess and the back-pedaling over Kinect, which I paid a premium for. The Kinect had potential, which Microsoft squandered recklessly. I traded it in with Amazon and with the money I earned I set out to build a perfect gaming PC for myself.

I started with a micro ATX case, an AMD 6300FX processor, and a GTX 760. After random reboots, blue screens of death and poor in-game performance. I switched to Intel, a Core i5 4670 and an ATX Gigabyte Gaming 7 motherboard; I also upgraded to a GTX 780 Ti. The 780 Ti opened the doors to many a 1080p/60FPS gaming sessions. It is a versatile card, and if it wasn't so expensive, I would have preferred to use another 780 Ti in a SLI configuration.

The best parts of gaming on the PC are comprehensively documented on several parts of the internet. For me, it has to be Steam; a single place for managing my entire game catalog. I am neutral on the Steam sales, because after you go on the initial buying frenzy, you do end up in a situation where you already own most, if not all of the games offered in those sales. However, the said Steam sales are a steal when they happen. As of May 2015, GoG Galaxy; a DRM-free platform for content distribution, primarily games, and an alternative to Steam launched it's open beta.

I also appreciate the bump in display resolution on the PC side of gaming. With the currently available crop of graphics cards, you can comfortably play games at 2500 x 1440 with a steady 60fps, with the graphical fidelity turned all the way up.

The entire debate in the console realm over 1080p vs 900p is a non-factor in the PC side of things.


Dual Radeon R9 290xes

With two R9 290x cards in Crossfire, my baseline resolution has moved up to 2560 x 1440. When I get a 4K (or the next reasonable evolutionary step in resolution) display, I will be able to utilize the dual card configuration in a manner appreciable to the computing power they hold.

For now, I enjoy a staggering 3200 x 1800 resolution for most of the games out there including Grand Theft Auto V as of May 2015, with the antialiasing turned down. Although sitting 6 feet away from the TV screen and a non-20/20 vision don't really help me appreciate the full extent of the visual splendor, I am able to discern details which were never achievable on consoles. This would be a moot point however, if I continue to think that my current configuration is future-proof.

The successor to 290x will be announced this year. nVidia will also announce the next card to replace the GTX 980. This is a mere six months after I bought the 780Ti, which at the time, was already a year old. To keep up with the pace at which these units are introduced and phased out would be an exercise in futility. You are better served to set your expectations accordingly and figure out what level of fidelity and frame-rate you are comfortable with. Most importantly, always consider the ratio of price to performance. It is almost never wise to go with the flagships, mostly because of the ridiculous launch price; but also because a slightly underpowered unit will launch alongside it, which will be just as performant and sufficient for your needs.

The value of researching what suits your gaming tastes can never be undermined. That said, if you are a PC gamer, you already know that.

Clover, Handoff and Continuity in Yosemite

01 April, 2015

In the Hackintosh realm, there are two prominent and extensively covered methods for installing OS X:
Clover and Chameleon At a very high level, both methods are created with the intent of installing OS X on PCs while using a combination of kext patches in case of Clover and/or kext injection in case of Chameleon.

Assuming that you have done your research on the most compatible hardware, you will still be hard-pressed to get everything working out of the box. With the constantly changing landscape of Hackintosh development, you will always need to stay on top of the different ways to get your components working.

This post focuses on a couple of new features introduced in OS X Yosemite called Handoff, Continuity and Facetime calling. Handoff allows you to transfer the state of activity in certain applications from your iPhone or iPad to your Mac and vice versa. Continuity refers to the ability of forwarding phone calls to your Mac or Macbook. You can also make calls from your Mac/Macbook using your iPhone connection. This way, if your phone is in another room, you can still take the call or even make a call.

Needless to say, unless you are using a first-party, Apple-certified WiFi/Bluetooth card, you have to configure Clover to make your card appear first-party. This post focuses on the Azurewave CE123H mini PCIe WiFi/Bluetooth combo card.

In spite of the fact that I document the steps for a specific card, the concept applies to all supported1 cards. There is an excellent thread located here that covers a complete list of cards that will support Handoff and Continuity.

Before you venture any further in the process of applying kext patches in Clover, it is very important to make sure that your network interfaces are configured correctly so that en0 refers to the first built-in network interface. This is vital to get many OS X services such as Mac App Store, iTunes and Messages among others.

Past this, you need the following kexts in your EFI Partition > CLOVER > kexts > 10.10:

  1. BcrmPatchRAM.kext
  2. BTFirmwareUploader.kext
  3. FakePCIID_BCM943552Z_as_BCM94360CS2.kext
  4. FakePCIID.kext

You need these kexts to firstly, enable uploading of custom firmware, and present your card to OS X as a first-party card. Once you have these in place, you need to correct the locale in order to enable all WiFi frequencies.
To achieve that, open Clover Configurator, mount your EFI partition and import your config.plist file.

Then, in the Kernel and Kext Patches section add an entry:
For the US/FCC fix, apply the following to AirPortBcrm4360
+ Find: 41 83 FC FF 74 2C 48
+ Replace: 66 C7 06 55 53 EB 2B

For the Handoff/Continuity, apply this patch to IOBluetoothFamily:
+ Find: 48 85 C0 74 5C 0F B7 48
+ Replace: 41 BE 0F 00 00 00 EB 59

Save the config.plist file and then rebuild your kext cache using Kext Wizard
Reboot, and then log out of your iCloud account on your Hackintosh as well as your iPhone or iPad and log back in.

You should have Handoff and Continuity enabled.


  1. There is a specific set of cards that work with this approach. Research your selection before you purchase. 

My FreeNAS box is down. Currently investigating. Could be hardware failure. Lost about 2TB of data.

Fruitr got DDoSed pretty badly. It will be down till I rewrite it in Python and re-deploy.

Messages, Clover and Yosemite 10.10.2

22 February, 2015

UPDATE: This method is confirmed to work on El Capitan Public Beta You are not required to contact Apple to get Messages to work. Generating a new Serial Number for your Hackintosh and following the steps detailed in the guide will suffice

I built myself a mini-ITX Hackintosh for design and coding, as well as a little audio production.

This particular combination of hardware components can be quite functional and productive once you get everything working. You may find this information on other sites.1 I researched the forums on the said sites and collated information that might serve as a reference for others, with a similar configuration or help someone make a decision.

I am currently running Yosemite 10.10.2 with UEFI Clover.
Messages is working along with Handoff, Continuity, Instant hotspot and the ability to connect to my 5Ghz WiFi network.


Hackintosh with a Focusrite Scarlett 2i2 2 In/2 Out USB Recording Audio Interface

Specifications
Motherboard Gigabyte GA-H97-WiFi
Processor Intel Core i3 4350 3.6Ghz
Case Cooler Master HAF 915R
Graphics nVidia GTX 760 2GB
WiFi/Bluetooth Azurewave CE123H (based on Broadcom BCM4352 reference chipset)

I had to order the Azurewave CE123H card separately, because the included Intel WiFi/Bluetooth combo card does not work with OS X. This card is confirmed to support the Bluetooth 4.0 LE (Low Energy) standard that is used by Handoff and Airdrop features.

Using Clover, installing OS X Yosemite is relatively painless, if you do your research2.

Once you install Yosemite, you will notice that you cannot log into Messages using your iCloud account. Either that or you will encounter an activation error. Additionally, Bluetooth won't be functional, and you won't be able to see your 5GHz WiFi network. Some additional steps are required to get that functional.

I had the following kexts in my EFI > Clover > kexts > 10.10 to get Bluetooth and 5Ghz working. Apparently, these kexts enable the uploading of custom firmware and fake a PCI ID for OS X, so that it thinks that you are using a first-party card.

BrcmPatchRAM.kext, BTFirmwareUploader.kext, FakePCIID_BCM94352Z_as_BCM94360CS2.kext and FakePCIID.kext

  1. In preparation, you must first ensure that your Ethernet card is recognized as en0 in System Profiler. The true reason behind this is to follow the BSD convention. OS X services such as Mac App Store, iTunes Store and Messages as well as iCloud all require that en0 refer to the first, built-in network interface.

  2. Secondly, you need valid MLB and ROM values. These are invariably essential to getting Messages to work. MLB stands for Main Logic Board; and all Mac computers - laptops and desktops have a MLB, which is uniquely identified using a number. This MLB along with a valid ROM value is used for authentication by Messages. ROM here, refers to, or rather used to refer to the Mac's Firewire MAC address. You can use your network interface's MAC address, by going to System Preferences > Network > [Interface: WiFi or Ethernet] > Advanced

  3. Then, open Clover Configurator and mount your EFI partition. Import your config.plist file.

  4. In the SMBIOS section, click the magic wand and generate a SMBIOS that is closest to the configuration of your hackintosh. For example, my hackintosh has a Haswell Core i3, so I went with a iMac13,2. Make sure that you "shake" the values for the week of manufacture and the unit number fields. This will generate a random serial number, which you should check against Apple's database here. The serial number must be invalid, which indicates that it is unique.

  5. Past that, you must take care of the Board-ID, Board Serial Number, Serial Number and SmUUID

  6. In the Rt Variables section, paste the MAC address (without colons) that you obtained in step 2, into the ROM field. In the MLB field, enter the serial number you generated in step 4, and append 5 random hexadecimal letters, so your entire serial number is seventeen digits.

  7. Run the command uudigen in Terminal and paste that value in SMBIOS > SmUUID

  8. Board Serial Number should be the same as MLB

  9. With this, you should enter the appropriate kext patches in Clover's Kext and Kernel Patches to enable the correct locale for WiFi and enable 5Ghz support. I will recommend that you peruse the excellent and comprehensive guide for finding the correct patch for your wireless card here

  10. Run nvram -p in your Terminal and make a note of the values. These should remain persistent even after your restart. This essentially means that the MLB and ROM values, which are used to authenticate Messages will persist ensuring that Messages will be functional across multiple reboots.

  11. Save your config.plist and reboot.

XBMC/Kodi, you are awesome, but good god your skins need some work.

Playing voice memos in the background

02 December, 2014

I recently discovered a way to play voice memos in the background on my iPhone. Why they don't display this behavior by default is baffling to say the least.

There are several published hacks to do this, and most of them involve sharing the memo with yourself via Messages.

My method is somewhat similar to this one1 and involves the least amount of intrusion.

  1. Open Voice memos and play the memo.
  2. Lock the screen.
  3. Wake the phone using the power button.
  4. Slide up to go into the Camera app.
  5. Press the home button to return to home screen and you will notice that the memo is playing in the background.

If you have your own method that works for you, but involves more steps, you can add this one to your list. I tested this on iOS 8.1.1 (12B435)

I will just assume that Willem Dafoe is the lead singer for Powderfinger. That is my happy place.

mongoose, Mongo and JSON

23 October, 2014

I am working on a reporting app that is built on the Quickbooks Online API. It pulls in reporting information that needs to be saved to a local database. I am using Mongo as the data store and using the mongoose ODM with node.js

That said, I have a schema already defined like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports = mongoose.model('vbDetail', {

    company_name: String,
    rowsdata: {vals:
                {
                    date: Date,
                    transaction_type: String,
                    transaction_num: String,
                    due_date: Date,
                    amount: Number,
                    open_balance: Number,
                    balance: Number
                }
            },

    meta_rows: [{
        identifier: String,
        processing_date: Date,
        processing_amount :Date,
        notes: String
    }]
})

Saving the JSON to this is straightforward. It does look tricky to loop over certain nested objects1. But it is a matter of just getting the loops right.

The JSON response itself looks like this (truncated):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
{ Header: 
           { ColData: 
              [ { value: 'GunnChamberlain PL' },
                { value: '' },
                { value: '' },
                { value: '' },
                { value: '' },
                { value: '' },
                { value: '' } ] },
          Rows: 
           { Row: 
              [ { ColData: 
                   [ { value: '03/10/2014' },
                     { value: 'Bill' },
                     { value: '2341' },
                     { value: '03/10/2014' },
                     { value: '500.0' },
                     { value: '500.0' },
                     { value: '500.0' } ],
                  type: 'Data' },
                { ColData: 
                   [ { value: '04/30/2014' },
                     { value: 'Bill' },
                     { value: '4663' },
                     { value: '04/30/2014' },
                     { value: '450.0' },
                     { value: '450.0' },
                     { value: '950.0' } ],
                  type: 'Data' },
                { ColData: 
                   [ { value: '05/31/2014' },
                     { value: 'Bill' },
                     { value: '4878' },
                     { value: '05/31/2014' },
                     { value: '875.0' },
                     { value: '875.0' },
                     { value: '1825.0' } ],
                  type: 'Data' },
                { ColData: 
                   [ { value: '06/30/2014' },
                     { value: 'Bill' },
                     { value: '5115' },
                     { value: '06/30/2014' },
                     { value: '680.0' },
                     { value: '680.0' },
                     { value: '2505.0' } ],
                  type: 'Data' } ] },
          Summary: 
           { ColData: 
              [ { value: 'Total for GunnChamberlain PL' },
                { value: '' },
                { value: '' },
                { value: '' },
                { value: '2505.0' },
                { value: '2505.0' },
                { value: '' } ] },
          type: 'Section' }

The concept is to loop over the Rows object that corresponds to individual companies. Then, for each nested Row objects loop over the ColData object and save the values to the database.

Here's what the code for it looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
   //test
  for (var row in report["Rows"]["Row"]) {
      while (count < companies) {
          // save the rows corresponding to each client
          for (var rowdata in report.Rows.Row[count].Rows.Row) {
              for (var coldata in report.Rows.Row[count].Rows.Row[rowdata]
                  // save company name
                  var vbd = new vbDetail({
                      company_name: report.Rows.Row[count].Header.ColDat
                  });

                  // save the row data per company
                  vbd.rowsdata = ({
                      vals: {
                          date: report.Rows.Row[count].Rows.Row[rowdata].ColData[0].value,
                          transaction_type: report.Rows.Row[count].Rows.Row[rowdata].ColData[1].value,
                          transaction_num: report.Rows.Row[count].Rows.Row[rowdata].ColData[2].value,
                          due_date: report.Rows.Row[count].Rows.Row[rowdata].ColData[3].value,
                          amount: report.Rows.Row[count].Rows.Row[rowdata].ColData[4].value,
                          open_balance: report.Rows.Row[count].Rows.Row[rowdata].ColData[5].value,
                          balance: report.Rows.Row[count].Rows.Row[rowdata].ColDat
                      }
                  }) console.log(vbd);

                  // Save the record to DB
                  vbd.save(function(err) {
                      if (err) console.log(err);
                  })
                }
              count++;
            }
      }
}