/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
/*
 * $Id: playlist.c,v 1.1.1.1 2003/01/22 13:26:39 rocko Exp $
 *
 * Copyright (c) 2000, 2001 by Shiman Associates Inc. and Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions: The above
 * copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the names of the authors or
 * copyright holders shall not be used in advertising or otherwise to
 * promote the sale, use or other dealings in this Software without
 * prior written authorization from the authors or copyright holders,
 * as applicable.
 *
 * All trademarks and registered trademarks mentioned herein are the
 * property of their respective owners. No right, title or interest in
 * or to any trademark, service mark, logo or trade name of the
 * authors or copyright holders or their licensors is granted.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mas/mas_dpi.h"
#include "playlist.h"


/* append a playlist track to the playlist */
int32
append_track( struct plist* pl, struct track_info* t )
{
    struct track_info* tail;
    
    if ( pl == 0 ) return mas_error(MERR_NULLPTR);
    tail = pl->head;
    if ( tail == 0 ) return mas_error(MERR_NULLPTR);
    if ( t == 0 ) return mas_error(MERR_NULLPTR);

    /* find the tail */
    while (tail->next != 0) tail = tail->next;

    t->prev = tail;
    tail->next = t;

    return 0;
}

/* given a playlist entry number "pos" return a pointer to the track_info */
struct track_info* 
get_track( struct plist* pl, int16 pos )
{
    struct track_info* t;
    int i = 0;
    
    if ( pl == 0 )
        return 0;

    t = pl->head;
    if ( t == 0 )
        return 0;

    for ( i=0; i<pos && (t->next != 0); i++ )
        t = t->next;

    if ( i == pos ) return t;
    else return 0;
}

/* remove a track from the playlist */
int32
delete_track( struct track_info* t )
{
    if ( t == 0 ) return mas_error(MERR_NULLPTR);

    if ( t->prev != 0 ) t->prev->next = t->next;
    if ( t->next != 0 ) t->next->prev = t->prev;

    if ( t->filename != 0 ) masc_rtfree( t->filename );

    masc_rtfree( t );

    return 0;
}

/* create a new playlist */
struct plist*
new_plist( void )
{
    struct plist* pl;

    pl = MAS_NEW( pl );
    
    pl->head = MAS_NEW( pl->head ); /* Null head */
    
    return pl;
}

/* remove all entries in a playlist */
int32
clear_plist( struct plist* pl )
{
    struct track_info* t;
    
    if ( pl == 0 ) return mas_error(MERR_NULLPTR);
    if ( pl->head == 0 ) return mas_error(MERR_NULLPTR);

    t = pl->head;

    /* suck all the tracks up and delete  */
    while (t->next != 0) delete_track( t->next );

    pl->c = 0;
    
    return 0;
}

/* remove all entries in a playlist and free the playlist */
int32
delete_plist( struct plist* pl )
{
    int32 err;
    
    err = clear_plist( pl );
    if ( err < 0 ) return err;

    delete_track( pl->head );
    masc_rtfree( pl );

    return 0;
}

/* jump to the next track in the playlist, return a pointer to that
 * track */
struct track_info*
advance_track( struct plist* pl )
{
    int i;
    struct track_info* t;

    /* only jump to next track if we're not repeating this one */
    if ( pl->repmode != REPEAT_1 )
        pl->c++;

    t = pl->head;

    /* find the c-th playlist entry ( head is 0-th ) */
    for (i=0; i<pl->c; i++)
    {
        t = t->next;

        /* at the end of the list? */
        if ( t == 0 )
        {
            /* if we're repeating all, loop back to the start */
            if ( pl->repmode == REPEAT_ALL )
            {
                /* set to track 1, if there is a track one, else reset
                   to the head & return NULL */
                if ( pl->head->next != 0 )
                    pl->c = 1;
                else pl->c = 0;

                t = pl->head->next;
                return t;
            }
            else return 0;
        }
    }
    
    return t;
}

/* jump to the prior track in a playlist */
struct track_info*
back_track( struct plist* pl )
{
    int i;
    struct track_info* t;

    pl->c--;
    t = pl->head;
    if ( pl->c <= 0 ) return 0;
    
    for (i=0; i<pl->c; i++)
    {
        t = t->next;
        if ( t == 0 ) return 0;
    }
    
    return t;
}

/* given a playlist entry number "pos" set the current playlist
   position to "pos". */
struct track_info*
set_track( struct plist* pl, int16 pos )
{
    int i;
    struct track_info* t;
    
    pl->c = pos;
    t = pl->head;
    
    for (i=0; i<pl->c; i++)
    {
        t = t->next;
        if ( t == 0 ) return 0;
    }
    
    return t;
}

