/*
 * audiorecorder.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */


#include "audiorecorder.h"
#include "setup.h"
#include "mainmenu.h"
#include "service.h"

#include <vdr/plugin.h>

#include <getopt.h>
#include <sys/stat.h>
#include <unistd.h>

#include <iostream>

extern "C" {
        #include <ffmpeg/avcodec.h>
}


using namespace std;

/* --- cPluginAudiorecorder ------------------------------------------------- */

const char *cPluginAudiorecorder::DESCRIPTION = "floods your disc with music";
const char *cPluginAudiorecorder::VERSION = "0.1.0-pre6";

string cPluginAudiorecorder::recdir;
int cPluginAudiorecorder::debug = 0;


cPluginAudiorecorder::cPluginAudiorecorder(void)
{
        dispatcher = NULL;
        postproc = NULL;
}


cPluginAudiorecorder::~cPluginAudiorecorder()
{
        delete dispatcher;
        delete postproc;
}


const char *cPluginAudiorecorder::CommandLineHelp(void)
{
        return "  -r dir,   --recdir=dir    set recording-directory to 'dir'.\n"
               "  -d level, --debug=level   set debugging level (default: 0),\n"
               "                            all stuff is written to stdout.\n"
               "                            0 = off\n"
               "                            1 = only errors\n"
               "                            2 = errors and further infos\n";
}


bool cPluginAudiorecorder::ProcessArgs(int argc, char *argv[])
{
        int c, option_index = 0;
        struct stat dir;
        
        static struct option long_options[] = {
                { "recdir", required_argument, NULL, 'r' },
                { "debug", required_argument, NULL, 'd' },
                { NULL }
        };
        
        c = getopt_long(argc, argv, "r:v:d:", long_options, &option_index);
        while (c != -1) {
                switch (c) {
                case 'r':
                        recdir = optarg;
                        break;
                case 'd':
                        if (atoi(optarg) > 0)
                                debug = atoi(optarg);
                        break;
                default:
                        return false;
                }
                
                c = getopt_long(argc, argv, "r:v:d:", long_options,
                        &option_index);
        }
        
        if (recdir.empty()) {
                cerr << endl << "audiorecorder: missing parameter --recdir|-r "
                     << endl;
                dsyslog("audiorecorder: missing parameter --recdir|-r");                
                return false;
        }
        
        if (recdir[recdir.length() - 1] != '/')
                recdir.append("/");
        
        stat(recdir.c_str(), &dir);
        
        if (! (dir.st_mode & S_IFDIR)) {
                cerr << endl << "audiorecorder: " << recdir << " (given with "
                        "the parameter --recdir|-r) isn't a directory" << endl;
                dsyslog("[audiorecorder]: %s (given with the parameter "
                        " --recdir|-r) isn't a directory", recdir.c_str());
                return false;
        }
        
        if (access(recdir.c_str(), R_OK | W_OK) != 0) {
                cerr << endl << "audiorecorder: can't access " << recdir <<
                        " (given with the parameter --recdir|-r)" << endl;
                dsyslog("[audiorecorder]: can't access %s (given with the "
                        "parameter --recdir|-r)", recdir.c_str());
                return false;
        }
        
        return true;
}


bool cPluginAudiorecorder::Initialize(void)
{
        /* Initialize any background activities the plugin shall perform. */
        return true;
}


bool cPluginAudiorecorder::Start(void)
{
        /* initialize libavcodec */
        avcodec_init();
        avcodec_register_all();
        
        //probe_audio_codecs();
        
        Cache.load();        
        
        dispatcher = new cDispatcher();
        postproc = new cPostproc();
        
        return true;
}


void cPluginAudiorecorder::Stop(void)
{
        /* Stop any background activities the plugin shall perform. */
}


void cPluginAudiorecorder::Housekeeping(void)
{
        /* Perform any cleanup or other regular tasks. */
}


