list.c++ 4.21 KB
//====================================================================
// list.c++
//
// Copyright 1993, Silicon Graphics, Inc.
// All Rights Reserved.
//
// This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
// the contents of this file may not be disclosed to third parties, copied or
// duplicated in any form, in whole or in part, without the prior written
// permission of Silicon Graphics, Inc.
//
// RESTRICTED RIGHTS LEGEND:
// Use, duplication or disclosure by the Government is subject to restrictions
// as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
// and Computer Software clause at DFARS 252.227-7013, and/or in similar or
// successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
// rights reserved under the Copyright Laws of the United States.
//====================================================================

#include "list.h"
#include "midifile.h"


/*
 * list stuff
 */
Node::Node()
{
    next = prev = 0;

    type = 0;
    time = 0;     

    status = 0;
    b1 = b2 = 0;
    
    data = 0;
    len = 0;       
}

List::List()
{
    head = tail = 0;
    sortEvents = 0;
    curNode = 0;
}

void List::OrderEvents(int orderFlag)
{
    sortEvents = orderFlag;
}

// Insert a node before the node returned by locate. If there is
// no head, it's an empty list, if locate returns zero, add to
// end of list, if locate returns the head, make node new head.
// otherwise simply add before node returned by locate
void List::Insert(Node *node)
{
    Node *before = locate(node);

    if(head == 0L) {  
        // empty list
    	head = tail = node;
        node->prev = 0L;
        node->next = 0L;
    } else if(before == 0L) { 
        // new tail
        tail->next = node;
        node->prev = tail;
        node->next = 0L;
        tail = node;
    } else if(before == head) {      
        // new head
    	head->prev = node;
        node->prev = 0L;
        node->next = head;
        head = node;
    } else {      
    	node->next = before;
        node->prev = before->prev;
        before->prev = node;
        node->prev->next = node;
    }
    
}

Node *List::locate(Node *newNode)
{
    long time = newNode->time;
    Node *node;
    Node *first;
    int  newNsort;
    int  oldSort;

    if(head == 0 || tail == 0) return(0);
    if(time > tail->time) return(0);
    if(time < head->time) return(head);

    if(curNode != 0) {
        node = curNode;
    } else {
        node = head;
        curNode = node;
    }

    if(!sortEvents) {
	if(time > node->time) {
	    while(time > node->time)
		node = node->next;
	    first = node;
	} else if(time < node->time) {
	    while(time < node->time)
		node = node->prev;
	    first = node->next;
	} else {
	    first = curNode;
	}
    } else {
	if(time > node->time) {
	    while(time > node->time)
		node = node->next;
	    first = node;
	} else {
	    while(time <= node->time) {
		node = node->prev;
		if(node)
		    first = node->next;
		else
		{
		    first = head;
		    break;
		}
	    }

	}
	if(time < first->time)
	    return(first);

	newNsort = SortValue(newNode);
	while((oldSort=SortValue(first)) <= newNsort)
	{
	    if(!first->next) /* first is tail */
		return (0);
	    if(first->next->time != time)
		return(first->next);
	    first = first->next;
	}
    }
    
    return(first);
}


//    SortValue
//
//    For each midi type add the following:
//         noteoff (0x80)      add  0x180
//         noteon  (0x90)      add  0x800
//         polykey (0xA0)      add  0x400
//         controller (0xB0)   add  0x200
//         program chng (0xC0) add  0x300
//         chan press (0xD0)   add  0x500
//         pitchbend (0xE0)    add  0x600
//         sys mesg (0xF0)     add  0x100

int  midiTypeSV[] = { 0x180,0x800,0x400,0x200,
		      0x300,0x500,0x600,0x100 };

int List::SortValue(Node *node)
{
    int val = 0;
    char status,shift;

    if(node->type == MIDI_TYPE)
    {
	status = node->status & MIDI_StatusMask;
	shift = (status>>4) - 8;
	val += midiTypeSV[shift];
	
	if(status == MIDI_ControlChange)
	{
	    switch(node->b1)
	    {
		case 102:
		    val += 10;
		    break;
		case 103:
		    val += 30;
		    break;
		case 104:
		case 105:
		    val += 20;
		    break;
		default:
		    val += 127;
	    }

	}
    }
	
    return (val);
}