<?php
/*
 # $Id: $
 ###############################################################################
 # AmaroK_Info: Script for InfoPlug amarok plugin (like xmms-infopipe).        #
 ###############################################################################
 # Author: Magnus Määttä <magnus@php.net>                                      #
 ###############################################################################
 # License: PHP Version 3                                                      #
 ###############################################################################
 # Custom String:                                                              #
 #                                                                             #
 #   %a   Album                                                                #
 #   %A   Artist                                                               #
 #   %b   Bitrate (Kilo)                                                       #
 #   %c   Comment                                                              #
 #   %f   Filename                                                             #
 #   %F   Sampling Frequency                                                   #
 #   %g   Genre                                                                #
 #   %G   Rating (@@* style)                                                   #
 #   %i   Title (track)                                                        #
 #   %p   Play count                                                           #
 #   %r   Release Name                                                         #
 #   %R   Rating                                                               #
 #   %s   Status                                                               #
 #   %S   Score                                                                #
 #   %t   Current position in track                                            #
 #   %T   Track length                                                         #
 #   %v   Volume                                                               #
 #   %y   Year                                                                 #
 #                                                                             #
 *#############################################################################*/

class AmaroK_Info extends PIF_Base
{
    /**
     * @var    array
     */
    public $data = array();

    /**
     * @var    string
     */
    public $ret_str = '';

    /**
     * @var object
     */
    public $parent;

    /**
     * Class constructor.
     */
    public function __construct($parent)
    {
        $this->parent = $parent;

        irssi_settings_add_str('amarok',  'amarok_info_uri',            'udp://10.0.3.5:5353');
        irssi_settings_add_str('amarok',  'amarok_show_method',            'msg');
        irssi_settings_add_str('amarok',  'amarok_preset_format',        'short');
        irssi_settings_add_str('amarok',  'amarok_custom_format',        '');
        irssi_settings_add_bool('amarok', 'amarok_print_if_stopped',    false);

        irssi_command_bind("anp", array($this, 'amarok_np'));
    }

    /**
     * /np command - Print help or what you're listening to.
     *
     * @return    bool
     */
    public function amarok_np($text, $server, $witem)
    {
        // Reset array
        $this->data = array();
        $text = trim($text);

        if ($text == "help") {
            echo"AmaroK_Info Help:\n============================================\n";
            echo "amarok_preset_format values:\n";
            echo "    short, custom\n";
            echo "amarok_show_method values:\n";
            echo "    msg or action\n";
            echo "Custom Format:\n";
            echo "%b  Bitrate                %c  Channels\n";
            echo "%f  Filename               %F  Sampling Frquency\n";
            echo "%g  Genre (Req. id3)       %i  ID3 Title\n";
            echo "%p  Current playlist entry %P  Playlist entries\n";
            echo "%r  Release Name (if any)  %s  Status\n";
            echo "%t  Position in song       %T  Song length\n";
            return true;
        }

//        if ($witem && ($witem->type == "CHANNEL" || $witem->type == "QUERY")) {
/*        foreach(array('target', 'nick', 'name', 'query', 'type', 'window') as $foo) {
            if (isset($witem->$foo)) {
                echo "$foo was set (". $witem->$foo .")\n";
            }
        } */

        if ($witem) {
            if (!$this->_getInfo()) {
                echo "AmaroK_Info: You are not listening to anything right now.\n";
                return false;
            }

            if (!irssi_settings_get_bool('amarok_print_if_stopped') &&
                (!isset($this->data['Status']) || $this->data['Status'] != 'Playing')) {
                echo "AmaroK_Info: You are not listening to anything right now.\n";
                return false;
            }

            if (!$this->_makeInfoString($text)) {
                echo "AmaroK_Info: You are not listening to anything right now.\n";
                return false;
            }

            $method = irssi_settings_get_str('amarok_show_method');

            if (strtolower($method) == 'msg') {
                $witem->command("MSG {$witem->name} {$this->ret_str}");
                return true;
            } elseif (strtolower($method) == 'action') {
                $witem->command("ME {$this->ret_str}");
                return true;
            } else {
                echo "AmaroK_Info: Unknown amarok_show_method type.\n";
                return false;
            }
        } else {
            echo "AmaroK_Info: Not in a query or channel window!\n";
            return false;
        }
    }

