Dec 30, 2016

Simplified way to get Shairport-sync works in your raspberry pi

The tutorial here is quite straight forward.
Sometimes you do need "fast-track" to get something done right away.

For deep diving purpose, please head to https://github.com/mikebrady/shairport-sync for full (useful) explanation about the setup.

The steps below was tested and might only work for:
- New installation (with no shairport-sync installed before)
- Raspbian (version 8, Jessie) check with cat /etc/os-release
- no external sound card attached (my case)
- tested on streaming through iTune from Macbook (macOS Sierra, 10.12.1)

I'm too will look for the simplest (easiest) approach first, so don't guilt about it, let's get start.
  1. As usual, update your rpi first
    1. sudo apt-get update & sudo apt-get upgrade
    2. sudo rpi-upgrade
  2. Install dependencies,
    1. sudo apt-get install build-essential git autoconf automake libtool libdaemon-dev libasound2-dev libpopt-dev libconfig-dev libpolarssl-dev libssl-dev avahi-daemon libavahi-client-dev
  3. Download/clone shairport-sync and configurations
    1. git clone https://github.com/mikebrady/shairport-sync.git
    2. cd shairport-sync
    3. autoreconf -i -f
    4. sudo ./configure --sysconfdir=/etc --with-alsa --with-avahi --with-ssl=openssl --with-metadata --with-systemd
    5. sudo make
    6. sudo getent group shairport-sync &>/dev/null || sudo groupadd -r shairport-sync >/dev/null
    7. sudo getent passwd shairport-sync &> /dev/null || sudo useradd -r -M -g shairport-sync -s /usr/bin/nologin -G audio shairport-sync >/dev/null
    8. sudo make install
    9. sudo systemctl enable shairport-sync
    10. sudo update-rc.d shairport-sync defaults 90 10
I've got the shairport-sync working well in my Debian build raspberry pi
And hope to add more explanation about the steps above once I manage to spend more time playing shartport-sync in the rpi.

You should visit the references below:
A guide from setting up WiFi to shairport-sync - Multiroom audio Rpi (2015)
Use of shairport (earlier version of shairport-sync) and mentioned alsamixer - hifi audio via airplay on Rpi (2013)

Oct 27, 2016

Apache not loading PHP after SierraOS upgrade (Homebrew way)

Had a hard time dealing with Apache Server + PHP on my Mac right after SierraOS upgrade.

I use homebrew to get my Mac run with latest PHP7 version instead of directly messing around with the original library come with the SierraOS.

Firstly, the latest update of homebrew, PHP module has no longer installed with Apache.
You need:
brew install php70 --with-apache
in order to download the PHP with libphp7.so 
(this is the file you need when you use apache to load php module)

2nd, after you have Apache downloaded with your PHP through homebrew.
All the manual configurations, by default,
have to be done inside /usr/local/etc/apache2/2.4 (yours might be 2.2, based on your installed version).
Remember those httpd.conf, httpd-vhost.conf, etc... they're all inside the /usr/local/etc/apache2/2.4 folder?

and add a missing media type to your mime_module which it's the most obscure step (to a beginner like me) to missed out during configuration.
AddType application/x-httpd-php .php
Symptom check (whether or not to add the line above):
- php module is loaded correctly, but plain php code still showing in your localhost, for instance, php_info() doesn't work

- your sudo apachectl configtest show nothing wrong "Syntax OK"

Apr 21, 2016

Unit test for Directive with template - AngularJs

As we are adding unit test for directive, its implementation can vary from simple to very complex.
The complex implementation require more knowledge about how to write deeper test in order to get better tested coverage.

To start testing you'll need to start with $compile of DOM element, link function, to angular's controller or anonymous function controller, to template...  

Here are the sources to learn about writing directive's unit test.

  • very interactive and straight forward Directive Unit Testing Guide
  • covered topics
    • "setup karma.config.js"
    • "how to start testing directive", 
    • "working with template" (ng-html2js processor)
  • has more thorough coverage of possible solutions required for Directive unit testing

2) Testing AngularJS directive controllers with Jasmine and Karma (1st tutorial) (2nd tutorial
  • Covered
    • setup sample karma.config.js
    • unit test of anonymous function as controller
    • make use of ng-html2js process
  • The best part of this tutorial is in "2nd tutorial" link, it provided sample of Directive using anonymous function as its controller
    • Testing with anonymous function as controller
      
      angular.directive('myDirective', function() {
        return {
          restrict: 'a',
          controller: function() {} // <--- anonymous controller
        };
      });
      

    • Alternative beside anonymous function as controller
      
      angular
      .controller('myCtrl', function() {})
      .directive('myDirective', function() {
        return {
          restrict: 'a',
          controller: 'myCtrl'
        };
      });
      
3) Testing AngularJS Directives

  • covered simple test of directive on
    • utilise jQlite 
    • unit test of directive's controller from one of the defined angular controller


Possible issue to overcome:

  1. To test a custom validation angular directive
    • unit test of form changes detection

Apr 8, 2016

AngularJs 2 Component: manually bind event listener to element

Sample code of binding element to an onchange event.

import {Directive, ElementRef, Output, EventEmitter, Renderer} from 'angular2/core';

