/*
 *   MediaMVP Device Plugin
 *
 *   (C) 2003 Dominic Morris
 *
 *   $Id: mvplive.c,v 1.3 2004/05/24 19:35:45 dom Exp $
 *   $Date: 2004/05/24 19:35:45 $
 *
 *
 *   Handle the mvplive:// URL type
 *
 *   Pretty hacky code, needs to be cleaned up a bit I think.
 */


#include "mvplive.h"

static fops_t liveurl_fops = {
    NULL,
    cMvpLiveURL::Open,
    cMvpLiveURL::Close,
    cMvpLiveURL::Seek,
    cMvpLiveURL::Read,
    cMvpLiveURL::Info
};

static cMvpLiveURL *URLInstance = NULL;


cMvpLiveURL::cMvpLiveURL(cRingBufferLinear *ringy)
{
    ringbuffer = ringy;

    if ( pipe(&transfer_pipe[0]) == -1 ) {
        printf("Can't create pipe\n");
        exit(1);
    }

    URLInstance = this;
    running = false;
    urlhandler_add("mvplive://",&liveurl_fops);
    urlhandler_add("mvplive2://",&liveurl_fops);

    Start();

}



cMvpLiveURL::~cMvpLiveURL()
{
    Cancel(3);
}

void cMvpLiveURL::Action()
{
    unsigned char *buf;
    int length;

    printf("Writer started pid %d\n",getpid());
    while(1) {
        if ( (buf = ringbuffer->Get(length) ) != NULL ) {
            /* Writing a length of 4000 seems to keep ivtv happy */
            if ( length > 0  ) {
                if ( running )
                    safe_write(transfer_pipe[1],buf,length);
                ringbuffer->Del(length);  

            } else {
                usleep(5);
            }

        } else {
            usleep(5);
        }
    }
}



/* Callbacks from the library */
void *cMvpLiveURL::Open(char *name, int *type, fops_t **fops, readready_cb cb, void *cb_ptr)
{
    URLInstance->running = true;
    URLInstance->cb = cb;
    URLInstance->cb_ptr = cb_ptr;

    if ( strncmp(name,"mvplive://",strlen("mvplive://")) == 0 ) {
        *type = MEDIA_MPEG | MEDIA_LIVE;
    } else {
        *type = MEDIA_MP3 | MEDIA_LIVE ;
    }

    URLInstance->event = (struct event *)malloc(sizeof(struct event));
    event_set(URLInstance->event,URLInstance->transfer_pipe[0],EV_READ,cMvpLiveURL::ReadEvent,URLInstance);
    event_add(URLInstance->event,NULL);

    return URLInstance;

}


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


void cMvpLiveURL::Close(void *ptr)
{
    URLInstance->running = false;
    event_del(URLInstance->event);
    free(URLInstance->event);

}

int cMvpLiveURL::Read(void *ptr, unsigned char *buf, size_t buflen)
{
    return read(URLInstance->transfer_pipe[0],buf,buflen);
}

int cMvpLiveURL::Info(void *ptr, int cmd, void *args)
{
    if ( cmd == URLFILE_SIZE ) {
        *(off_t *)args = 0;
        return 0;
    }
    return -1;
}

void cMvpLiveURL::ReadEvent(int fd, short event, void *arg)
{
    event_add(URLInstance->event,NULL);
    URLInstance->cb(URLInstance->cb_ptr);
}

bool cMvpLiveURL::Poll(cPoller &Poller, int TimeoutMs)
{
    if ( running ) {
        Poller.Add(transfer_pipe[1],true);
        return Poller.Poll(TimeoutMs);
    } 
    return false;
}
