1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.midi; 18 19 import android.media.midi.MidiReceiver; 20 21 import java.io.IOException; 22 23 /** 24 * Add MIDI Events to an EventScheduler 25 */ 26 public class MidiEventScheduler extends EventScheduler { 27 private static final String TAG = "MidiEventScheduler"; 28 // Maintain a pool of scheduled events to reduce memory allocation. 29 // This pool increases performance by about 14%. 30 private final static int POOL_EVENT_SIZE = 16; 31 private MidiReceiver mReceiver = new SchedulingReceiver(); 32 33 private class SchedulingReceiver extends MidiReceiver { 34 /** 35 * Store these bytes in the EventScheduler to be delivered at the specified 36 * time. 37 */ 38 @Override onSend(byte[] msg, int offset, int count, long timestamp)39 public void onSend(byte[] msg, int offset, int count, long timestamp) 40 throws IOException { 41 MidiEvent event = createScheduledEvent(msg, offset, count, timestamp); 42 if (event != null) { 43 add(event); 44 } 45 } 46 47 @Override onFlush()48 public void onFlush() { 49 MidiEventScheduler.this.flush(); 50 } 51 } 52 53 public static class MidiEvent extends SchedulableEvent { 54 public int count = 0; 55 public byte[] data; 56 MidiEvent(int count)57 private MidiEvent(int count) { 58 super(0); 59 data = new byte[count]; 60 } 61 MidiEvent(byte[] msg, int offset, int count, long timestamp)62 private MidiEvent(byte[] msg, int offset, int count, long timestamp) { 63 super(timestamp); 64 data = new byte[count]; 65 System.arraycopy(msg, offset, data, 0, count); 66 this.count = count; 67 } 68 69 @Override toString()70 public String toString() { 71 String text = "Event: "; 72 for (int i = 0; i < count; i++) { 73 text += data[i] + ", "; 74 } 75 return text; 76 } 77 } 78 79 /** 80 * Create an event that contains the message. 81 */ createScheduledEvent(byte[] msg, int offset, int count, long timestamp)82 private MidiEvent createScheduledEvent(byte[] msg, int offset, int count, 83 long timestamp) { 84 MidiEvent event; 85 if (count > POOL_EVENT_SIZE) { 86 event = new MidiEvent(msg, offset, count, timestamp); 87 } else { 88 event = (MidiEvent) removeEventfromPool(); 89 if (event == null) { 90 event = new MidiEvent(POOL_EVENT_SIZE); 91 } 92 System.arraycopy(msg, offset, event.data, 0, count); 93 event.count = count; 94 event.setTimestamp(timestamp); 95 } 96 return event; 97 } 98 99 /** 100 * Return events to a pool so they can be reused. 101 * 102 * @param event 103 */ 104 @Override addEventToPool(SchedulableEvent event)105 public void addEventToPool(SchedulableEvent event) { 106 // Make sure the event is suitable for the pool. 107 if (event instanceof MidiEvent) { 108 MidiEvent midiEvent = (MidiEvent) event; 109 if (midiEvent.data.length == POOL_EVENT_SIZE) { 110 super.addEventToPool(event); 111 } 112 } 113 } 114 115 /** 116 * This MidiReceiver will write date to the scheduling buffer. 117 * @return the MidiReceiver 118 */ getReceiver()119 public MidiReceiver getReceiver() { 120 return mReceiver; 121 } 122 123 } 124