/*
 *   MediaMVP Plugin
 *
 *   (C) 2003 Dominic Morris
 *
 *   $Id: vdrurl.c,v 1.15 2005/01/31 19:54:09 dom Exp $
 *   $Date: 2005/01/31 19:54:09 $
 *
 *
 *   Handle the vdr:// URL type
 */

#include "libmvp.h"

#include "vdrurl.h"
#include "misc.h"

static fops_t vdrurl_fops = {
    NULL,
    cMediamvpVdrURL::Open,
    cMediamvpVdrURL::Close,
    cMediamvpVdrURL::Seek,
    cMediamvpVdrURL::Read,
    cMediamvpVdrURL::Info
};


cMediamvpVdrURL::cMediamvpVdrURL()
{
    m_Transceiver = NULL;
    event = NULL;
    name = NULL;
}

cMediamvpVdrURL::~cMediamvpVdrURL()
{
    if ( m_Transceiver != NULL ) {
        DELETENULL(m_Transceiver);
    }

    if ( event ) {
        event_del(event);
        free(event);
        event = NULL;
    }
    
    close(transfer_pipe[0]);
    close(transfer_pipe[1]);
    
    free(name);
}

void cMediamvpVdrURL::Init()
{
    urlhandler_add("vdr://",&vdrurl_fops);
}

cDevice *cMediamvpVdrURL::GetDevice(const cChannel *Channel, int Priority)
{
    cDevice    *device = NULL;
    bool ndr;

    device = cDevice::GetDevice(Channel, Priority, &ndr);

#ifndef SINGLE_DEVICE
    if (ndr) {
                device = NULL;
    }
#endif

    Dprintf(MOO,"Selected device @%p (primary = %p)\n",device,cDevice::PrimaryDevice());
        
    return device;
}

void *cMediamvpVdrURL::Open(char *name, int *type, fops_t **fops, readready_cb cb, void *cb_ptr)
{
    cMediamvpVdrURL *vdrurl = new cMediamvpVdrURL;
    char            *realname;
    const cChannel  *Channel;
    cDevice         *device;

    vdrurl->cb = cb;
    vdrurl->cb_ptr = cb_ptr;

    if ( strncmp(name,"vdr://",strlen("vdr://") ) ) {
        return NULL;
    }
    
    realname = name + strlen("vdr://");


    if ( ( Channel = ChannelFromString(realname) ) == NULL ) {
        delete vdrurl;
        return NULL;
    }

    
    if ( (device = vdrurl->GetDevice(Channel,0) ) == NULL ) {
        delete vdrurl;
        return NULL;
    }

    /* If there's no pids defined then don't try to play it */
#if VDRVERSNUM >= 10318
    if ( (Channel->Vpid() == 0 || Channel->Vpid() == 1 || Channel->Vpid() == 0x1fff ) && Channel->Apid(0) == 0) {
#else
    if ( (Channel->Vpid() == 0 || Channel->Vpid() == 1 || Channel->Vpid() == 0x1fff ) && Channel->Apid1() == 0) {

#endif
        delete vdrurl;
        return NULL;
    }

    if ( Channel->Vpid() == 0 || Channel->Vpid() == 1 || Channel->Vpid() == 0x1fff ) {
        *type = MEDIA_MP3 | MEDIA_SOCKET | MEDIA_LIVE;
    } else {
        *type = MEDIA_MPEG | MEDIA_SOCKET | MEDIA_LIVE;
    }

    vdrurl->name = strdup(Channel->Name());


    if ( pipe(&vdrurl->transfer_pipe[0]) == -1 ) {
        delete vdrurl;
        return NULL;
    }

    /* Create an event */
    vdrurl->event = (struct event *)malloc(sizeof(*vdrurl->event));
    event_set(vdrurl->event,vdrurl->transfer_pipe[0],EV_READ,cMediamvpVdrURL::ReadEvent,vdrurl);
    event_add(vdrurl->event,NULL);


    /* Create a new transceiver */
    vdrurl->m_Transceiver = new cMediamvpTransceiver(Channel,0,vdrurl->transfer_pipe[1],device);
    
    Dprintf(MOO,"Opened channel %s vdrurl %p transceiver %p\n",name,vdrurl,vdrurl->m_Transceiver);

    vdrurl->m_Transceiver->Activate(TRUE);

    return vdrurl;
}

off_t cMediamvpVdrURL::Seek(void *ptr, off_t offset, int whence)
{
    return (off_t) -1;
}

void cMediamvpVdrURL::Close(void *ptr)
{
    cMediamvpVdrURL *vdrurl = ( cMediamvpVdrURL *) ptr;

    if ( vdrurl != NULL ) {
        Dprintf(MOO,"Closing channel %s vdrurl %p transceiver %p\n",vdrurl->name,ptr,vdrurl->m_Transceiver);
        delete vdrurl;
   
    }

    return;
}

int cMediamvpVdrURL::Info(void *ptr, int cmd, void *arg)
{
    cMediamvpVdrURL *vdrurl = ( cMediamvpVdrURL *)ptr;

    switch ( cmd ) {
    case URLFILE_SIZE:
        *(off_t *)arg = 0;
        break;
    case URLFILE_NAME:
        *(char **)arg = vdrurl->name;
        break;
    default:
        return -1;
    }
    return 0;
}

int cMediamvpVdrURL::Read(void *ptr, unsigned char *buf, size_t buflen)
{
    cMediamvpVdrURL *vdrurl = ( cMediamvpVdrURL *)ptr;

    if ( vdrurl != NULL ) {
        return read(vdrurl->transfer_pipe[0],buf,buflen);       
    }
    return 0;
}

void cMediamvpVdrURL::ReadEvent(int fd, short event, void *arg)
{
    cMediamvpVdrURL *vdrurl = ( cMediamvpVdrURL *)arg;

    if ( vdrurl != NULL ) {
        event_add(vdrurl->event,NULL);
        vdrurl->cb(vdrurl->cb_ptr);
    }
}
