Merge "AudioMixer can be configured for fewer max tracks"
diff --git a/include/common_time/local_clock.h b/include/common_time/local_clock.h
index 845d1c2..384c3de 100644
--- a/include/common_time/local_clock.h
+++ b/include/common_time/local_clock.h
@@ -28,7 +28,7 @@
 
 class LocalClock {
   public:
-     LocalClock();
+    LocalClock();
 
     bool initCheck();
 
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 552e829..ad27a1e 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -169,7 +169,7 @@
                                     callback_t cbf       = 0,
                                     void* user           = 0,
                                     int notificationFrames = 0,
-                                    int sessionId = 0);
+                                    int sessionId        = 0);
 
     /* Creates an audio track and registers it with AudioFlinger. With this constructor,
      * the PCM data to be rendered by AudioTrack is passed in a shared memory buffer
@@ -215,7 +215,7 @@
                             int notificationFrames = 0,
                             const sp<IMemory>& sharedBuffer = 0,
                             bool threadCanCallJava = false,
-                            int sessionId = 0);
+                            int sessionId       = 0);
 
 
     /* Result of constructing the AudioTrack. This must be checked
@@ -468,6 +468,7 @@
 
             // body of AudioTrackThread::threadLoop()
             bool processAudioBuffer(const sp<AudioTrackThread>& thread);
+
             status_t createTrack_l(audio_stream_type_t streamType,
                                  uint32_t sampleRate,
                                  audio_format_t format,
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index ca93ce5..40dffd4 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1493,7 +1493,7 @@
         pContext->pBundledContext->firstVolume = LVM_FALSE;
     }
     return 0;
-}    /* end setVolumeLevel */
+}    /* end VolumeSetVolumeLevel */
 
 //----------------------------------------------------------------------------
 // VolumeGetVolumeLevel()
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 048be1d..55cd3ad 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -104,9 +104,10 @@
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames,
-            0, false, sessionId);
+            0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId);
 }
 
+// DEPRECATED
 AudioTrack::AudioTrack(
         int streamType,
         uint32_t sampleRate,
@@ -124,7 +125,7 @@
 {
     mStatus = set((audio_stream_type_t)streamType, sampleRate, (audio_format_t)format, channelMask,
             frameCount, (audio_policy_output_flags_t)flags, cbf, user, notificationFrames,
-            0, false, sessionId);
+            0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId);
 }
 
 AudioTrack::AudioTrack(
@@ -144,8 +145,8 @@
       mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT)
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
-            0, flags, cbf, user, notificationFrames,
-            sharedBuffer, false, sessionId);
+            0 /*frameCount*/, flags, cbf, user, notificationFrames,
+            sharedBuffer, false /*threadCanCallJava*/, sessionId);
 }
 
 AudioTrack::~AudioTrack()
@@ -194,6 +195,7 @@
     if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         return NO_INIT;
     }
+
     uint32_t afLatency;
     if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
         return NO_INIT;
@@ -203,9 +205,11 @@
     if (streamType == AUDIO_STREAM_DEFAULT) {
         streamType = AUDIO_STREAM_MUSIC;
     }
+
     if (sampleRate == 0) {
         sampleRate = afSampleRate;
     }
