Linked list in C++ with pointer to pointer

I used to write linked list code in recursive form so that I don’t need to use dummy header node or something like that. This gives me a clear linked list with any extra nodes in it. Of cause, it is in recursive form thus there a memory and time overhead associated with it. The following is the example code.

#include <iostream>

using namespace std;
struct NODE {
    int value;
    NODE *next;
} *root;

void printList (NODE *root) {
    while (root != NULL) {
        cout << root->value << ' ';
        root = root->next;
    cout << endl;

void addNode (NODE **root, int value) {
    if ((*root)!=NULL && (*root)->value < value) {
        addNode (&((*root)->next), value);
    else {
        NODE *tmp;
        tmp = new NODE;
        tmp->value = value;
        tmp->next = *root;
        *root = tmp;

int main() {
    srand (time(NULL));
    for (int i=0; i<500; i++)
        addNode (&root, rand() % 1000);

    return 0;

Once you understand what the pointer to pointer **root is about then the whole program is not much special.

Last week, I had a chance to write code which required the use of linked list again. I suddenly about whether it can be converted to a non-recursive form which is something that did not come to my mind before. It turned out that the non-recursive form is actually very easy to write.

// Non recursive version
void addNode (NODE **root, int value) {
    while ((*root)!=NULL && (*root)->value < value) {
        root = &((*root)->next);
    NODE *tmp;
    tmp = new NODE;
    tmp->value = value;
    tmp->next = *root;
    *root = tmp;

Adding Google Voice Assistant back to MIUI 9

I have a XiaoMi 6 running Chinese MIUI9 (developer ROM) but installed with Google frame with the backup/restore method described on the Internet. Everything was fine except a few months ago, the Google Voice Assistant (GVA) stop working. I could use the Chinese Voice Assistant (it is quite good) but most of my contacts were written in English which cannot be recognized by the Chinese Voice Assistant.

Every time when MIUI has a new update, I tried to reinstall the GVA just to see whether the bug was fixed or not, and every time, I got the same error message.

java.lang.RuntimeException: Unable to create service java.lang.SecurityException: Failed to find provider for user 0; expected to find a valid ContentProvider for this authority

I think the main problem may be caused by some missing “partner” app. Today, I finally find the way to fix it. I installed an app named and slove the program.

Upgrade to Xiaomi Mi 6

I have been using Xiaomi 2S for a long time without upgrading. It is still usable but getting slow on task switching. I like Xiaomi because of its OS support. Up to now, my 2S still getting software upgrade every now and then.

As for my new Mi 6. The one I get is Chinese version which does not have Google Play. So, the first task I had was to try to install Google framework on the phone. After some search on the Internet, I found two ways to do so:

  1. Flash the official “global” ROM from the MIUI website ( This ROM contains the Google framework in it. However, Mi 6 is a locked phone which means I need to unlock the phone first before I can directly flash any ROM to it. There is instruction on MIUI website ( and the Internet showing to apply and perform the unlocking. After unlocking, you can flash the global ROM to gain the Google framework.
  2. The second option is using the local restore option which provided on the Internet. The idea is to restore the set of apps which form the Google framework. The backup of this set of apps is available for download from the Internet. The advantage of this approach is you do not need to unlock or root your device at all. However, if you want to root your device, you do need to unlock it first.

I tried the global ROM approach first. I found it has very good support of Google framework include the use of “ok Google” to unlock or activate voice command. However, even I used the developer version of ROM, it does not support rooting the device. This means I have to use some third-party apps for both flashing and rooting the device. Even worse, after each MIUI upgrade, I have to do the flashing and rooting again.

This brings me to try to reverse the device back to the Chinese ROM and try the restore approach for installing the Google framework. It works out fine. I can use Google Play and all other Google apps. However, the “ok google” cannot be activated in the same way as in the Global ROM. But now, I have the MIUI rooting support back!

In my opinion, if you want to root the device, the Chinese ROM together with the restore approach is a better choice.

Adding subtitle to mp4 movie with ffmpeg

I need to add a short copyright message at the beginning and ending of a short movie. So, I think it will be great to use ffmpeg for this simple task. Well, it turned out to be not as simple as I initially expected.

Running the initial simple command (show below) taken from somewhere in WWW result in error in reading the .srt file.

ffmpeg -i input-dv.mp4 -vf output-dv.mp4

Initially, I have my .srt setup as follows:

The movie should only be used in ...

Since the error message said it “cannot read” the file, I tried to change its name, adding fullpath, etc. Nothing worked. I also tried to change the contain. And finally, the following works. See the difference? I missed the spaces sounding “–>”!

00:00:00,000 --> 00:00:10,000
The movie should only be used in ...

Now the program run and produced a result mp4 file. However, when I viewed the movie, there was no subtitle! After reviewing the screen full of messages displayed during the conversion, I found there was a warning message about the missing fonts.conf file. Another round of information digging began.

This time, luckily, not before long, I came across a post ( where it provided most information about setting up the fonts.conf file.

Here are steps I took:

1. Download the fonts.conf from the above post and put it in the root directory of ffmpeg which, in my case, is D:\WinApps\ffmpeg

2. Setup the envoironment variables as follows:

set FC_CONFIG_DIR=d:\WinApp\ffmpeg
set FONTCONFIG_FILE=fonts.conf
set FONTCONFIG_PATH=d:\WinApp\ffmpeg

3. Run the following command

ffmpeg -i input-dv.mp4 -vf'Fontsize=18' output-dv.mp4

The first time I run the command, it took a bit longer to process.

The final problem is adding Chinese in the subtitle text. This turned out to be the most simple one to be solved. Just make sure the file encoding is in UTF-8. For this, I use the feature provided notepad directly.

“int RECV_PIN = TKD2;” error in Arduino IR library

Ok, it has been a long time since my last play-around with Arduino. This time, I tried to build a simple IR controller to open and close a window shader that I am planing to build. So I copy a sample program and test it out and get the error “TKD2 not defined” error in the following line of code in the file IRremoteTools.cpp which is part of the IRremote library.

int RECV_PIN = TKD2; // the pin the IR receiver is connected to

The simplest solution for this problem turned out to be just delete the two files IRremoteTools.cpp and IRremoteTools.h from the library directory. These two files just provide some additional function interface to the library which I am quite happy to live without them.

Allowing a local WiFi router to connect to the Internet through a wire LAN

I recently need to set up a WiFi router in my room where I have a computer that connects to a wired network with 802.1x authentication. The network is connected to the internet. Since the WiFi router cannot directly connect to a network with 802.1x authentication, the router is connected to the computer (running Ubuntu 16.04.1 LTS) instead. The following is the code, allowing the traffic from the WiFi router through my computer connect to the network with Internet capability.

# Perform NAT so that the WiFi route can connect to the Internet
# eth0 connect to a network which can connect to the Internet
# eth1 connect to LAN through WiFi router
# code taken from
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
/sbin/iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

“symbol(s) not found for architecture x86_64 error” when compiling OpenCV example program in Mac OS X 10.12

I just completed the installation of OpenCV 3 in my Mac (running OS X 10.12) after a long search of various installation methods.  However, when I tried to compile a sample C++ program, the following error was resulted:

Undefined symbols for architecture x86_64:
  "cv::imread(cv::String const&, int)", referenced from:
      _main in DisplayImage-6f69a1.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [DisplayImage] Error 1

So, once again, the search is on. After searching for the entire morning for solutions, I came across many “solution posts” that did not work!

Finally, I reached a post that mentioned “imread has been moved in the opencv_imgcodecs library.” and should “Try to add -lopencv_imgcodecs to your linker flags.” This solved my problem.

This case made me wonder how many people who posted “incorrect solution” had actually tried to replicate the error and actually solved the problem? Or did they just “think” what may be the problem and provide “guesses” about the possible solutions?

I am not saying that try ones best to provide information to the other is a bad thing. But providing too many “unproven” information in the web not only not able to help, it also makes the searching for true solution more difficult!