Site Sponsors:
Tagging Your MP# Files 
Command-line audiophiles of all descriptions surely know about ffmpeg - The de-facto way of managing allot more than MP3 files, ffmpeg ranks highly - even amongst the audacity set - for managing the ear-candy.



An avid consumer of every audio book I can afford (I get about 2 a year - Christmas & Father's day :) once ripped from the CDs most book-listeners feel that any random-play feature - as enjoyed by most of the planet - should be considered a form of torture.

Until so considered by a joint Geneva / UN-declaration, like many we simply *need* to combine all spoken-word tracks into a SINGLE album-file, or risk going 'radical ;-)

Tweakin' Tags


When it comes time to update the tags for our audio amalgamations, rather than using ffmpeg however, one will find the services of the taglib examples to be in high-demand. Namely, `tagreader` and `tagwriter`.

Designed to do precisely what their names imply, one can save hours by updating music meta-data in place.

Indeed, with a collection of over 60 unifile audiobooks to update, commands such as:

ffmpeg -i /MyMedia/AudioBooks/SW_05_02_21_The_Unifying_Force.mp3 -metadata title="SW_05_02_21_The_Unifying_Force" /MyMedia/biglist/SW_05_02_21_The_Unifying_Force.mp3
on a 1.2 GB file ... are simply evil!

The Recipe


Unlike using ffmpeg (sudo-installable,) using taglib's examples are - at the time of this telling - never for the faint-hearted.

For those who would like to use the aforementioned pair of tag-management console tools however, here are my notes:

# (1) You must install Gnu's C/C++
sudo apt-get install c++

# (2) You must install CMake
sudo apt-get install cmake

# (3) You mist install BOOST
sudo apt-get install libboost-all-dev

# (4) You must download, unpack, make & install taglib
cd /<wherever_unziped>/taglib-1.11.1
cmake -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release .
make
sudo make install

# (5) The examples folder under <wherever_unziped> will have the tagreader & tagwriter
-rwxr-xr-x 1 root root 1281440 Feb 24 04:31 tagreader
-rwxr-xr-x 1 root root 1287144 Feb 24 04:31 tagreader_c
-rw-rw-r-- 1 root root 2913 Oct 23 23:03 tagreader_c.c
-rw-rw-r-- 1 root root 3413 Oct 23 23:03 tagreader.cpp
-rwxr-xr-x 1 root root 1282016 Feb 24 04:31 tagwriter
-rw-rw-r-- 1 root root 5201 Oct 23 23:03 tagwriter.cpp


Caveat Python


Note: For those who would like to use `pip install pytaglib` under Python / PyPi, note that we came up with the above strategy rather than swimming thru the plethora of build problems. (*)

Not only will one need to install taglib anywize, but by simply building the examples (-DBUILD_EXAMPLES=ON, above) you'll already have what you need to manage your audio metadata without writing a single line of code:
./tagwriter

Usage: tagwriter <fields> <files>

Where the valid fields are:
-t <title>
-a <artist>
-A <album>
-c <comment>
-g <genre>
-y <year>
-T <track>
-R <tagname> <tagvalue>
-I <tagname> <tagvalue>
-D <tagname>
And yes, FWIW the taglib heroes have my personal vote for surely what be the all-time best `example` program in the history of example-program-oscpacy. -Right down to that macho, got-my big-boy pants-on, C++ incarnation. ;-)


(*) Example of the `pip3 install pytaglib` woes:
fatal error: taglib/tstring.h: No such file or directory
is just the beginning of the problem - after getting past those, one will also see errors such as:
/usr/bin/ld: //usr/local/lib/libtag.a(tstring.cpp.o): relocation R_X86_64_32S against `_ZTVN6TagLib6StringE' can not be used when making a shared object; recompile with -fPIC
Is not life too short for thousands of developers to be fixing that type of nonsense ... in a PyPi Package?


[ add comment ] ( 134 views )   |  permalink  |  related link
GNU C++: Ineritance & Default Parameter Confusion 
For those who like to use C++, the sole justification for many is the ability to implement a common signature over several related implementations.

Commonly known as "inheritance," when we need to use a parent's function / signature, yet provide a unique child-implementation of our own, we call it "polymorphism."

C++ Slicing


When it comes to using default parameters, we should note that those actually applied to our call will depend upon the receiving type.

No matter if we are using a vtable or no (*), this ability to "chop off" children definitions in C++ is a remnant of something called "Slicing."

By way of example, given the following base class & factory enumeration:
namespace BlogNouns {

enum Types {
typeThing, typePlace, typePerson
};

class Thing {
public:
virtual void speak(const char *psz = "Ima Thing") {
printf("Thing: %s\n", psz);
}

static Thing& Create(Types which);
};
}
, upon creating a few children we shall also provide a different default "speak" parameter:
    class Place : public Thing {
public:
virtual void speak(const char *psz = "Ima Place") {
printf("Place: %s\n", psz);
}

};