+
     // these below should probably come from the audioFlinger too...
     if (format == AUDIO_FORMAT_DEFAULT) {
         format = AUDIO_FORMAT_PCM_16_BIT;
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index f1f62f7..7fa6bb7 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -89,7 +89,7 @@
 
     // create the output AudioTrack
     mAudioTrack = new AudioTrack();
-    mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parametrize this
+    mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parameterize this
             pLibConfig->sampleRate,
             AUDIO_FORMAT_PCM_16_BIT,
             audio_channel_out_mask_from_count(pLibConfig->numChannels),
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8f62ee4..148018d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1571,7 +1571,7 @@
                 AUDIO_POLICY_OUTPUT_FLAG_NONE,
                 CallbackWrapper,
                 mCallbackData,
-                0,
+                0,  // notification frames
                 mSessionId);
     } else {
         t = new AudioTrack(
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 1886050..6abaf23 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -348,6 +348,37 @@
     }
 
     mInitCheck = OK;
+
+    // get iTunes-style gapless info if present
+    ID3 id3(mDataSource);
+    if (id3.isValid()) {
+        ID3::Iterator *com = new ID3::Iterator(id3, "COM");
+        if (com->done()) {
+            delete com;
+            com = new ID3::Iterator(id3, "COMM");
+        }
+        while(!com->done()) {
+            String8 commentdesc;
+            String8 commentvalue;
+            com->getString(&commentdesc, &commentvalue);
+            const char * desc = commentdesc.string();
+            const char * value = commentvalue.string();
+
+            // first 3 characters are the language, which we don't care about
+            if(strlen(desc) > 3 && strcmp(desc + 3, "iTunSMPB") == 0) {
+
+                int32_t delay, padding;
+                if (sscanf(value, " %*x %x %x %*x", &delay, &padding) == 2) {
+                    mMeta->setInt32(kKeyEncoderDelay, delay);
+                    mMeta->setInt32(kKeyEncoderPadding, padding);
+                }
+                break;
+            }
+            com->next();
+        }
+        delete com;
+        com = NULL;
+    }
 }
 
 size_t MP3Extractor::countTracks() {
@@ -555,33 +586,6 @@
         return meta;
     }
 
-    ID3::Iterator *com = new ID3::Iterator(id3, "COM");
-    if (com->done()) {
-        delete com;
-        com = new ID3::Iterator(id3, "COMM");
-    }
-    while(!com->done()) {
-        String8 commentdesc;
-        String8 commentvalue;
-        com->getString(&commentdesc, &commentvalue);
-        const char * desc = commentdesc.string();
-        const char * value = commentvalue.string();
-
-        // first 3 characters are the language, which we don't care about
-        if(strlen(desc) > 3 && strcmp(desc + 3, "iTunSMPB") == 0) {
-
-            int32_t delay, padding;
-            if (sscanf(value, " %*x %x %x %*x", &delay, &padding) == 2) {
-                mMeta->setInt32(kKeyEncoderDelay, delay);
-                mMeta->setInt32(kKeyEncoderPadding, padding);
-            }
-            break;
-        }
-        com->next();
-    }
-    delete com;
-    com = NULL;
-
     struct Map {
         int key;
         const char *tag1;
diff --git a/media/libstagefright/timedtext/TimedText3GPPSource.cpp b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
index c423ef0..4854121 100644
--- a/media/libstagefright/timedtext/TimedText3GPPSource.cpp
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
@@ -39,19 +39,21 @@
 }
 
 status_t TimedText3GPPSource::read(
-        int64_t *timeUs, Parcel *parcel, const MediaSource::ReadOptions *options) {
+        int64_t *startTimeUs, int64_t *endTimeUs, Parcel *parcel,
+        const MediaSource::ReadOptions *options) {
     MediaBuffer *textBuffer = NULL;
     status_t err = mSource->read(&textBuffer, options);
     if (err != OK) {
         return err;
     }
     CHECK(textBuffer != NULL);
-    textBuffer->meta_data()->findInt64(kKeyTime, timeUs);
-    // TODO: this is legacy code. when 'timeUs' can be <= 0?
-    if (*timeUs > 0) {
-        extractAndAppendLocalDescriptions(*timeUs, textBuffer, parcel);
-    }
+    textBuffer->meta_data()->findInt64(kKeyTime, startTimeUs);
+    CHECK_GE(*startTimeUs, 0);
+    extractAndAppendLocalDescriptions(*startTimeUs, textBuffer, parcel);
     textBuffer->release();
+    // endTimeUs is a dummy parameter for 3gpp timed text format.
+    // Set a negative value to it to mark it is unavailable.
+    *endTimeUs = -1;
     return OK;
 }
 
