How to: How to copy an Oracle tablespace across platforms – quick and dirty ;-)

On the source machine:
Set the tablespace(s) into read only mode

Alter tablespace <tablespace> read only

Export the tablespace meta data using export

expdp system/<password> DUMPFILE=expdat.dmp DIRECTORY = dpump_dir TRANSPORT_TABLESPACES = <list of tablespaces separated by commas> TRANSPORT_FULL_CHECK=Y

If the dumpdir is not set up, you will get an ‘invalid’ directory error:

CREATE DIRECTORY dmpdir as ‘/somedir’;
GRANT read,write on DIRECTORY to system;

Export the data converting on the fly:
Determine the platform name for the destination machine:

SELECT PLATFORM_ID, PLATFORM_NAME, ENDIAN_FORMAT FROM V$TRANSPORTABLE_PLATFORM
rman TARGET /
RMAN> CONVERT TABLESPACE </list><list of tablespaces separated by commas> to PLATFORM ‘<platform name from previous step>’  FORMAT=’/somedir/%U’;
Share Button

How to create an iTunes/iPod compatible audiobook (MPEG4 m4b) on Linux using MP4Box and mp4v2 v1.9.1 – it can be done!

I’ve been wracking my brains over this for the past few weeks and it finally struck me how to create an m4b audiobook with chapters that is compatible with your iPod, iTunes, VLC, etc.  It was very simple once I figured it out:

Step 1:

encode the mp3 files to “aac” (mpeg4) using your favorite converter (I use ffmpeg):

ffmpeg -i "track1.mp3" -y -vn -acodec libfaac -ab 128k -ar 44100 -threads 3 -f mp4 track1.aac

Step 2:

Create a chapters file so that MP4Box can understand it:

* Common syntax : CHAPTERX=h:m:s[:ms or .ms] on one line and CHAPTERXNAME=name on the other – the order is not important but chapter lines MUST be declared sequencially (same X value expected for 2 consecutive lines).

track1.chapters:

CHAPTER1=00:00:00.000
CHAPTER1NAME=Chapter 001
CHAPTER2=00:30:00.139
CHAPTER2NAME=Chapter 002
CHAPTER3=01:00:00.728
CHAPTER3NAME=Chapter 003
CHAPTER4=01:30:01.269
CHAPTER4NAME=Chapter 004
CHAPTER5=02:00:01.858
CHAPTER5NAME=Chapter 005
CHAPTER6=02:30:02.375
CHAPTER6NAME=Chapter 006
CHAPTER7=03:00:02.964
CHAPTER7NAME=Chapter 007
CHAPTER8=03:30:03.553
CHAPTER8NAME=Chapter 008
CHAPTER9=04:00:04.094
CHAPTER9NAME=Chapter 009
CHAPTER10=04:30:04.683
CHAPTER10NAME=Chapter 010
CHAPTER11=05:00:05.224
CHAPTER11NAME=Chapter 011
CHAPTER12=05:30:05.765
CHAPTER12NAME=Chapter 012
CHAPTER13=05:46:14.106
CHAPTER13NAME=Chapter 013
CHAPTER14=06:16:14.143
CHAPTER14NAME=Chapter 014
CHAPTER15=06:46:14.732
CHAPTER15NAME=Chapter 015
CHAPTER16=07:16:15.249
CHAPTER16NAME=Chapter 016
CHAPTER17=07:46:15.790
CHAPTER17NAME=Chapter 017
CHAPTER18=08:16:16.331
CHAPTER18NAME=Chapter 018
CHAPTER19=08:46:16.920
CHAPTER19NAME=Chapter 019
CHAPTER20=09:16:17.460
CHAPTER20NAME=Chapter 020
CHAPTER21=09:46:18.050
CHAPTER21NAME=Chapter 021
CHAPTER22=10:16:18.639
CHAPTER22NAME=Chapter 022

Step 3:

Add the chapters to the audio file (creates Nero format chapter markers):

MP4Box -add track1.aac -chap track1.chapters test.mp4

Step 4:

Convert the Nero chapter markers to Quicktime chapter markers using mp4chaps from the mp4v2 project (you will want v1.9.1 or higher):

mp4chaps --convert --chapter-qt test.mp4
converting chapters in file "test.mp4" from Nero to QuickTime

Step 5:

Rename the file from .mp4 to .m4b extension so iTunes will see it as an audiobook:

mv test.mp4 test.m4b

Proof that it works:

and VLC showing the chapters:

Of course, we aren’t putting in any tags such as “author” or “genre” in this example. Use your favorite tags editor to do so.

Share Button

A better way to convert your mp3 tags using Perl, POE, Linux::Inotify2 and POE::Wheel::Run (for you Sony PS3 or other media player)