    /**
     *
     *
     */
    protected function _getInfo()
    {
        $info_file = irssi_settings_get_str('amarok_info_uri');
        $info = explode(':', $info_file);
        clearstatcache();
        $tmp = explode('/', $info[2]);

        if ($info[0] == "file") {
            /* Get data from infopipe file. */
            if (@file_exists($info[1])) {
                $file = @file($info[1]);
                foreach ($file as $line) {
                    $tmp = explode(':', $line, 2);
                    $this->data[$tmp[0]] = trim($tmp[1]);
                }
            } else {
                echo "AmaroK_Info: Couldn't open file $info_file.\n";
                return false;
            }
        } elseif (($info[0] == 'udp' || $info[0] == 'tcp') && @is_numeric($tmp[0])) {
            $fp = fsockopen("{$info[0]}:{$info[1]}", $info[2], $errno, $errstr, 5);
            if (!$fp) {
                echo "AmaroK_Info: Couldn't connect to {$info[0]}:{$info[1]}:{$tmp[0]}.\n";
                echo "AmaroK_Info: Errno $errno: $errstr\n";
                return false;
            } else {
                stream_set_timeout($fp, 5);
                /* Send one byte and get data. */
                fwrite($fp, "\n", 1);
                $data = fread($fp, 25000);
                $status = stream_get_meta_data($fp);
                if (!$status['timed_out']) {
                    $buf = explode("\n", trim($data));
                    foreach ($buf as $line) {
                        $tmp = explode(':', $line, 2);
                        if (count($tmp) == 2) $this->data[$tmp[0]] = trim($tmp[1]);
                        @fclose($fp);
                    }
                 } else {
                     echo "AmaroK_Info: Timeout while reading data from socket.\n";
                    echo "AmaroK_Info: infoplug thread locked up ?\n";
                    @fclose($fp);
                    return false;
                 }
            }
        } else {
            echo "AmaroK_Info: Unknown method. Use udp://host:port or tcp://host:port or file:/path/file.foo\n";
            echo "Info0: {$info[0]}     tmp0: {$tmp[0]}\n";
            return false;
        }

        return true;
    }

    /**
     *
     *
     */
    protected function _makeInfoString($custom_text = null)
    {
        // Check that we have a valid array first.
        if (!isset($this->data['Artist'])) return false;

        $preset = irssi_settings_get_str('amarok_preset_format');
        if (strlen($custom_text) > 3) $preset = $custom_text;

        /* Check which preset we should use. */
        switch ($preset) {
            case 'short':
                $format = "np: %A - %i";
                break;
            case 'medium':
                $format = "np: %A - %i [%t/%T]";
                break;
            case 'long':
                $format = "np: %A - %i [%t/%T @ %bkbps]";
                break;
            case 'vlong':
                $format = "♫ %A - %i [%t/%T ♫ %g ♫ %bkbps ♫ %G]";
                break;
            case 'magnus1':
                $format = "♫ %A - %i ♫ %r [%t/%T ♫ %g ♫ %bkbps ♫ %G]";
                break;
            case 'custom':
                $format = irssi_settings_get_str('amarok_custom_format');
                break;
            case 'custom_text':
                $format = $custom_text;
                break;
            default:
                echo "Amarok_Info: Invalid preset format specified.\n";
                return false;
                break;
        }

        /* Get filename */
        $tmp = explode('/', $this->data['URL']);
        $filename = $tmp[count($tmp) - 1];

        /* Find release name if any. */
        $release = $this->_getReleaseName($tmp);

        /* Graphical version of rating */
        $gfxRating = $this->_getGfxRating();

        /* Replacements */
        $replace = array('%a', '%A', '%b', '%c', '%f', '%F', '%g', '%G', '%i', '%p', '%r', '%R', '%s', '%S', '%t', '%T', '%v', '%y');
        $with = array(
            @$this->data['Album'],
            @$this->data['Artist'],
            @$this->data['Bitrate'],
            @$this->data['Comment'],
            $filename,
            @($this->data['Sample Rate'] / 1000),
            @$this->data['Genre'],
            $gfxRating,
            @$this->data['Title'],
            @$this->data['Play Count'],
            $release,
            @$this->data['Rating'],
            @$this->data['Status'],
            @$this->data['Score'],
            @$this->data['Current Time'],
            @$this->data['Total Time'],
            @$this->data['Volume'],
            @$this->data['Year'],
        );

        $this->ret_str = str_replace($replace, $with, $format);
        return true;
    }

    /**
     *
     *
     */
    protected function _getReleaseName($file)
    {
        /* Get the name of the release. */
        $count = count($file) - 1;
        $parts = array();

        for ($i = 0; $i < $count; $i++) {
            $len = strlen($file[$i]);
            $parts[$i] = 0;
            for ($x = 0; $x < $len; $x++) {
                /* Correctly named releases should have _ and - instead of spaces.
                 * Lower name "rating" if we find spaces.
                 */
                if ($file[$i]{$x} === '_' || $file[$i]{$x} === '-') $parts[$i]++;
                if ($file[$i]{$x} === ' ' && $parts[$i] > 0) $parts[$i]--;
            }
        }

        arsort($parts, SORT_NUMERIC);
        $ret = key($parts);

        /* Atleast 15 chars and 4 _ or - should be in the name. */
        if (strlen($file[$ret]) < 15 || $parts[$ret] < 3) {
            return "NONE";
        } else {
            return $file[$ret];
        }
    }

    /**
     * Get graphical representation of rating
     *
     * @return    string
     */
    protected function _getGfxRating()
    {
        $r = @$this->data['Rating'];

        if (!is_numeric($r) || $r == 0) {
            return '-';
        }

        // The GFX representation
        $g = "";

        while($r) {
            if (!($r % 2)) {
                $g .="*";
                $r -= 2; 
            } else {
                $g .="+";
                $r--;
            }
        }

        // String is reversed
        $g = strrev($g);

        return $g;
    }
}

$_module = 'AmaroK_Info';