diff --git a/media/libstagefright/timedtext/TimedText3GPPSource.h b/media/libstagefright/timedtext/TimedText3GPPSource.h
index 4ec3d8a..4170940 100644
--- a/media/libstagefright/timedtext/TimedText3GPPSource.h
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.h
@@ -33,7 +33,8 @@
     virtual status_t start() { return mSource->start(); }
     virtual status_t stop() { return mSource->stop(); }
     virtual status_t read(
-            int64_t *timeUs,
+            int64_t *startTimeUs,
+            int64_t *endTimeUs,
             Parcel *parcel,
             const MediaSource::ReadOptions *options = NULL);
     virtual status_t extractGlobalDescriptions(Parcel *parcel);
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp
index 8717914..917c62a 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.cpp
+++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp
@@ -31,6 +31,7 @@
 namespace android {
 
 static const int64_t kAdjustmentProcessingTimeUs = 100000ll;
+static const int64_t kWaitTimeUsToRetryRead = 100000ll;
 
 TimedTextPlayer::TimedTextPlayer(const wp<MediaPlayerBase> &listener)
     : mListener(listener),
@@ -139,13 +140,25 @@
 }
 
 void TimedTextPlayer::doRead(MediaSource::ReadOptions* options) {
-    int64_t timeUs = 0;
+    int64_t startTimeUs = 0;
+    int64_t endTimeUs = 0;
     sp<ParcelEvent> parcelEvent = new ParcelEvent();
-    status_t err = mSource->read(&timeUs, &(parcelEvent->parcel), options);
-    if (err != OK) {
+    status_t err = mSource->read(&startTimeUs, &endTimeUs,
+                                 &(parcelEvent->parcel), options);
+    if (err == WOULD_BLOCK) {
+        postTextEventDelayUs(NULL, kWaitTimeUsToRetryRead);
+        return;
+    } else if (err != OK) {
         notifyError(err);
-    } else {
-        postTextEvent(parcelEvent, timeUs);
+        return;
+    }
+
+    postTextEvent(parcelEvent, startTimeUs);
+    if (endTimeUs > 0) {
+        CHECK_GE(endTimeUs, startTimeUs);
+        // send an empty timed text to clear the subtitle when it reaches to the
+        // end time.
+        postTextEvent(NULL, endTimeUs);
     }
 }
 
@@ -162,6 +175,13 @@
         } else {
             delayUs = timeUs - positionUs - kAdjustmentProcessingTimeUs;
         }
