Sunday, November 6, 2011

TinyXML

#include <ltinyxml.h>

// ----------------------------------------------------------------------
// STDOUT dump and indenting utility functions
// ----------------------------------------------------------------------
const unsigned int NUM_INDENTS_PER_SPACE=2;

const char * getIndent( unsigned int numIndents )
{
 static const char * pINDENT="                                      + ";
 static const unsigned int LENGTH=strlen( pINDENT );
 unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
 if ( n > LENGTH ) n = LENGTH;
 
 return &pINDENT[ LENGTH-n ];
}

// same as getIndent but no "+" at the end
const char * getIndentAlt( unsigned int numIndents )
{
 static const char * pINDENT="                                        ";
 static const unsigned int LENGTH=strlen( pINDENT );
 unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
 if ( n > LENGTH ) n = LENGTH;
 
 return &pINDENT[ LENGTH-n ];
}

int dump_attribs_to_stdout(TiXmlElement* pElement, unsigned int indent)
{
 if ( !pElement ) return 0;
 
 TiXmlAttribute* pAttrib=pElement->FirstAttribute();
 int i=0;
 int ival;
 double dval;
 const char* pIndent=getIndent(indent);
 printf("\n");
 while (pAttrib)
 {
  printf( "%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value());
  
  if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS)    printf( " int=%d", ival);
  if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( " d=%1.1f", dval);
  printf( "\n" );
  i++;
  pAttrib=pAttrib->Next();
 }
 return i;
}

void dump_to_stdout( TiXmlNode* pParent, unsigned int indent = 0 )
{
 if ( !pParent ) return;
 
 TiXmlNode* pChild;
 TiXmlText* pText;
 int t = pParent->Type();
 printf( "%s", getIndent(indent));
 int num;
 
 switch ( t )
 {
  case TiXmlNode::TINYXML_DOCUMENT:
   printf( "Document" );
   break;
   
  case TiXmlNode::TINYXML_ELEMENT:
   printf( "Element [%s]", pParent->Value() );
   num=dump_attribs_to_stdout(pParent->ToElement(), indent+1);
   switch(num)
   {
    case 0:  printf( " (No attributes)"); break;
    case 1:  printf( "%s1 attribute", getIndentAlt(indent)); break;
    default: printf( "%s%d attributes", getIndentAlt(indent), num); break;
   }
   break;
   
    case TiXmlNode::TINYXML_COMMENT:
     printf( "Comment: [%s]", pParent->Value());
     break;
     
    case TiXmlNode::TINYXML_UNKNOWN:
     printf( "Unknown" );
     break;
     
    case TiXmlNode::TINYXML_TEXT:
     pText = pParent->ToText();
     printf( "Text: [%s]", pText->Value() );
     break;
     
    case TiXmlNode::TINYXML_DECLARATION:
     printf( "Declaration" );
     break;
    default:
     break;
 }
 printf( "\n" );
 for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
 {
  dump_to_stdout( pChild, indent+1 );
 }
}

// load the named file and dump its structure to STDOUT
void dump_to_stdout(const char* pFilename)
{
 TiXmlDocument doc(pFilename);
 bool loadOkay = doc.LoadFile();
 if (loadOkay)
 {
  printf("\n%s:\n", pFilename);
  dump_to_stdout( &doc ); // defined later in the tutorial
 }
 else
 {
  printf("Failed to load file \"%s\"\n", pFilename);
 }
}


void build_simple_doc( )
{
 // Make xml: World
 TiXmlDocument doc;

 TiXmlDeclaration * declaration = new TiXmlDeclaration( "1.0", "UTF-8", "" );
 TiXmlElement * root = new TiXmlElement( "mipsdiag" );

 doc.LinkEndChild( declaration );
 doc.LinkEndChild( root );

 TiXmlElement * cpu = new TiXmlElement( "cpu" );
 root->LinkEndChild(cpu);
 
 TiXmlComment * comment = new TiXmlComment();
 comment->SetValue("-- CPU utilization --" );
 cpu->LinkEndChild(comment);

 TiXmlElement *cpu_res = new TiXmlElement("cpu_resouce");
 cpu_res->SetAttribute("type", "utilization");
 cpu_res->SetAttribute("units", "percent");
 cpu->LinkEndChild(cpu_res);

 TiXmlText *cpu_utilization = new TiXmlText("0.11");
 cpu_res->LinkEndChild(cpu_utilization);

 dump_to_stdout( &doc );
 doc.SaveFile( "mipsdiag.xml" );
}