class Person : public Place {
public:
virtual void speak(const char *psz = "Ima Person") {
printf("Person: %s\n", psz);
}

Having set the stage for the first demonstration, supporting the aspersion =) we'll see:
using namespace BlogNouns;


int main(int argc, char** argv) {
puts("MyNouns");
Thing& noun = Thing::Create(Types::typePerson);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typePlace);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typeThing);
noun.speak();
delete &noun;

return 0;
}

-will use the default receiving-type ("Thing") parameter:

MyNouns
Person: Ima Thing
Place: Ima Thing
Thing: Ima Thing

Conversely however, whenever we change the receiving type to match the type actually created, we see that we will - instead - use that associated receiving-type's default parameter:

int main(int argc, char** argv) {

puts("BlogNouns");
Person& person = (Person&)Thing::Create(Types::typePerson);
person.speak();
delete &person;

Place& place = (Place&)Thing::Create(Types::typePlace);
place.speak();
delete &place;

Thing& thing = Thing::Create(Types::typeThing);
thing.speak();
delete &thing;

return 0;
}

BlogNouns
Person: Ima Person
Place: Ima Place
Thing: Ima Thing
Finally, note that I'm-a using:
c++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.



Sharing is caring,


-Rn

(*) Here is the "sliced proof" that virtual table (vtable) definitions do not matter:

With VTABLES:


/* Virtual - Replacing parental definitions.
*/

#include <iostream>

using namespace std;

namespace BlogNouns {

enum Types {
typeThing, typePlace, typePerson
};

// Simplified

class Thing {
public:
virtual void speak(const char *psz = "Ima Thing") {
printf("Thing: %s\n", psz);
}

static Thing& Create(Types which);
};

class Place : public Thing {
public:
virtual void speak(const char *psz = "Ima Place") {
printf("Place: %s\n", psz);
}

};

class Person : public Place {
public:
virtual void speak(const char *psz = "Ima Person") {
printf("Person: %s\n", psz);
}

};

Thing& Thing::Create(Types which) {
switch (which) {
case typeThing:
return *(new Thing);
case typePerson:
return *(new Person);
case typePlace:
return *(new Place);
}
}

}

using namespace BlogNouns;


int main(int argc, char** argv) {

{
puts("MyNouns");
Thing& noun = Thing::Create(Types::typePerson);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typePlace);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typeThing);
noun.speak();
delete &noun;
}
puts("BlogNouns");
Person& person = (Person&)Thing::Create(Types::typePerson);
person.speak();
delete &person;

Place& place = (Place&)Thing::Create(Types::typePlace);
place.speak();
delete &place;

Thing& thing = Thing::Create(Types::typeThing);
thing.speak();
delete &thing;

return 0;
}


Output:

MyNouns
Person: Ima Thing
Place: Ima Thing
Thing: Ima Thing
BlogNouns
Person: Ima Person
Place: Ima Place
Thing: Ima Thing


Without:


/* No Virtuals - Simply Overriding parental definitions.
*/
#include <iostream>

using namespace std;

namespace BlogNouns {

enum Types {
typeThing, typePlace, typePerson
};

// Simplified

class Thing {
public:
void speak(const char *psz = "Ima Thing") {
printf("Thing: %s\n", psz);
}

static Thing& Create(Types which);
};

class Place : public Thing {
public:
void speak(const char *psz = "Ima Place") {
printf("Place: %s\n", psz);
}

};

class Person : public Place {
public:
void speak(const char *psz = "Ima Person") {
printf("Person: %s\n", psz);
}

};

Thing& Thing::Create(Types which) {
switch (which) {
case typeThing:
return *(new Thing);
case typePerson:
return *(new Person);
case typePlace:
return *(new Place);
}
}

}

using namespace BlogNouns;


int main(int argc, char** argv) {

{
puts("MyNouns");
Thing& noun = Thing::Create(Types::typePerson);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typePlace);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typeThing);
noun.speak();
delete &noun;
}
puts("BlogNouns");
Person& person = (Person&)Thing::Create(Types::typePerson);
person.speak();
delete &person;

Place& place = (Place&)Thing::Create(Types::typePlace);
place.speak();
delete &place;

Thing& thing = Thing::Create(Types::typeThing);
thing.speak();
delete &thing;

return 0;
}


Output:

Thing: Ima Thing
Thing: Ima Thing
Thing: Ima Thing
BlogNouns
Person: Ima Person
Place: Ima Place
Thing: Ima Thing

[ add comment ] ( 120 views )   |  permalink

<<First <Back | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Next> Last>>