Nithin Philips - 2011-05-24

Hi,
I just wanted to share a pair of shell scripts that I made to create a fake directory structure and invoke mediatomb from a cron job. Those who are using mediatomb without javascript support may find this useful.

Here's some background. I share a lot of TV shows via mediatomb, including ones that are currently being aired and I wanted to have a folder that would show only the episodes that aired recently so that I can quickly find new episodes. The same goes for movies that were added to the library recently. My mediatomb build has no javascript support and even if it did, my understanding is that the javascript code only runs when the file is added to the library for the first time. This is not very useful for creating something like a "recently added" folder. My library is located on multiple cifs shares and that makes inotify useless. My setup is to run a shell script from cron that would create the desired directory structure using symbolic links. Then the script will invoke RPC calls via the mediatomb web interface. This way, the scan for new files and mediatomb updates are synchronized.

There are a couple of downsides to this setup. 1. You need to put the fake directory trees on the root of your file system to avoid havaing to dig through a very deep directory tree. 2. If you use this script along with the javascripts to organize, there will be duplicates of files.

Prereqs: The mediatomb web interface must be enabled. It should not be password protected.

The create-links script.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/bin/bash
#set -o errexit -o nounset -o xtrace
# Merges (flattens) all files in $1 into $2 using symbolic links.
# $1 = Source, an arry
# $2 = destination
function merge_files {
        pushd "$2"
        declare -a source_dirs=("${!1}")
        rm *
        for source_dir in "${source_dirs[@]}"
        do
                ln -s ${source_dir}/* .
        done
        popd
}
# Merges (flattens) all files in $1 into $2 using symbolic links.
# $1 = Source, an arry
# $2 = destination
# $3 = ctime (for find) age of files to find
function merge_files_new {
        pushd "$2"
        declare -a source_dirs=("${!1}")
        rm -rf *
        for source_dir in "${source_dirs[@]}"
        do
                find "${source_dir}/" -name '*.*' -ctime ${3} -exec ln -s -t . {} \;
        done
        popd
}
# Merges (flattens) all directories in $1 into $2 using symbolic links.
# $1 = Source, an arry
# $2 = destination
# $3 = ctime (for find) age of the directories to find
function merge_directory_new {
        pushd "$2"
        declare -a source_dirs=("${!1}")
        rm -rf *
        for source_dir in "${source_dirs[@]}"
        do
                find "${source_dir}/" -mindepth 1 -name '*' -type d -ctime ${3} -printf '"%f"\n' | xargs mkdir
        done
        popd
}
MOVIE_DIRS=("/mnt/xxx/movies" "/mnt/yyy/movies")
TV_DIRS=("/mnt/xxx/TV" "/mnt/yyy/TV")
# Merge all movies
merge_files MOVIE_DIRS[@] "/Movies"
# Merge all TV
merge_files TV_DIRS[@] "/TV"
# Merge all New Movies
merge_files_new MOVIE_DIRS[@] "/New Movies" -14
# Merge all new TV Shows with recent episodes
# For better usability we organize new Episodes by Show
merge_directory_new TV_DIRS[@] "/New Episodes" -14
for dir in /New\ Episodes/*
do
    pushd "$dir"
    dirname=$(basename "$dir")
    showdir="/TV/${dirname}/"
    find "${showdir}" -name "*.*" -ctime -14 -print0 | xargs -0 ln -s -t .
    popd
done
# finally force mediatomb to update
# don't forget to check id's
./mediatomb-rescan

The mediatomb-rescan script. Change /var/lib/mediatomb/mediatomb.html to match your configuration. Also, edit the /interface?… link to match your desired settings.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
#set -o errexit -o nounset -o xtrace
# $1 = the url to the MediaTomb installation, must end with a '/'
# $2 = SID ("sid=###"
# $3 = object id (get from mediatomb web-interface)
# $4 = (optional) the title of this object
function mt_autoscan {
    local name=$4
    if [ -z "$4" ]; then name=$3; fi
    local result=$(curl --silent "$1content/interface?req_type=autoscan&action=as_edit_save&object_id=$3&from_fs=0&scan_mode=timed&scan_level=basic&recursive=true&interval=43200&cancel=Cancel&$2" | awk -F"," '{print $1}' | sed 's/["{}]//g')
    # If scan result returned false, write the output to stderr
    if [[ $result == *false* ]]; then
        printf "%25s %s\n" "Scanning $name >" "$result" 1>&2
    fi
    # Write output to stdout
    printf "%25s %s\n" "Scanning $name >" "$result"    
}
# $1 = the url to the MediaTomb installation, must end with a '/'
function mt_login {
    # Note: this only works for passwordless login.
    local cur_sid=$(curl --silent "$1content/interface?req_type=auth&action=get_sid" | awk -F"," '{print $2}' | sed -e 's/"//g' -e  's/:/=/')
    echo $cur_sid
}
function mt_find_url {
    local url=$(cat /var/lib/mediatomb/mediatomb.html | sed -e 's/^.*URL=//g' -e 's/"><\/head>.*$//g')
    echo $url
}
URL=$(mt_find_url)
echo "Found MediaTomb at $URL"
SESSION_ID=$(mt_login "$URL")
# call mt_autoscan like this: The container id can be found via the web interface. 
# The title is optional.
#
#mt_autoscan $URL $SESSION_ID 424 "Movies"

Put these scripts in /bin or somewhere and call create-links from cron also, make sure that the directories like /TV and /Movies are owned by the same user who owns the mediatomb process (often "mediatomb").

Hope someone finds this useful.