+        postTextEventDelayUs(parcel, delayUs);
+    }
+}
+
+void TimedTextPlayer::postTextEventDelayUs(const sp<ParcelEvent>& parcel, int64_t delayUs) {
+    sp<MediaPlayerBase> listener = mListener.promote();
+    if (listener != NULL) {
         sp<AMessage> msg = new AMessage(kWhatSendSubtitle, id());
         msg->setInt32("generation", mSendSubtitleGeneration);
         if (parcel != NULL) {
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.h b/media/libstagefright/timedtext/TimedTextPlayer.h
index b869f18..47aff03 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.h
+++ b/media/libstagefright/timedtext/TimedTextPlayer.h
@@ -67,6 +67,7 @@
     void doRead(MediaSource::ReadOptions* options = NULL);
     void onTextEvent();
     void postTextEvent(const sp<ParcelEvent>& parcel = NULL, int64_t timeUs = -1);
+    void postTextEventDelayUs(const sp<ParcelEvent>& parcel = NULL, int64_t delayUs = -1);
     void notifyError(int error = 0);
     void notifyListener(const Parcel *parcel = NULL);
 
diff --git a/media/libstagefright/timedtext/TimedTextSRTSource.cpp b/media/libstagefright/timedtext/TimedTextSRTSource.cpp
index c44a99b..7b1f7f6 100644
--- a/media/libstagefright/timedtext/TimedTextSRTSource.cpp
+++ b/media/libstagefright/timedtext/TimedTextSRTSource.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <binder/Parcel.h>
+#include <media/stagefright/foundation/ADebug.h>  // for CHECK_xx
 #include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaDefs.h>  // for MEDIA_MIMETYPE_xxx
@@ -63,19 +64,18 @@
 }
 
 status_t TimedTextSRTSource::read(
-        int64_t *timeUs,
+        int64_t *startTimeUs,
+        int64_t *endTimeUs,
         Parcel *parcel,
         const MediaSource::ReadOptions *options) {
-    int64_t endTimeUs;
     AString text;
-    status_t err = getText(options, &text, timeUs, &endTimeUs);
+    status_t err = getText(options, &text, startTimeUs, endTimeUs);
     if (err != OK) {
         return err;
     }
 
-    if (*timeUs > 0) {
-        extractAndAppendLocalDescriptions(*timeUs, text, parcel);
-    }
+    CHECK_GE(*startTimeUs, 0);
+    extractAndAppendLocalDescriptions(*startTimeUs, text, parcel);
     return OK;
 }
 
diff --git a/media/libstagefright/timedtext/TimedTextSRTSource.h b/media/libstagefright/timedtext/TimedTextSRTSource.h
index 62710a0..e1371b8 100644
--- a/media/libstagefright/timedtext/TimedTextSRTSource.h
+++ b/media/libstagefright/timedtext/TimedTextSRTSource.h
@@ -36,7 +36,8 @@
     virtual status_t start();
     virtual status_t stop();
     virtual status_t read(
-            int64_t *timeUs,
+            int64_t *startTimeUs,
+            int64_t *endTimeUs,
             Parcel *parcel,
             const MediaSource::ReadOptions *options = NULL);
     virtual sp<MetaData> getFormat();
diff --git a/media/libstagefright/timedtext/TimedTextSource.h b/media/libstagefright/timedtext/TimedTextSource.h
index 9349342..756cc31 100644
--- a/media/libstagefright/timedtext/TimedTextSource.h
+++ b/media/libstagefright/timedtext/TimedTextSource.h
@@ -43,7 +43,8 @@
   virtual status_t stop() = 0;
   // Returns subtitle parcel and its start time.
   virtual status_t read(
-          int64_t *timeUs,
+          int64_t *startTimeUs,
+          int64_t *endTimeUs,
           Parcel *parcel,
           const MediaSource::ReadOptions *options = NULL) = 0;
   virtual status_t extractGlobalDescriptions(Parcel *parcel) {
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 1652cae..257f62c 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -15,6 +15,7 @@
     $(call include-path-for, audio-effects) \
     $(call include-path-for, audio-utils)
 
+# FIXME keep libmedia_native but remove libmedia after split
 LOCAL_SHARED_LIBRARIES := \
     libaudioutils \
     libcommon_time_client \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d83d19a..3ab4e34 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -894,7 +894,8 @@
             // indicate output device change to all input threads for pre processing
             AudioParameter param = AudioParameter(keyValuePairs);
             int value;
-            if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+            if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
+                    (value != 0)) {
                 for (size_t i = 0; i < mRecordThreads.size(); i++) {
                     mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
                 }
@@ -1588,7 +1589,7 @@
 }
 
 // PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread::Track>  AudioFlinger::PlaybackThread::createTrack_l(
+sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
         const sp<AudioFlinger::Client>& client,
         audio_stream_type_t streamType,
         uint32_t sampleRate,
@@ -2337,7 +2338,7 @@
     size_t tracksWithEffect = 0;
 
     float masterVolume = mMasterVolume;
-    bool  masterMute = mMasterMute;
+    bool masterMute = mMasterMute;
 
     if (masterMute) {
         masterVolume = 0;
@@ -2376,7 +2377,7 @@
                 // +1 for rounding and +1 for additional sample needed for interpolation
                 minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
                 // add frames already consumed but not yet released by the resampler
-                // because cblk->framesReady() will  include these frames
+                // because cblk->framesReady() will include these frames
                 minFrames += mAudioMixer->getUnreleasedFrames(track->name());
                 // the minimum track buffer size is normally twice the number of frames necessary
                 // to fill one buffer and the resampler should not leave more than one buffer worth
@@ -2514,6 +2515,7 @@
 
             // reset retry count
             track->mRetryCount = kMaxTrackRetries;
+
             // If one track is ready, set the mixer ready if:
             //  - the mixer was not ready during previous round OR
             //  - no other track is not ready
@@ -3372,19 +3374,19 @@
         }
     } else {
         mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
-            // construct the shared structure in-place.
-            new(mCblk) audio_track_cblk_t();
-            // clear all buffers
-            mCblk->frameCount = frameCount;
-            mCblk->sampleRate = sampleRate;
-            mChannelCount = channelCount;
-            mChannelMask = channelMask;
-            mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
-            memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
-            // Force underrun condition to avoid false underrun callback until first data is
-            // written to buffer (other flags are cleared)
-            mCblk->flags = CBLK_UNDERRUN_ON;
-            mBufferEnd = (uint8_t *)mBuffer + bufferSize;
+        // construct the shared structure in-place.
+        new(mCblk) audio_track_cblk_t();
+        // clear all buffers
+        mCblk->frameCount = frameCount;
+        mCblk->sampleRate = sampleRate;
+        mChannelCount = channelCount;
+        mChannelMask = channelMask;
+        mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+        memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
+        // Force underrun condition to avoid false underrun callback until first data is
+        // written to buffer (other flags are cleared)
+        mCblk->flags = CBLK_UNDERRUN_ON;
+        mBufferEnd = (uint8_t *)mBuffer + bufferSize;
     }
 }
 