int main()
{
 build_simple_doc();
}

Tuesday, October 18, 2011

Ooma has dialtone, but unable to make calls

There might be a bug in Old Ooma Broadband Voip device which for some reason could not establish voice connection (although it could connect to Ooma gateway  and we could hear its unique dialtone).

To fix it is actually very simple, just unplug the power to it and leave it like that for about 15 seconds, and than replug it

iTunes fails to upgrade iPad with error 1611

This issue was due to SIM card.

Try remove the SIM card while doing upgrade.  Once the upgrade is complete, we can reinsert the SIM card.

Monday, September 5, 2011

Recover file name copied from iPod/iPhone

With gtkPod, we are able to connect to iPhone/iPod and copy all the files, but the filenames are all cryptic (they are all in four letters). With the following script, we can recover the file names and convert them into readable format in the form of "artist - album" pattern.

#!/bin/sh
FULLPATH=$1
FILE=${FULLPATH##*/}
FILENAME=${FILE%.*}
EXT=${FILE##*.}
#echo "FILENAME=$FILENAME"
#echo "EXTension=$EXT"
shift
OPTS=$@
echo filename=$FILENAME

meta=`mp4info "$FULLPATH" | awk '/Metadata / {sub(/^[ \t]+/, "")};1'`
#echo meta=$meta
TITLE=`echo "$meta" | awk '/Metadata Name: / {gsub(/Metadata Name: /,""); print }'`
ARTIST=`echo "$meta" | awk '/Metadata Artist: / {gsub(/Metadata Artist: /,""); print }'`

if [ -z "$TITLE" ]
then
 TITLE="unknown"
else
 echo TITLE=$TITLE
fi

if [ -z "$ARTIST" ]
then
 ARTIST="unknown"
else
 echo ARTIST=$ARTIST
fi

TARGET="$ARTIST - $TITLE.$EXT"
cp "$FULLPATH" "$TARGET"

if [ -n $ "$TARGET" ]
then
 rm "$FULLPATH"
fi

Save the above script into an executable file, say mp4fixname.

To fix a filename, just run it and pass the encoded filename.
For example, if the file name is NXJA.m4a, we just run the script as below:


mp4fixname NXJA.m4a

The original filename will be replaced in artist and song name format according to metadata/tags stored in the original file.

Converting m4a song to mp3 format

Sometimes, I need to convert files I bought from iTunes to MP3 format. Well, actually not all songs we buy convertable to MP3. Only non-DRM format (with m4a extension) can be converted. The protected format with m4p extension still cannot be converted, theoritically at least (there is a hack to remove the DRM. But that's not easy and won't be covered here).

The following script converts an MP4 file to MP3 format.
It copies all the tags stored in the original file into the target file.
Make sure you have ffmpeg, mp4info, awk, and bc installed.

#!/bin/bash

#!/bin/bash

FULLPATH=$1
file=${FULLPATH##*/}
FILENAME=${file%.*}
EXT=${file##*.}
#echo "FILENAME=$FILENAME"
#echo "EXTension=$EXT"
shift
OPTS=$@

if [ `echo $EXT | tr [:upper:] [:lower:]` = "m4a" ]
then
 bitratekbps=`mp4info "$FULLPATH" | awk '$1 ~ /([0-9]+) kbps/g {print $8}'`
 bitratebps=`echo "scale=10; $bitratekbps*1000" | bc -l`
 hz=`mp4info "$FULLPATH" | awk '$1 ~ /([0-9]+) kbps/g {print $10}'`

 ffmpeg -i "$FILENAME.m4a" -aq 1 -ab $bitratebps -ar $hz -f mp3 \
        -metadata major_brand="MP3" \
         -metadata compatible_brands="MP3 libmp3lame" \
        "$FILENAME.mp3" $OPTS
fi



Save the file, say, to m4a2mp3 and make it executable.

To convert a song:

m4a2mp3 song.m4a

The target file name is the same, except the extension now is MP3. Also, some tags/metadata are replaced to reflect the new format. If you want to add other options, you can put that after file name. For example: m4a2mp3 song.m4a -metadata mymeta="converted from m4a"

Monday, August 8, 2011

Assembly in Linux

section .data
    hello:     db 'Hello world!',10    ; 'Hello world!' plus a linefeed character
    helloLen:  equ $-hello             ; Length of the 'Hello world!' string

section .text
    global _start

    _start:
    mov ecx,5            ; display the string 5 times

_loop:
    mov eax,4            ; The system call for write (sys_write)
    mov ebx,1            ; File descriptor 1 - standard output
    push ecx             ; save ecx as it is gonna be used as param to sys_write
    mov ecx,hello        ; Put the offset of hello in ecx
    mov edx,helloLen     ; helloLen is a constant, so we don't need to say
                         ;  mov edx,[helloLen] to get it's actual value
    int 80h              ; Call the kernel
    pop ecx              ; restore ecx (counter)
    loop _loop
    mov eax,1            ; The system call for exit (sys_exit)
    mov ebx,0            ; Exit with return code of 0 (no error)
    int 80h


Steps:
  1. Save the file as syscall.asm
  2. Execute: nasm -f elf syscall.asm
  3. Execute: ld -s -o syscall syscall.o
  4. run it as: ./syscall
  5. To check the object file, we can use objdump, elfdump, or readelf. For example:

$ readelf -a ./syscall.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          64 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         7
  Section header string table index: 3

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .data             PROGBITS        00000000 000160 00000d 00  WA  0   0  4

  [ 2] .text             PROGBITS        00000000 000170 00002b 00  AX  0   0 16

  [ 3] .shstrtab         STRTAB          00000000 0001a0 000031 00      0   0  1

  [ 4] .symtab           SYMTAB          00000000 0001e0 000080 10      5   7  4

  [ 5] .strtab           STRTAB          00000000 000260 000029 00      0   0  1

  [ 6] .rel.text         REL             00000000 000290 000008 08      4   2  4
$ readelf -a ./syscall.o
ELF Header:s:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32unknown)
  Data:                              2's complement, little endianpecific)
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1 0x290 contains 1 entries:
  Entry point address:               0x0Value  Sym. Name
  Start of program headers:          0 (bytes into file)
  Start of section headers:          64 (bytes into file)
  Flags:                             0x0e.
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0Vis      Ndx Name
  Size of section headers:           40 (bytes)UND
  Number of section headers:         7DEFAULT  ABS syscall.asm
  Section header string table index: 3DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    2
Section Headers:     0 NOTYPE  LOCAL  DEFAULT    1 hello
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .data             PROGBITS        00000000 000160 00000d 00  WA  0   0  4
  [ 2] .text             PROGBITS        00000000 000170 00002b 00  AX  0   0 16
  [ 3] .shstrtab         STRTAB          00000000 0001a0 000031 00      0   0  1
  [ 4] .symtab           SYMTAB          00000000 0001e0 000080 10      5   7  4
  [ 5] .strtab           STRTAB          00000000 000260 000029 00      0   0  1
  [ 6] .rel.text         REL             00000000 000290 000008 08      4   2  4
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

Relocation section '.rel.text' at offset 0x290 contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000011  00000201 R_386_32          00000000   .data

There are no unwind sections in this file.

Symbol table '.symtab' contains 8 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS syscall.asm
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    2
     4: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 hello
     5: 0000000d     0 NOTYPE  LOCAL  DEFAULT  ABS helloLen
     6: 00000005     0 NOTYPE  LOCAL  DEFAULT    2 _loop
     7: 00000000     0 NOTYPE  GLOBAL DEFAULT    2 _start

No version information found in this file.