@Directive({
  selector: 'my-comp'
})
export class myComp {
  constructor(el: ElementRef, renderer: Renderer) {
    renderer.listen(el.nativeElement, 'change', event => console.log(event));
  }
}

Stuff you need:
  • directive decorator
  • ElementRef.nativeElement
  • Renderer.listen()

Directive decorator
For my case here, I use directive decorator, because I do not need any template update.
If you are familiar with AngularJs 1.x, this is same as the directive with empty template like short example below:
eg.

angular.directive('myApp', function() {
  return {
    restrict: 'A',
    template: '',
    link: function() { ... }
  };
);


And of course you can choose to import Page, and use it with template like:

import {Page, ElementRef, Output, EventEmitter, Renderer} from 'angular2/core';

@Page({
  selector: 'my-app',
  template: 'Your template goes here'
})

// more code...


ElementRef.nativeElement
The similarity of ElementRef.nativeElement in AngularJs 2 with element parameter in Link() in AngularJs 1.x directive.


angular.directive('myApp', function() {
  return {
    restrict: 'A',
    template: '',
    link: function(scope, element, attributes) {
      // `ElementRef.nativeElement` is almost similar with
      // the `element` parameter in this link() function
    }
  };
);

Renderer.listen() - Angular2 beta 13
Add custom listener to keep track of an event fired, this helps at emitting or initiating additional action.
It works just like how AngularJs 1.x bind an event and initiate its parent's controller function in the scope.
Example AngularJs 1.x below:

angular
.controller('myCtrl', function() {
  scope.onClick = function(event) {
    console.log(event);
  };
})
.directive('myApp', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attributes) {
      // it bind event to element as in Angular 1.x
      $(element).bind('click', function(event) {
        scope.onClick(event);
      });
    }
  };
);


In AngularJs 2, more complete version of the sample code from top which indicate the use of Renderer.listen()

import {
  Directive, 
  ElementRef, 
  Output, 
  EventEmitter, 
  Renderer, 
  Component,
  bootstrap
} from 'angular2/core';

@Directive({
  selector: '[my-comp]'
})
class myComp {
  @Output() click = new EventEmitter();
  constructor(el: ElementRef, renderer: Renderer) { 
    renderer.listen(el.nativeElement, 'click', (event) => {
      this.onClick(event);
    });
  }

  onClick(event){
    this.click.emit({
      value: event
    });
  }
}

@Component({
  template: '<button (click)="showclick($event)" my-comp></button>',
  directives: [myComp]
})
class myApp {
  showClick($event) {
   console.log('changes::', $event);
  }
}
bootstrap(myApp);



Reference/learning source: Dynamically add event listener in Angular 2

Mar 28, 2016

Homebrew-ed Postgresql: "Export error: Failed to execute pg_dump"

Problem to troubleshoot
Export error: Failed to execute pg_dump (given path in your conf/config.inc.php : /usr/bin/pg_dump). Please, fix this path in your configuration and relog.

Postgres phppgadmin: Export error
I am new to postgresql database,
and recently I have a chance to play with this technology and at the meantime, I have been facing newbie issues with it.

Since I won't using this tool for a long time, it's better to record down the troubleshooting note for future in the simple way.

I use homebrew to install postgresql and phppgadmin.

As said in the error message, we'll need to edit conf/config.inc.php in order to get it fixed.

1) find your config.inc.php with "mdfind -name config.inc.php"
search for config.inc.php file
2) Find your pg_dump binary file path with "which pg_dump"
pg_dump location
3) Place correct path to "pg_dump" configuration

4) Once you done steps above, remember to relogin your user in phppgadmin for changes above to take effect.


Jan 22, 2016

Implant / inject event function to every (change of src) page in iframe with AngularJs

To inject an event manually with AngularJs (from the outside of child iframe),
you'll need two key things:

  • window.onload()
  • window.onmousedown

You'll need an angular directive to help injecting the event function and iframe page being "load".

// inject touch event to iframe child body
angular.directive('iframe', function() {
  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      element[0].onload = function() {
        scope.loaded();
      };
    },
    controller: function($scope, $window) {
      $scope.loaded = function() {
        $window.frames[0].window.onmousedown = function() {
          alert('Touched!');
        };
      };
    }
  };
});


Firstly, from element[0], you'll get your iframe element.
2nd, prepare a "loaded()" function to let "link()" to initiate for "onload()".


This solution made by the inspiration from AngularJS: onLoad from an iframe directive by Ashish Datta

Jan 20, 2016

Changing current $state will "back" button instead of menu button

How not to keep view history as you use $state.go()?

Menu button (icon)
In ionic (v1.2.4), when we are trying to change current state to other state,
it'll substitute "menu" button as "Back" button :

  $state.go('app.home');

Back button (icon)
or even solution below also won't help from showing the back button (icon).

  $state.go('app.home', {}, {
    location: 'replace',
    reload: true,
    inherit: false
  });


And gratefully, until I found a solution on stackoverflow, where people also facing the same issue as I did.

with code

  $ionicHistory.nextViewOptions({
    disableBack: true
  });

is enough to achieve my expected ("refresh" view history) result.

angular.controller('AppCtrl', function($state, $ionicHistory) {
  
  $scope.goHome = function () {
    $ionicHistory.nextViewOptions({
      disableBack: true
    });
    $state.go('app.home');
  };

});