@@ -3792,16 +3794,9 @@
     if (!client->reserveTimedTrack())
         return NULL;
 
-    sp<TimedTrack> track = new TimedTrack(
+    return new TimedTrack(
         thread, client, streamType, sampleRate, format, channelMask, frameCount,
         sharedBuffer, sessionId);
-
-    if (track == NULL) {
-        client->releaseTimedTrack();
-        return NULL;
-    }
-
-    return track;
 }
 
 AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
@@ -4261,7 +4256,7 @@
         RecordThread *recordThread = (RecordThread *)thread.get();
         recordThread->stop(this);
         TrackBase::reset();
-        // Force overerrun condition to avoid false overrun callback until first data is
+        // Force overrun condition to avoid false overrun callback until first data is
         // read from buffer
         android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
     }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 0e4b24a..7a57613 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -899,6 +899,7 @@
     protected:
         SortedVector< wp<Track> >       mActiveTracks;
 
+        // Allocate a track name.  Returns name >= 0 if successful, -1 on failure.
         virtual int             getTrackName_l() = 0;
         virtual void            deleteTrackName_l(int name) = 0;
         virtual uint32_t        activeSleepTimeUs();
@@ -1559,9 +1560,10 @@
         uint32_t mNewLeftVolume;       // new volume on left channel
         uint32_t mNewRightVolume;      // new volume on right channel
         uint32_t mStrategy; // strategy for this effect chain
-        // mSuspendedEffects lists all effect currently suspended in the chain
-        // use effect type UUID timelow field as key. There is no real risk of identical
+        // mSuspendedEffects lists all effects currently suspended in the chain.
+        // Use effect type UUID timelow field as key. There is no real risk of identical
         // timeLow fields among effect type UUIDs.
+        // Updated by updateSuspendedSessions_l() only.
         KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
     };
 
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 91f7515..3f4c19a 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -60,6 +60,10 @@
     mState.outputTemp   = NULL;
     mState.resampleTemp = NULL;
     // mState.reserved
+
+    // FIXME Most of the following initialization is probably redundant since
+    // tracks[i] should only be referenced if (mTrackNames & (1 << i)) != 0
+    // and mTrackNames is initially 0.  However, leave it here until that's verified.
     track_t* t = mState.tracks;
     for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
         t->needs = 0;
@@ -135,7 +139,7 @@
         invalidateState(1<<name);
     }
     if (track.resampler != NULL) {
-        // delete  the resampler
+        // delete the resampler
         delete track.resampler;
         track.resampler = NULL;
         track.sampleRate = mSampleRate;
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 7a61467..856450c 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -71,9 +71,14 @@
 
 
     // For all APIs with "name": TRACK0 <= name < TRACK0 + MAX_NUM_TRACKS
+
+    // Allocate a track name.  Returns new track name if successful, -1 on failure.
     int         getTrackName();
+
+    // Free an allocated track by name
     void        deleteTrackName(int name);
 
+    // Enable or disable an allocated track by name
     void        enable(int name);
     void        disable(int name);