So, what we have here is a country that tries to run itself on the commandments of a god who the people feel maybe wearing his underpants on his head. Has he abominated underpants?

No sir, but is probably only a matter of time.

Yesterday, I posted Howto: Convert your mp3 tags (id3v2 to id3v1) so your Playstation 3 can play your MP3s! and it worked fine but there was one little problem with it.

When we processed the files, namely running eye3D, we did so synchronously. Essentially, the file notification came in from the Linux kernel and we processed the file at that time. This may be an issue of overflowing the inotify queue within the Linux kernel if there are a lot of files to process.

A better solution would be to add the file to an internal queue and process the files in a sub process using POE::Wheel::Run. Of course we will limit the number of sub processes 🙂

#!/usr/bin/perl

use strict;
use warnings;

use File::Basename;
use File::Find ();
use Getopt::Std;
use Linux::Inotify2;
use POE qw( Kernel Session Wheel::Run );

$|++;

#######################################
#######################################

our @found_dirs;
our $max_concurrent_tasks;

sub watch_add_dir {
my ($heap_ref, $session, $dir_name) = @_;

##############
# Watch this directory with a call back
# to the watch_hdlr() subroutine via
# a message to the POE system
##############
$heap_ref-&gt;{inotify}-&gt;watch($dir_name, IN_CREATE|IN_CLOSE_WRITE, $session-&gt;postback("watch_hdlr"));
print " Watching directory $dir_name\n";
}

sub watch_hdlr {
my ($kernel, $heap, $session, $event) = ( $_[KERNEL], $_[HEAP], $_[SESSION], $_[ARG1][0] );

my $name = $event-&gt;fullname;
my $short_name = $event-&gt;name;

##############
# We can receive many many notifications
# for a file. If we've already processed
# the file, do nothing.
##############
unless ($heap-&gt;{inotify}{files}{$name}) {

##############
# If a new directory is added, we need
# to watch that directory too.
##############
if ($event-&gt;IN_CREATE &amp;&amp; -d $name) {
print "New directory: $name\n";
watch_add_dir($heap, $session, $name);
} elsif ($event-&gt;IN_CLOSE_WRITE) {

##############
# When a file descriptor that was opened for
# 'writing' is closed, then process that
# file it was being written to. We're
# assuming that the file is complete at this
# point as the operation will be a copy into
# the watched directory
##############
my $ext = ( fileparse($name, '\..*') )[2];

if (lc($ext) eq '.mp3') {
##############
# Add the file to the file process queue
##############
push @{ $heap-&gt;{task}{task_files} }, $name;

##############
# Mark that we have processed the file. If
# we don't we will end up processing the file
# in an infinite loop because we are modifying
# the files.
##############
$heap-&gt;{inotify}{files}{$name} = 1;

##############
# Yield to "task_next_file" through so
# that we can process files in the queue.
##############
$kernel-&gt;yield("task_next_file");
}

$heap-&gt;{inotify}{files}{$name} = 1;
}
}

##############
# While possible, it is highly unlikely that we will
# overflow the notification buffers within the Linux
# kernel. If so, we should report that.
##############
print "events for $name have been lost\n" if $event-&gt;IN_Q_OVERFLOW;
}

sub task_next_file {
my ($kernel, $heap) = @_[ KERNEL, HEAP ];

##############
# Process the files in the queue up
# to the $max_concurrent_tasks at
# once. Any extras will be processed
# when a file (task) completes.
##############
while ( keys( %{ $heap-&gt;{task} } ) &lt; $max_concurrent_tasks ) {
my $next_task_file = shift @{ $heap-&gt;{task}{task_files} };

##############
# If the $next_task_file is empty, then we can safely
# ignore it.
##############
last unless defined $next_task_file;

##############
# Use POE::Wheel::Run to fire off the
# file processing using a sub process
# to the process_file() subroutine
##############
my $task = POE::Wheel::Run-&gt;new (
Program =&gt; sub { process_file($next_task_file) },
StdoutEvent =&gt; "task_output",
CloseEvent =&gt; "task_done",
);

##############
# Update the session with the task
# information and the kernel with
# the SIG_CHILD handler. These are
# necessary for the task to execute.
##############
$heap-&gt;{task}-&gt;{ $task-&gt;ID } = $task;
$kernel-&gt;sig_child( $task-&gt;PID, "sig_child");
}
}

sub process_file {
my $file = shift;

print " Processed \"$file\"\n";

##############
# Use the eyeD3 package to convert
# the mp3 id3v2/3/4 to id3v1. If
# eyeD3 fails, we don't really care. 🙂
##############
my $cmd_output = `eyeD3 --to-v1.1 "$file"`;
$cmd_output = `eyeD3 --remove-v2 "$file"`;
}

sub find_wanted {
my $object = $File::Find::name;

if (-d $object) {
push @found_dirs, $object;
}
}

