Package de.sciss.eisenkraut.net

Source Code of de.sciss.eisenkraut.net.MeterManager

/*
*  MeterManager.java
*  Eisenkraut
*
*  Copyright (c) 2004-2014 Hanns Holger Rutz. All rights reserved.
*
*  This software is published under the GNU General Public License v3+
*
*
*  For further information, please contact Hanns Holger Rutz at
*  contact@sciss.de
*
*
*  Changelog:
*    13-Jul-06  created
*/

package de.sciss.eisenkraut.net;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.Timer;

import de.sciss.app.BasicEvent;
import de.sciss.app.EventManager;
import de.sciss.gui.PeakMeterView;
import de.sciss.jcollider.Bus;
import de.sciss.jcollider.Constants;
import de.sciss.jcollider.Group;
import de.sciss.jcollider.OSCResponderNode;
import de.sciss.jcollider.NodeWatcher;
import de.sciss.jcollider.Server;
import de.sciss.jcollider.ServerEvent;
import de.sciss.jcollider.ServerListener;
import de.sciss.jcollider.Synth;
import de.sciss.net.OSCBundle;
import de.sciss.net.OSCMessage;

/**
@author    Hanns Holger Rutz
@version  0.70, 03-Jul-08
*/
public class MeterManager
implements OSCResponderNode.Action, Constants, ServerListener, ActionListener,
       EventManager.Processor
{
  private List          collAllClients    = new ArrayList();
  private List          collActiveClients  = new ArrayList();
  private Map            mapClients      = new HashMap()// key = MeterListener, value = MeterClient

  private Server          server        = null;
 
  private Bus            bus          = null;
  private Group          grp          = null;
 
  private int            numCtrlChans    = 0;
 
  private OSCBundle        meterBangBndl    = null;
  private OSCResponderNode    resp        = null;

  private final Timer        meterTimer;
  private final SuperColliderClient sc;
 
  private int            numTask        = 0;
 
  private final EventManager    elm;

  public MeterManager( SuperColliderClient sc )
  {
    this.sc    = sc;
    meterTimer  = new javax.swing.Timer( 33, this );
    elm      = new EventManager( this );
    sc.addServerListener( this );
  }
 
  public void dispose()
  {
    sc.removeServerListener( this );
    disposeServer();
  }

  private void meterBang()
  {
    if( (server != null) && (meterBangBndl != null) ) {
      try {
        server.sendBundle( meterBangBndl );
      }
      catch( IOException e1 ) { /* don't print coz the frequency might be high */ }
    }
  }

  // ------------- ActionListener interface -------------

  public void actionPerformed( ActionEvent e )
  {
    meterBang();
  }

  // ------------- ServerListener interface -------------

  public void serverAction( ServerEvent e )
  {
    switch( e.getID() ) {
    case ServerEvent.STOPPED:
      setServer( null );
      break;
     
    case ServerEvent.RUNNING:
      setServer( e.getServer() );
      break;
     
    default:
      break;
    }
  }

  // ----------------- OSCResponderNode.Action interface -----------------
 
  public void respond( OSCResponderNode r, OSCMessage msg, long time )
  {
    elm.dispatchEvent( new Event( r, msg, time ));
  }

  // ----------------- EventManager.Processor interface -----------------

  public void processEvent( BasicEvent be )
  {
    final Event      e      = (Event) be;
    final OSCMessage  msg      = e.msg;
    final int      busIndex  = ((Number) msg.getArg( 0 )).intValue();
    final int      numVals    = ((Number) msg.getArg( 1 )).intValue();
// getWhen doesn't provide a valid value i think
//    final long      time    = e.getWhen();
    final long      time    = System.currentTimeMillis();
    Client        mc; 
 
    if( (bus == null) || (busIndex != bus.getIndex()) ) return;

    for( int i = 0; i < collActiveClients.size(); i++ ) {
      mc  = (Client) collActiveClients.get( i );
      if( !mc.task ) continue;
      for( int j = 0, k = 0, m = numVals + 2, off = mc.cOffset + 2; (k < mc.cNum) && (off < m); j++ ) {
        if( mc.channels[ j ] >= 0 ) {
          mc.peakRMSPairs[ k++ ] = ((Number) msg.getArg( off++ )).floatValue();
          mc.peakRMSPairs[ k++ ] = ((Number) msg.getArg( off++ )).floatValue();
        } else {
          mc.peakRMSPairs[ k++ ] = 0f;
          mc.peakRMSPairs[ k++ ] = 0f;
          off += 2;
        }
      }
      mc.view.meterUpdate( mc.peakRMSPairs, 0, time );
    }
  }

  private static void printError( String name, Throwable t )
  {
    System.err.println( name + " : " + t.getClass().getName() + " : " + t.getLocalizedMessage() );
  }

  private void disposeServer()
  {
    Client mc;

    meterTimer.stop();
   
    if( resp != null ) resp.remove();
 
    if( bus != null ) {
      bus.free();
      bus = null;
    }
    grp  = null;
   
    if( server == null ) return;
   
    for( int i = 0; i < collAllClients.size(); ) {
      mc = (Client) collAllClients.get( i );
      if( mc.server == server ) {
        collAllClients.remove( i );
      } else {
        i++;
      }
    }

    collActiveClients.clear();
    server      = null;
    meterBangBndl  = null;
  }
 
  private void setServer( Server s )
  {
    Client mc;

    disposeServer();
 
    if( s == null ) return;

    server    = s;
       
    for( int i = 0; i < collAllClients.size(); i++ ) {
      mc = (Client) collAllClients.get( i );
      if( mc.server == server ) {
        collActiveClients.add( mc );
      }
    }
       
    resp  = new OSCResponderNode( server, "/c_setn", this );
    resortClients();
  }
 
  public void setListenerTask( PeakMeterView view, boolean task, OSCBundle bndl )
  {
    if( !EventQueue.isDispatchThread() ) throw new IllegalMonitorStateException();

    final Client mc = (Client) mapClients.get( view );
    if( mc == null ) return;
    if( mc.task != task ) {
      mc.task  = task;
      if( mc.server == server ) {
        final boolean weCreated = bndl == null;
        if( weCreated ) bndl = new OSCBundle();
        for( int j = 0; j < mc.synths.length; j++ ) {
          if( mc.synths[ j ] != null ) {
            bndl.addPacket( mc.synths[ j ].runMsg( task ));
          }
        }
        if( weCreated && (bndl.getPacketCount() > 0) ) {
          try {
            server.sendBundle( bndl );
          }
          catch( IOException e1 ) {
            printError( "setListenerTask", e1 );
          }
        }
        if( task ) {
          if( ++numTask == 1 ) {
            meterTimer.restart();
          }
        } else {
          if( --numTask == 0 ) {
            meterTimer.stop();
          }
        }
      }
    }
  }

  public void addListener( PeakMeterView ml, Bus b, Group g, boolean task )
  {
    final int[] channels = new int[ b.getNumChannels() ];

    for( int i = 0, j = b.getIndex(); i < channels.length; ) {
      channels[ i++ ] = j++;
    }
    addListener( ml, b.getServer(), channels, g, task );
  }

  public void addListener( PeakMeterView ml, Server s, int[] channels, Group g, boolean task )
  {
    final Client mc;

    if( !EventQueue.isDispatchThread() ) throw new IllegalMonitorStateException();
 
    mc = new Client( ml, s, channels, g, task );
    if( mapClients.put( ml, mc ) != null ) throw new IllegalArgumentException( "MeterListener was already registered" );
    collAllClients.add( mc );
    if( mc.server == server ) {
      collActiveClients.add( mc );
      resortClients();
    }
  }
 
  public void removeListener( PeakMeterView view )
  {
    final Client  mc;
    final OSCBundle    bndl;
   
    if( !EventQueue.isDispatchThread() ) throw new IllegalMonitorStateException();

    mc = (Client) mapClients.remove( view );
    if( mc == null ) return;
    collAllClients.remove( mc );
    if( collActiveClients.remove( mc )) {
      bndl = new OSCBundle();
      for( int i = 0; i < mc.synths.length; i++ ) {
        if( mc.synths[ i ] != null ) {
          bndl.addPacket( mc.synths[ i ].freeMsg() );
          mc.synths[ i ] = null;
        }
      }
      if( bndl.getPacketCount() > 0 ) {
        try {
          if( server.isRunning() ) server.sendBundle( bndl );
          resortClients();
        }
        catch( IOException e1 ) {
          printError( "removeMeterListener", e1 );
        }
      }
    }
  }
 
  private void resortClients()
  {
    final NodeWatcher  nw;
    int          off  = 0;
    OSCBundle      bndl;
    Group        g;
    boolean        haveGrpTrig  = false;
    Client        mc;
    int          srcChan;
 
    meterTimer.stop();

    if( resp != null ) resp.remove();

    bndl      = new OSCBundle();
    meterBangBndl  = null;

    for( int i = 0; i < collActiveClients.size(); i++ ) {
      mc = (Client) collActiveClients.get( i );
      for( int j = 0; j < mc.synths.length; j++ ) {
        if( mc.synths[ j ] != null ) {
          bndl.addPacket( mc.synths[ j ].freeMsg() );
          mc.synths[ j ] = null;
        }
      }
      mc.setOffset( off );
      off += mc.cNum;
    }
   
    if( bus != null ) {
      bus.free();
      bus = null;
    }
   
    numCtrlChans  = off;
    if( bndl.getPacketCount() > 0 ) {
      try {
        if( server.isRunning() ) server.sendBundle( bndl );
      }
      catch( IOException e1 ) {
        numCtrlChans  = 0;
        printError( "resortClients", e1 );
      }
    }
   
    numTask = 0;
   
    try {
      if( (server != null) && (numCtrlChans > 0) ) {
        nw    = NodeWatcher.newFrom( server );
        bndl  = new OSCBundle();
        bus    = Bus.control( server, numCtrlChans );
        if( bus != null ) {
          meterBangBndl = new OSCBundle();
          meterBangBndl.addPacket( new OSCMessage( "/c_getn", new Object[] {
            new Integer( bus.getIndex() ), new Integer( bus.getNumChannels() )}));

          for( int i = 0; i < collActiveClients.size(); i++ ) {
            mc  = (Client) collActiveClients.get( i );
            if( mc.task ) numTask++;
            if( mc.g != null ) {
              g  = mc.g;
              meterBangBndl.addPacket( new OSCMessage( "/n_set", new Object[] {
                new Integer( g.getNodeID() ), "t_trig", new Integer( 1 )}));
            } else {
              if( grp == null ) {
                grp = Group.basicNew( server );
                grp.setName( "MeterManager" );
                bndl.addPacket( grp.newMsg( server.getDefaultGroup(), kAddToTail ));
                nw.register( grp );
              }
              g  = grp;
              if( !haveGrpTrig ) {
                meterBangBndl.addPacket( new OSCMessage( "/n_set", new Object[] {
                  new Integer( g.getNodeID() ), "t_trig", new Integer( 1 )}));
                haveGrpTrig = true;
              }
            }
            for( int j = 0, m = bus.getIndex() + mc.cOffset; j < mc.synths.length; j++, m += 2 ) {
              srcChan      = mc.channels[ j ];
              if( srcChan >= 0 ) {
                mc.synths[ j ] = Synth.basicNew( "eisk-meter", server );
                bndl.addPacket( mc.synths[ j ].newMsg( g, new String[] {
                  "i_aInBs""i_kOtBs" }, new float[] {
                  srcChan,    m }, kAddToTail ));
                if( !mc.task ) {
                  bndl.addPacket( mc.synths[ j ].runMsg( false ));
                }
                nw.register( mc.synths[ j ]);
              }
            }
          }
          if( bndl.getPacketCount() > 0 ) {
            try {
              server.sendBundle( bndl );
              if( resp != null ) resp.add();
              if( numTask > 0 ) meterTimer.restart();
            }
            catch( IOException e1 ) {
              printError( "resortClients", e1 );
            }
          }
        } else {
          System.err.println( "MeterManager : ran out of control busses!" );
        }
      }
    }
    catch( IOException e1 ) {
      e1.printStackTrace();
    }
  }

  // ------------- internal classes -------------
 
  private static class Event
  extends BasicEvent
  {
    protected OSCMessage msg;
   
    protected Event( Object src, OSCMessage msg, long time )
    {
      super( src, 0, time );
      this.msg = msg;
    }

    public boolean incorporate( BasicEvent oldEvent )
    {
      if( (oldEvent instanceof Event) && (oldEvent.getSource() == getSource()) ) {
        final OSCMessage omsg = ((Event) oldEvent).msg;
        if( omsg.getName().equals( msg.getName() ) &&
          (omsg.getArgCount() == msg.getArgCount()) &&
          omsg.getArg( 0 ).equals( msg.getArg( 0 )) &&  // busIndex
          omsg.getArg( 1 ).equals( msg.getArg( 1 ))) {  // numVals
         
          final Object[] fuseArgs = new Object[ msg.getArgCount() ];
          fuseArgs[ 0 ] = msg.getArg( 0 );
          fuseArgs[ 1 ] = msg.getArg( 1 );
          for( int i = 2; i < fuseArgs.length; i++ ) {
            fuseArgs[ i ] = new Float( Math.max(
                ((Numbermsg.getArg( i )).floatValue(),
                ((Number) omsg.getArg( i )).floatValue() ));
          }
          msg = new OSCMessage( msg.getName(), fuseArgs );
          return true;
        }
      }
      return false;
    }
  }
 
  private static class Client
  {
    protected final float[]      peakRMSPairs;
    protected final int        cNum;
    protected int          cOffset;
    protected final PeakMeterView  view;
    protected final int[]      channels;
    protected final Group      g;
    protected final Synth[]      synths;
    protected final Server      server;
    protected boolean        task;
   
    protected Client( PeakMeterView view, Server server, int[] channels, Group g, boolean task )
    {
      this.view    = view;
      this.server    = server;
      this.channels  = channels;
      this.g      = g;
      this.task    = task;

      cNum      = channels.length << 1;
      peakRMSPairs  = new float[ cNum ];
      synths      = new Synth[ channels.length ];
    }
   
    protected void setOffset( int cOffset )
    {
      this.cOffset  = cOffset;
    }
   
    public String toString()
    {
      final StringBuffer sb = new StringBuffer();
      sb.append( "[ " );
      for( int i = 0; i < channels.length; i++ ) {
        if( i > 0 ) sb.append( ", " );
        sb.append( channels[ i ]);
      }
      sb.append( " ]" );
      return( "MeterClient( "+view+", "+server+", " + sb.toString() + ", " + g + ", " + task + " )" );
    }
  }
}
TOP

Related Classes of de.sciss.eisenkraut.net.MeterManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.