Logo Search packages:      
Sourcecode: rosegarden version File versions  Download package

AlsaPort.cpp

// -*- c-indentation-style:"stroustrup" c-basic-offset: 4 -*-
/*
  Rosegarden-4
  A sequencer and musical notation editor.

  This program is Copyright 2000-2006
  Guillaume Laurent   <glaurent@telegraph-road.org>,
  Chris Cannam        <cannam@all-day-breakfast.com>,
  Richard Bown        <bownie@bownie.com>

  The moral right of the authors to claim authorship of this work
  has been asserted.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; either version 2 of the
  License, or (at your option) any later version.  See the file
  COPYING included with this distribution for more information.
*/

#include "AlsaPort.h"

#include <iostream>
#include <cstdlib>
#include <cstdio>

#ifdef HAVE_ALSA

// ALSA
#include <alsa/asoundlib.h>
#include <alsa/seq_event.h>
#include <alsa/version.h>

#include "MappedInstrument.h"
#include "Midi.h"
#include "WAVAudioFile.h"
#include "MappedStudio.h"
#include "rosestrings.h"

#ifdef HAVE_LIBJACK
#include <jack/types.h>
#include <unistd.h> // for usleep
#include <cmath>
#endif

namespace Rosegarden
{

AlsaPortDescription::AlsaPortDescription(Instrument::InstrumentType type,
                                         const std::string &name,
                                         int client,
                                         int port,
                               unsigned int clientType,
                               unsigned int portType,
                               unsigned int capability,
                                         PortDirection direction):
        m_type(type),
        m_name(name),
        m_client(client),
        m_port(port),
      m_clientType(clientType),
      m_portType(portType),
      m_capability(capability),
        m_direction(direction)
{
}


bool
AlsaPortCmp::operator()(AlsaPortDescription *a1, AlsaPortDescription *a2)
{
    // Ordering for ALSA ports in the list:
    //
    // * Hardware ports (client id 64-127) sorted by direction
    //   (write, duplex, read) then client id then port id
    //
    // * Software ports (client id 128+) sorted by client id
    //   then port id
    // 
    // * System ports (client id 0-63) sorted by client id then
    //   port id


    // See comment in AlsaDriver::createMidiDevice -- the client
    // numbering scheme changed in ALSA driver 1.0.11rc1.
    // We now order:
    //
    // * Write-only software ports (client id 128+) sorted by client
    //   id then port id
    // 
    // * Probable hardware ports (client id 16-127) sorted by
    //   direction (write, duplex, read) then client id (64+
    //   preferred) then port id
    // 
    // * Read-write or read-only software ports (client id 128+)
    //   sorted by client id then port id
    // 
    // * System ports (client id 0-15) sorted by client id then
    //   port id
    //
    // It's necessary to handle software ports ahead of
    // hardware/system ports, because we want to keep all the hardware
    // ports together (we don't want to change the priority of a
    // hardware port relative to a software port based on its client
    // ID) and we can't know for sure whether the 16-63 range are
    // hardware or system ports.

    enum Category {
      WRITE_ONLY_SOFTWARE,
      HARDWARE_PROBABLY,
      MIXED_SOFTWARE,
      SYSTEM
    };
    
    bool oldScheme = (SND_LIB_MAJOR == 0 ||
                  (SND_LIB_MAJOR == 1 &&
                   SND_LIB_MINOR == 0 &&
                   SND_LIB_SUBMINOR < 11));

    Category a1cat;
    if (a1->m_client < 16) a1cat = SYSTEM;
    else if (oldScheme && (a1->m_client < 64)) a1cat = SYSTEM;
    else if (a1->m_client < 128) a1cat = HARDWARE_PROBABLY;
    else a1cat = MIXED_SOFTWARE;

    if (a1cat == MIXED_SOFTWARE) {
      if (a1->m_direction == WriteOnly) a1cat = WRITE_ONLY_SOFTWARE;
    }

    Category a2cat;
    if (a2->m_client < 16) a2cat = SYSTEM;
    else if (oldScheme && (a2->m_client < 64)) a2cat = SYSTEM;
    else if (a2->m_client < 128) a2cat = HARDWARE_PROBABLY;
    else a2cat = MIXED_SOFTWARE;

    if (a2cat == MIXED_SOFTWARE) {
      if (a2->m_direction == WriteOnly) a2cat = WRITE_ONLY_SOFTWARE;
    }

    if (a1cat != a2cat) return int(a1cat) < int(a2cat);

    if (a1cat == HARDWARE_PROBABLY) {

      if (a1->m_direction == WriteOnly) {
          if (a2->m_direction != WriteOnly) return true;
      } else if (a1->m_direction == Duplex) {
          if (a2->m_direction == ReadOnly) return true;
      }
      
      int c1 = a1->m_client;
      int c2 = a2->m_client;
      if (c1 < 64) c1 += 1000;
      if (c2 < 64) c2 += 1000;
      if (c1 != c2) return c1 < c2;

    } else if (a1cat == SYSTEM) {

      int c1 = a1->m_client;
      int c2 = a2->m_client;
      if (c1 < 16) c1 += 1000;
      if (c2 < 16) c2 += 1000;
      if (c1 != c2) return c1 < c2;
    }

    if (a1->m_client != a2->m_client) {
      return a1->m_client < a2->m_client;
    } else {
      return a1->m_port   < a2->m_port;
    }
}

}

#endif // HAVE_ALSA

Generated by  Doxygen 1.6.0   Back to index