#######################################
#######################################
#######################################

my %arg_options;
my $watch_dir;

getopts('d:t:', \%arg_options);

if ($arg_options{d} &amp;&amp; -d $arg_options{d}) {
$watch_dir = $arg_options{d};

if ($arg_options{t} &amp;&amp; $arg_options{t} =~ /^\d+/) {
$max_concurrent_tasks = $arg_options{t};
} else {
$max_concurrent_tasks = 2;
}

##############
# We need to watch all existing sub directories
# so we will find them and add them to the
# @found_dirs array to be added to the watched
# directories when we create the Inotify object
##############
File::Find::find({wanted =&gt; \&amp;find_wanted}, $watch_dir);

POE::Session-&gt;create
( inline_states =&gt;
{ _start =&gt; sub {
my $inotify_FH;

##############
# alias this particular POE session to
# 'notify' so we can easily reference
# it later if needed
##############
$_[KERNEL]-&gt;alias_set('notify');

##############
# Create the Linux::INotify object
##############
$_[HEAP]{inotify} = new Linux::Inotify2
or die "Unable to create new inotify object: $!";

##############
# Add the preexisting directories to
# be watched from the @found_dirs array
##############
foreach my $dir (@found_dirs) {
watch_add_dir($_[HEAP], $_[SESSION], $dir);
}

##############
# We need to create a hash in the "notify"
# POE session so we can determine if we've
# processed a file already
##############
$_[HEAP]{inotify}{files} = {};

##############
# The Inotify notifications are received
# on a file descriptor. We need to read
# from it when there is something to be
# read
##############
open $inotify_FH, "&lt; &amp;=" . $_[HEAP]{inotify}-&gt;fileno
or die "Can’t fdopen: $!\n";

##############
# Inform POE to poll the file descriptor
##############
$_[KERNEL]-&gt;select_read( $inotify_FH, "inotify_poll" );
},
inotify_poll =&gt; sub {
$_[HEAP]{inotify}-&gt;poll;
},
watch_hdlr =&gt; \&amp;watch_hdlr,

##############
# Process the next file in the queue
##############
task_next_file =&gt; \&amp;task_next_file,

##############
# print the output of the job
##############
task_output =&gt; sub {
my $result = $_[ARG0];

print "$result\n";
},

##############
# When we are done with a file, go process the
# next file if there is one waiting
##############
task_done =&gt; sub {
my ($kernel, $heap, $task_id) = @_[ KERNEL, HEAP, ARG0 ];

delete $heap-&gt;{task}{$task_id};
$kernel-&gt;yield("task_next_file");
},
sig_child =&gt; sub {
my ($heap, $pid) = @_[ HEAP, ARG1 ];

my $details = delete $heap-&gt;{$pid};
},
},
);

POE::Kernel-&gt;run();
}

Example output:

ps3_mp3_converter.pl -d /home/jfroebe/j
 Watching directory /home/jfroebe/j
Watching directory /home/jfroebe/j/bin
Watching directory /home/jfroebe/j/doc
Watching directory /home/jfroebe/j/java
Watching directory /home/jfroebe/j/lib
Watching directory /home/jfroebe/j/j
Watching directory /home/jfroebe/j/j/tmp
Watching directory /home/jfroebe/j/sdk
Watching directory /home/jfroebe/j/sdk/demo
Watching directory /home/jfroebe/j/sdk/include
New directory: /home/jfroebe/j/Earth Final Conflict Soundtrack
Watching directory /home/jfroebe/j/Earth Final Conflict Soundtrack
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/01 Main Title.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/02 The Scret of Strandhill-Redemption.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/03 Old Flame.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/04 Defector.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/05 Decidion.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/06 Float Like a Butterfly.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/07 Sandoval's Run.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/08 Bliss.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/09 If You Could Read My Mind.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/10 Lilli.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/11 Law and Order.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/12 Atavus.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/13 Between Heaven and Hell.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/14 Sleepers.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/15 Dimensions.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/16 Moonscape.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/17 Isabel.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/18 The Gauntlet.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/19 Second Chances.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/20 One Man's Castle.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/21 Payback.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/22 Truth.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/23 Déjà Vu.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/24 Crossfire.mp3"
Processed "/home/jfroebe/j/Earth Final Conflict Soundtrack/25 Volunteers-End Credits.mp3"
Share Button

Howto: Convert your mp3 tags (id3v2 to id3v1) so your Playstation 3 can play your MP3s!

  1. Run the converter on your media server: ps3_mp3_converter.pl -d {directory}
  2. Copy your mp3 collection wherever you told ps3_mp3_converter.pl to run in.
#!/usr/bin/perl

use strict;
use warnings;

use File::Basename;
use File::Find ();
use Getopt::Std;
use Linux::Inotify2;
use POE;