const char *cPluginAudiorecorder::MainMenuEntry(void)
{
        main_menu.str("");
        main_menu.clear();
        
        main_menu << "Audiorecorder ("
                << (dispatcher->is_active() ? "on" : "off")
                << ") " << dispatcher->get_recording_receivers()
                << "/" << dispatcher->get_attached_receivers(-1)
                << "/" << SetupValues.max_receivers
                << ", " << postproc->get_num_queued();
        
        return main_menu.str().c_str();
}


cOsdObject *cPluginAudiorecorder::MainMenuAction(void)
{
        return new cMainmenu(dispatcher);
}


cString cPluginAudiorecorder::Active(void)
{
        /*
	if (postproc->get_num_queued() != 0)
		return "active postprocessings";
        */
	return NULL; 
}


cMenuSetupPage *cPluginAudiorecorder::SetupMenu(void)
{
        return new cAudiorecorderSetup();
}


bool cPluginAudiorecorder::SetupParse(const char *name, const char *value)
{
        if (strcmp(name, "start_type") == 0)
                SetupValues.start_type = atoi(value);
        else if (strcmp(name, "max_receivers") == 0)
                SetupValues.max_receivers = atoi(value);
        else if (strcmp(name, "min_free_space") == 0)
                SetupValues.min_free_space = atoi(value);
        else if (strcmp(name, "pause") == 0)
                SetupValues.pause = atoi(value);
        else if (strcmp(name, "max_postproc") == 0)
                SetupValues.max_postproc = atoi(value);
        else if (strcmp(name, "default_view") == 0)
                SetupValues.default_view = atoi(value);
        else if (strcmp(name, "fade_in") == 0)
                SetupValues.fade_in = atoi(value);
        else if (strcmp(name, "fade_in_mode") == 0)
                SetupValues.fade_in_mode = atoi(value);
        else if (strcmp(name, "fade_out") == 0)
                SetupValues.fade_out = atoi(value);
        else if (strcmp(name, "fade_out_mode") == 0)
                SetupValues.fade_out_mode = atoi(value);
        else if (strcmp(name, "audio_codec") == 0) {
                int c;
                
                for (c = 0; c < SetupValues.num_audio_codecs; ++c) {
                        if (strcmp(value, audio_codecs[c]) == 0) {
                                SetupValues.audio_codec = c;
                                break;
                        }
                }
        }
        else if (strcmp(name, "bit_rate") == 0)
                SetupValues.bit_rate = atoi(value);
        else
                return false;
        
        return true;
}


bool cPluginAudiorecorder::Service(const char *id, void *data)
{
        if (! id)
                return false;
        
        if (strcmp(id, "Audiorecorder-StatusRtpChannel-v1.0") == 0) {
                if (data) {
                        struct Audiorecorder_StatusRtpChannel_v1_0 *d;
                        d = (struct Audiorecorder_StatusRtpChannel_v1_0 *)data;
                        d->status =
                                dispatcher->get_recording_status(d->channel);
                }
                return true;
        }
        
        return false;
}

const char **cPluginAudiorecorder::SVDRPHelpPages(void)
{
        /* Return help text for SVDRP commands this plugin implements */
        return NULL;
}


cString cPluginAudiorecorder::SVDRPCommand(const char *command,
        const char *option, int &reply_code)
{
        /* Process SVDRP commands this plugin implements */
        return NULL;
}


void cPluginAudiorecorder::probe_audio_codecs() {
        int c;
        char *tmp;
        AVCodec *codec = NULL;
        
        for (c = 1; c < SetupValues.num_audio_codecs; ++c) {
                codec = avcodec_find_encoder_by_name(audio_codecs[c]);
                if (codec)
                        continue;
                
                esyslog("[audiorecorder]: your version of libavcodec (ffmpeg) "
                        "is not compiled with %s support (%s, %s())", audio_codecs[c], __FILE__, __func__);
                
                tmp = audio_codecs[c];
                audio_codecs[c] =
                        audio_codecs[SetupValues.num_audio_codecs - 1];
                audio_codecs[SetupValues.num_audio_codecs - 1] = tmp;
                --SetupValues.num_audio_codecs;
        }
}


VDRPLUGINCREATOR(cPluginAudiorecorder); /* Don't touch this! */