$|++;

#######################################
#######################################

our @found_dirs;

sub watch_add_dir {
 my ($heap_ref, $session, $dir_name) = @_;

 $heap_ref->{inotify}->watch($dir_name, IN_CREATE|IN_CLOSE_WRITE, $session->postback("watch_hdlr"));
 print " Watching directory $dir_name\n";
}

sub watch_hdlr {
 my ($heap_ref, $session, $event) = ( $_[HEAP], $_[SESSION], $_[ARG1][0] );

 my $name = $event->fullname;
 my $short_name = $event->name;

 unless ($_[HEAP]{inotify}{files}{$name}) {
  if ($event->IN_CREATE && -d $name) {
   print "New directory: $name\n";
   watch_add_dir($heap_ref, $session, $name);
  } elsif ($event->IN_CLOSE_WRITE) {
   my $ext = ( fileparse($name, '\..*') )[2];

   if (lc($ext) eq '.mp3') {
    print "-"x20 . "\n";
    print "$name:\n";

    my $cmd_output = `eyeD3 --to-v1.1 "$name"`;
    $cmd_output = `eyeD3 --remove-v2 "$name"`;
   }

   $_[HEAP]{inotify}{files}{$name} = 1;
  }
 }

 print "events for $name have been lost\n" if $event->IN_Q_OVERFLOW;
}

sub find_wanted {
 my $object = $File::Find::name;

 if (-d $object) {
  push @found_dirs, $object;
 }
}

#######################################
#######################################
#######################################

my %arg_options;
my $watch_dir;

getopts('d:', \%arg_options);

if ($arg_options{d} && -d $arg_options{d}) {
 $watch_dir = $arg_options{d};
 File::Find::find({wanted => \&find_wanted}, $watch_dir);

 POE::Session->create
  ( inline_states =>
   { _start => sub {
     my $inotify_FH;

     $_[KERNEL]->alias_set('notify');
     $_[HEAP]{inotify} = new Linux::Inotify2
      or die "Unable to create new inotify object: $!";

     foreach my $dir (@found_dirs) {
      watch_add_dir($_[HEAP], $_[SESSION], $dir);
     }

     $_[HEAP]{inotify}{files} = {};

     open $inotify_FH, "< &=" . $_&#91;HEAP&#93;{inotify}->fileno
     or die "Can’t fdopen: $!\n";

     $_[KERNEL]->select_read( $inotify_FH, "inotify_poll" );
   },
   inotify_poll => sub {
    $_[HEAP]{inotify}->poll;
   },
    watch_hdlr => \&watch_hdlr,
   },
 );

 POE::Kernel->run();
}

exit 0;
Share Button

Using AviDemux 2.4.1 to convert a video to h.264 mpeg4 for the Sony Playstation 3

Hi all,

After trial and error, I finally figured out how to convert an old divx 3 (you know, the old hacked version of the codec) video file to a format that my Sony Playstation 3 (PS3) could handle.  Why is it that Sony has made the PS3 to be such a finicky beast when it comes to reading video files, I will never know:

How to convert a video file using AviDemux v2.4.1 on Ubuntu 8.04 (Hardy Heron):

  • Load the original video file into AviDemux
  • Auto -> PSP (H.264) – choose defaults

  • Video -> Configure -> 2 Pass

  • Format -> MP4

  • Save with the extension “.mp4”

If you’re going to put the video on an USB thumbdrive, you will need to create a folder:

  • On the USB Thumbdrive:   VIDEO
  • Group videos with subdirectories:  VIDEO / SCIFI
Share Button

Combining multiple Adobe PDF files into a single PDF file

After I downloaded a few eBooks from Bruce Perens’ Open Source Series, I noticed that several of the books were zip files containing the chapters as individual PDF files.  I don’t know about you, but I would rather hava a single monolithic PDF file for each book.

By using Ghostscript and pdftk, we are able to create the PDF file with no problem:

gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE="Implementing CIFS The Common Internet File System.pdf" -dBATCH frontmatter.pdf content.pdf foreword.pdf intro.pdf ch01.pdf  ch02.pdf  ch03.pdf  ch04.pdf  ch05.pdf  ch06.pdf  ch07.pdf  ch08.pdf  ch09.pdf  ch10.pdf  ch11.pdf ch12.pdf  ch13.pdf  ch14.pdf  ch15.pdf  ch16.pdf  ch17.pdf  ch18.pdf  ch19.pdf  ch20.pdf  ch21.pdf  ch22.pdf ch23.pdf  ch24.pdf  ch25.pdf  ch26.pdf apa.pdf apb.pdf apc.pdf apd.pdf glossary.pdf references.pdf index.pdf 

On Ubuntu Linux, you can quickly install these two tools with a single command:

aptitude install gs pdftk
Share Button