<commit_before>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// Author: Alexander Chemeris <Alexander DOT Chemeris AT SIPez DOT com>

// SYSTEM INCLUDES
#include <assert.h>

// APPLICATION INCLUDES
#include <mp/MpAudioOutputConnection.h>
#include <mp/MpOutputDeviceDriver.h>
#include <mp/MpMediaTask.h> // for MpMediaTask::signalFrameStart()
#include <os/OsLock.h>
#include <os/OsCallback.h>
#include <os/OsDefs.h>    // for min macro

#ifdef RTL_ENABLED
#include <rtl_macro.h>
#else
#define RTL_BLOCK(x)
#define RTL_EVENT(x,y)
#endif

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STATIC VARIABLE INITIALIZATIONS
// PRIVATE CLASSES
// DEFINES
#define DEBUG_PRINT
#undef  DEBUG_PRINT

// MACROS
#ifdef DEBUG_PRINT // [
#  define debugPrintf    printf
#else  // DEBUG_PRINT ][
static void debugPrintf(...) {}
#endif // DEBUG_PRINT ]

/* //////////////////////////// PUBLIC //////////////////////////////////// */

/* ============================ CREATORS ================================== */

MpAudioOutputConnection::MpAudioOutputConnection(MpOutputDeviceHandle deviceId,
                                                 MpOutputDeviceDriver *deviceDriver)
: UtlInt(deviceId)
, mMutex(OsMutexBase::Q_PRIORITY)
, mUseCount(0)
, mpDeviceDriver(deviceDriver)
, mCurrentFrameTime(0)
, mMixerBufferLength(0)
, mpMixerBuffer(NULL)
, mMixerBufferBegin(0)
, mpTickerCallback(NULL)
, mDoFlowgraphTicker(FALSE)
{
   assert(mpDeviceDriver != NULL);
};

MpAudioOutputConnection::~MpAudioOutputConnection()
{
   assert(mpTickerCallback == NULL);
   if (mpTickerCallback != NULL)
   {
      if (mpDeviceDriver != NULL)
      {
         mpDeviceDriver->setTickerNotification(NULL);
      }

      delete mpTickerCallback;
      mpTickerCallback = NULL;
   }
}

/* ============================ MANIPULATORS ============================== */

OsStatus MpAudioOutputConnection::enableDevice(unsigned samplesPerFrame,
                                               unsigned samplesPerSec,
                                               MpFrameTime currentFrameTime,
                                               MpFrameTime mixerBufferLength)
{
   OsStatus result = OS_FAILED;
   OsLock lock(mMutex);

   assert(samplesPerFrame > 0);
   assert(samplesPerSec > 0);

   if (mpDeviceDriver->isEnabled())
   {
      return OS_INVALID_STATE;
   }

   // Driver should be able to request next frame in mixer mode.
   if (mixerBufferLength > 0 && !mpDeviceDriver->isFrameTickerSupported())
   {
      return OS_NOT_SUPPORTED;
   }

   // Set current frame time for this connection.
   mCurrentFrameTime = currentFrameTime;

   // Allocate mixer buffer if requested.
   // There is nothing to do if it is not requested, as we're sure that we was
   // in disabled state and mixer buffer was not allocated.
   if (mixerBufferLength > 0)
   {
      // Calculate number of samples in mixer buffer.
      // I.e. convert from milliseconds to samples and round to frame boundary.
      // Note: this calculation may overflow (e.g. 10000msec*44100Hz > 4294967296smp).
      unsigned bufferSamples = mixerBufferLength*samplesPerSec/1000;
      bufferSamples = ((bufferSamples + samplesPerFrame - 1) / samplesPerFrame)
                     * samplesPerFrame;

      // Initialize mixer buffer. All mixer buffer related variables will be set here.
      if (initMixerBuffer(bufferSamples) != OS_SUCCESS)
      {
         return result;
      }
   }

   // Enable ticker if needed.
   if (isTickerNeeded())
   {
      setDeviceTicker();
   }

   // Enable device driver
   result = mpDeviceDriver->enableDevice(samplesPerFrame, samplesPerSec,
                                         mCurrentFrameTime);

   return result;
}

OsStatus MpAudioOutputConnection::disableDevice()
{
   OsStatus result = OS_FAILED;
   OsLock lock(mMutex);

   // Disable ticker notification and delete it if any.
   if (isTickerNeeded())
   {
      clearDeviceTicker();
   }

   // Disable device and set result code.
   result = mpDeviceDriver->disableDevice();

   // Free mixer buffer if device was set to disabled state.
   if (!mpDeviceDriver->isEnabled())
   {
      // Do not check return code, as it is not critical if it fails.
      freeMixerBuffer();
   }

   return result;
}

OsStatus MpAudioOutputConnection::enableFlowgraphTicker()
{
   OsStatus result = OS_NOT_SUPPORTED;
   OsLock lock(mMutex);

   assert(mDoFlowgraphTicker == FALSE);

   if (mpDeviceDriver->isFrameTickerSupported())
   {
      result = OS_SUCCESS;

      // Set flowgraph ticker flag
      mDoFlowgraphTicker = TRUE;

      // Enable ticker if not enabled already
      if (mpTickerCallback == NULL)
      {
         result = setDeviceTicker();
      }
   }

   return result;
}

OsStatus MpAudioOutputConnection::disableFlowgraphTicker()
{
   OsStatus result = OS_NOT_SUPPORTED;
   OsLock lock(mMutex);

   assert(mDoFlowgraphTicker == TRUE);

   if (mpDeviceDriver->isFrameTickerSupported())
   {
      result = OS_SUCCESS;

      // Set flowgraph ticker flag
      mDoFlowgraphTicker = FALSE;

      // Disable ticker if we're not in mixer mode.
      if (!isTickerNeeded())
      {
         clearDeviceTicker();
      }
   }

   return result;
}

OsStatus MpAudioOutputConnection::pushFrame(unsigned int numSamples,
                                            const MpAudioSample* samples,
                                            MpFrameTime frameTime)
{
   OsStatus result = OS_FAILED;
   RTL_BLOCK("MpAudioOutputConnection::pushFrame");

   assert(numSamples > 0);

   // Check for late frame. Check for too early frame is done inside mixFrame()
   // function (if mixer mode is used) and will not be done if direct write
   // mode is used.
   // TODO:: This check should be fixed to support frame time wrap around.
   if (frameTime < mCurrentFrameTime)
   {
      debugPrintf("MpAudioOutputConnection::pushFrame()"
                  " OS_INVALID_STATE frameTime=%d, currentTime=%d\n",
                  frameTime, mCurrentFrameTime);
      result = OS_INVALID_STATE;
      return result;
   }

   // From now we access internal data. Take lock.
   OsLock lock(mMutex);
   RTL_EVENT("MpAudioOutputConnection::pushFrame", this->getValue());

   // Do we have mixer buffer, i.e. are we in direct write mode or not?
   if (isMixerBufferAvailable())
   {
      // We're in mixer mode.

      // Do nothing if no audio was pushed. Mixer buffer will be filled with
      // silence or data from other sources.
      if (samples != NULL)
      {
         // Convert frameTime to offset in mixer buffer.
         // Note: frameTime >= mCurrentFrameTime.
         unsigned mixerBufferOffsetFrames =
                  (frameTime-mCurrentFrameTime) / mpDeviceDriver->getFramePeriod();
         unsigned mixerBufferOffsetSamples =
                  mixerBufferOffsetFrames * mpDeviceDriver->getSamplesPerFrame();

         // Mix this data with other sources.
         result = mixFrame(mixerBufferOffsetSamples, samples, numSamples);
      }
   }
   else
   {
      // We're in direct write mode.

      // In this mode pushed frame should have same size as device driver frame.
      // Later we may write code which enable pushing frames containing multiple
      // device driver frames.
      assert(numSamples == mpDeviceDriver->getSamplesPerFrame());

      // So, push data to device driver and forget.
      result = mpDeviceDriver->pushFrame(numSamples, samples, frameTime);

      // But do not forget to advance our frame time.
      mCurrentFrameTime += numSamples * 1000 / mpDeviceDriver->getSamplesPerSec();
   }

   return result;
};

/* ============================ ACCESSORS ================================= */

/* ============================ INQUIRY =================================== */

/* //////////////////////////// PROTECTED ///////////////////////////////// */

OsStatus MpAudioOutputConnection::initMixerBuffer(unsigned mixerBufferLength)
{
   // We cannot allocate buffer of zero length.
   if (mixerBufferLength == 0)
   {
      return OS_FAILED;
   }

   // Deallocate mixer buffer if it is allocated.
   if (isMixerBufferAvailable())
   {
      // Do not check return value. Nothing fatal may happen inside.
      freeMixerBuffer();
   }

   // Initialize variables.
   mMixerBufferLength = mixerBufferLength;
   mpMixerBuffer = new MpAudioSample[mMixerBufferLength];
   mMixerBufferBegin = 0;

   // Clear buffer data.
   memset(mpMixerBuffer, 0, mMixerBufferLength*sizeof(MpAudioSample));

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::freeMixerBuffer()
{
   OsStatus result = OS_FAILED;

   // Free only if there is something to free.
   if (isMixerBufferAvailable())
   {
      mMixerBufferLength = 0;
      if (mpMixerBuffer != NULL)
      {
         delete[] mpMixerBuffer;
         mpMixerBuffer = NULL;
      }
      mMixerBufferBegin = 0;

      result = OS_SUCCESS;
   }

   return result;
}

OsStatus MpAudioOutputConnection::mixFrame(unsigned frameOffset,
                                           const MpAudioSample* samples,
                                           unsigned numSamples)
{
   assert(numSamples > 0);
   assert(samples != NULL);

   // Check for late frame. Whole frame should fit into buffer to be accepted.
   if (frameOffset+numSamples > mMixerBufferLength)
   {
      debugPrintf("MpAudioOutputConnection::mixFrame()"
                  " OS_LIMIT_REACHED offset=%d, samples=%d, bufferLength=%d\n",
                  frameOffset, numSamples, mMixerBufferLength);
      return OS_LIMIT_REACHED;
   }

   // Calculate frame start as if buffer is linear
   unsigned frameBegin = mMixerBufferBegin+frameOffset;
   // and wrap it because it is circular actually.
   if (frameBegin >= mMixerBufferLength)
   {
      frameBegin -= mMixerBufferLength;
   }

   // Calculate size of first chunk to mix.
   unsigned firstChunkSize = sipx_min(numSamples, mMixerBufferLength-frameBegin);

   // Counter variables for next two loops
   unsigned srcIndex, dstIndex;

   // from frame begin to buffer wrap
   for (srcIndex=0, dstIndex=frameBegin;
        srcIndex<firstChunkSize;
        srcIndex++, dstIndex++)
   {
      mpMixerBuffer[dstIndex] += samples[srcIndex];
   }

   // from buffer wrap to frame end
   for (dstIndex=0;
        srcIndex<numSamples;
        srcIndex++, dstIndex++)
   {
      mpMixerBuffer[dstIndex] += samples[srcIndex];
   }

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::advanceMixerBuffer(unsigned numSamples)
{
   assert(numSamples > 0 && numSamples <= mMixerBufferLength);

   // If buffer could be copied in one pass
   if (mMixerBufferBegin+numSamples <= mMixerBufferLength)
   {
      memset(&mpMixerBuffer[mMixerBufferBegin],
             0,
             numSamples*sizeof(MpAudioSample));
      mMixerBufferBegin += numSamples;
      mMixerBufferBegin %= mMixerBufferLength;
   }
   else
   {
      unsigned firstChunkSize = mMixerBufferLength-mMixerBufferBegin;
      memset(&mpMixerBuffer[mMixerBufferBegin],
             0,
             firstChunkSize*sizeof(MpAudioSample));
      memset(&mpMixerBuffer[0],
             0,
             (numSamples-firstChunkSize)*sizeof(MpAudioSample));

      mMixerBufferBegin = numSamples - firstChunkSize;
   }

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::setDeviceTicker()
{
   // Do driver support ticker callback?
   if (!mpDeviceDriver->isFrameTickerSupported())
   {
      return OS_NOT_SUPPORTED;
   }

   // Create callback and register it with device driver
   mpTickerCallback = new OsCallback((int)this, tickerCallback);
   assert(mpTickerCallback != NULL);
   if (mpDeviceDriver->setTickerNotification(mpTickerCallback) != OS_SUCCESS)
   {
      delete mpTickerCallback;
      mpTickerCallback = NULL;
      freeMixerBuffer();
      return OS_FAILED;
   }

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::clearDeviceTicker()
{
   assert(mpTickerCallback != NULL);

   mpDeviceDriver->setTickerNotification(NULL);
   delete mpTickerCallback;
   mpTickerCallback = NULL;

   return OS_SUCCESS;
}

void MpAudioOutputConnection::tickerCallback(const int userData, const int eventData)
{
   OsStatus result;
   MpAudioOutputConnection *pConnection = (MpAudioOutputConnection*)userData;
   RTL_BLOCK("MpAudioOutputConnection::tickerCallBack");

   if (pConnection->mMutex.acquire(OsTime(5)) == OS_SUCCESS)
   {

      // If we're in mixer mode - push frame to device.
      if (pConnection->isMixerBufferAvailable())
      {
         // So, push data to device driver and forget.
         result = pConnection->mpDeviceDriver->pushFrame(
                        pConnection->mpDeviceDriver->getSamplesPerFrame(),
                        pConnection->mpMixerBuffer+pConnection->mMixerBufferBegin,
                        pConnection->mCurrentFrameTime);
         debugPrintf("MpAudioOutputConnection::tickerCallback()"
                     " frame=%d, pushFrame result=%d\n",
                     pConnection->mCurrentFrameTime, result);
//       assert(result == OS_SUCCESS);

         // Advance mixer buffer and frame time.
         pConnection->advanceMixerBuffer(pConnection->mpDeviceDriver->getSamplesPerFrame());
         pConnection->mCurrentFrameTime +=
                              pConnection->mpDeviceDriver->getSamplesPerFrame() * 1000
                              / pConnection->mpDeviceDriver->getSamplesPerSec();
      }

      // Signal frame processing interval start if we were asked about.
      if (pConnection->mDoFlowgraphTicker)
      {
         MpMediaTask::signalFrameStart();
      }

      pConnection->mMutex.release();
   }
}

/* //////////////////////////// PRIVATE /////////////////////////////////// */

/* ============================ FUNCTIONS ================================= */

<commit_msg>Reduce scope of lock in MpAudioOutputConnection::tickerCallback() to cut down context switch overhead in case when MediaTask have higher priority  then driver's thread. This is undesirable combination of threads' priorities, though.<commit_after>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// Author: Alexander Chemeris <Alexander DOT Chemeris AT SIPez DOT com>

// SYSTEM INCLUDES
#include <assert.h>

// APPLICATION INCLUDES
#include <mp/MpAudioOutputConnection.h>
#include <mp/MpOutputDeviceDriver.h>
#include <mp/MpMediaTask.h> // for MpMediaTask::signalFrameStart()
#include <os/OsLock.h>
#include <os/OsCallback.h>
#include <os/OsDefs.h>    // for min macro

#ifdef RTL_ENABLED
#include <rtl_macro.h>
#else
#define RTL_BLOCK(x)
#define RTL_EVENT(x,y)
#endif

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STATIC VARIABLE INITIALIZATIONS
// PRIVATE CLASSES
// DEFINES
#define DEBUG_PRINT
#undef  DEBUG_PRINT

// MACROS
#ifdef DEBUG_PRINT // [
#  define debugPrintf    printf
#else  // DEBUG_PRINT ][
static void debugPrintf(...) {}
#endif // DEBUG_PRINT ]

/* //////////////////////////// PUBLIC //////////////////////////////////// */

/* ============================ CREATORS ================================== */

MpAudioOutputConnection::MpAudioOutputConnection(MpOutputDeviceHandle deviceId,
                                                 MpOutputDeviceDriver *deviceDriver)
: UtlInt(deviceId)
, mMutex(OsMutexBase::Q_PRIORITY)
, mUseCount(0)
, mpDeviceDriver(deviceDriver)
, mCurrentFrameTime(0)
, mMixerBufferLength(0)
, mpMixerBuffer(NULL)
, mMixerBufferBegin(0)
, mpTickerCallback(NULL)
, mDoFlowgraphTicker(FALSE)
{
   assert(mpDeviceDriver != NULL);
};

MpAudioOutputConnection::~MpAudioOutputConnection()
{
   assert(mpTickerCallback == NULL);
   if (mpTickerCallback != NULL)
   {
      if (mpDeviceDriver != NULL)
      {
         mpDeviceDriver->setTickerNotification(NULL);
      }

      delete mpTickerCallback;
      mpTickerCallback = NULL;
   }
}

/* ============================ MANIPULATORS ============================== */

OsStatus MpAudioOutputConnection::enableDevice(unsigned samplesPerFrame,
                                               unsigned samplesPerSec,
                                               MpFrameTime currentFrameTime,
                                               MpFrameTime mixerBufferLength)
{
   OsStatus result = OS_FAILED;
   OsLock lock(mMutex);

   assert(samplesPerFrame > 0);
   assert(samplesPerSec > 0);

   if (mpDeviceDriver->isEnabled())
   {
      return OS_INVALID_STATE;
   }

   // Driver should be able to request next frame in mixer mode.
   if (mixerBufferLength > 0 && !mpDeviceDriver->isFrameTickerSupported())
   {
      return OS_NOT_SUPPORTED;
   }

   // Set current frame time for this connection.
   mCurrentFrameTime = currentFrameTime;

   // Allocate mixer buffer if requested.
   // There is nothing to do if it is not requested, as we're sure that we was
   // in disabled state and mixer buffer was not allocated.
   if (mixerBufferLength > 0)
   {
      // Calculate number of samples in mixer buffer.
      // I.e. convert from milliseconds to samples and round to frame boundary.
      // Note: this calculation may overflow (e.g. 10000msec*44100Hz > 4294967296smp).
      unsigned bufferSamples = mixerBufferLength*samplesPerSec/1000;
      bufferSamples = ((bufferSamples + samplesPerFrame - 1) / samplesPerFrame)
                     * samplesPerFrame;

      // Initialize mixer buffer. All mixer buffer related variables will be set here.
      if (initMixerBuffer(bufferSamples) != OS_SUCCESS)
      {
         return result;
      }
   }

   // Enable ticker if needed.
   if (isTickerNeeded())
   {
      setDeviceTicker();
   }

   // Enable device driver
   result = mpDeviceDriver->enableDevice(samplesPerFrame, samplesPerSec,
                                         mCurrentFrameTime);

   return result;
}

OsStatus MpAudioOutputConnection::disableDevice()
{
   OsStatus result = OS_FAILED;
   OsLock lock(mMutex);

   // Disable ticker notification and delete it if any.
   if (isTickerNeeded())
   {
      clearDeviceTicker();
   }

   // Disable device and set result code.
   result = mpDeviceDriver->disableDevice();

   // Free mixer buffer if device was set to disabled state.
   if (!mpDeviceDriver->isEnabled())
   {
      // Do not check return code, as it is not critical if it fails.
      freeMixerBuffer();
   }

   return result;
}

OsStatus MpAudioOutputConnection::enableFlowgraphTicker()
{
   OsStatus result = OS_NOT_SUPPORTED;
   OsLock lock(mMutex);

   assert(mDoFlowgraphTicker == FALSE);

   if (mpDeviceDriver->isFrameTickerSupported())
   {
      result = OS_SUCCESS;

      // Set flowgraph ticker flag
      mDoFlowgraphTicker = TRUE;

      // Enable ticker if not enabled already
      if (mpTickerCallback == NULL)
      {
         result = setDeviceTicker();
      }
   }

   return result;
}

OsStatus MpAudioOutputConnection::disableFlowgraphTicker()
{
   OsStatus result = OS_NOT_SUPPORTED;
   OsLock lock(mMutex);

   assert(mDoFlowgraphTicker == TRUE);

   if (mpDeviceDriver->isFrameTickerSupported())
   {
      result = OS_SUCCESS;

      // Set flowgraph ticker flag
      mDoFlowgraphTicker = FALSE;

      // Disable ticker if we're not in mixer mode.
      if (!isTickerNeeded())
      {
         clearDeviceTicker();
      }
   }

   return result;
}

OsStatus MpAudioOutputConnection::pushFrame(unsigned int numSamples,
                                            const MpAudioSample* samples,
                                            MpFrameTime frameTime)
{
   OsStatus result = OS_FAILED;
   RTL_BLOCK("MpAudioOutputConnection::pushFrame");

   assert(numSamples > 0);

   // Check for late frame. Check for too early frame is done inside mixFrame()
   // function (if mixer mode is used) and will not be done if direct write
   // mode is used.
   // TODO:: This check should be fixed to support frame time wrap around.
   if (frameTime < mCurrentFrameTime)
   {
      debugPrintf("MpAudioOutputConnection::pushFrame()"
                  " OS_INVALID_STATE frameTime=%d, currentTime=%d\n",
                  frameTime, mCurrentFrameTime);
      result = OS_INVALID_STATE;
      return result;
   }

   // From now we access internal data. Take lock.
   OsLock lock(mMutex);
   RTL_EVENT("MpAudioOutputConnection::pushFrame", this->getValue());

   // Do we have mixer buffer, i.e. are we in direct write mode or not?
   if (isMixerBufferAvailable())
   {
      // We're in mixer mode.

      // Do nothing if no audio was pushed. Mixer buffer will be filled with
      // silence or data from other sources.
      if (samples != NULL)
      {
         // Convert frameTime to offset in mixer buffer.
         // Note: frameTime >= mCurrentFrameTime.
         unsigned mixerBufferOffsetFrames =
                  (frameTime-mCurrentFrameTime) / mpDeviceDriver->getFramePeriod();
         unsigned mixerBufferOffsetSamples =
                  mixerBufferOffsetFrames * mpDeviceDriver->getSamplesPerFrame();

         // Mix this data with other sources.
         result = mixFrame(mixerBufferOffsetSamples, samples, numSamples);
      }
   }
   else
   {
      // We're in direct write mode.

      // In this mode pushed frame should have same size as device driver frame.
      // Later we may write code which enable pushing frames containing multiple
      // device driver frames.
      assert(numSamples == mpDeviceDriver->getSamplesPerFrame());

      // So, push data to device driver and forget.
      result = mpDeviceDriver->pushFrame(numSamples, samples, frameTime);

      // But do not forget to advance our frame time.
      mCurrentFrameTime += numSamples * 1000 / mpDeviceDriver->getSamplesPerSec();
   }

   return result;
};

/* ============================ ACCESSORS ================================= */

/* ============================ INQUIRY =================================== */

/* //////////////////////////// PROTECTED ///////////////////////////////// */

OsStatus MpAudioOutputConnection::initMixerBuffer(unsigned mixerBufferLength)
{
   // We cannot allocate buffer of zero length.
   if (mixerBufferLength == 0)
   {
      return OS_FAILED;
   }

   // Deallocate mixer buffer if it is allocated.
   if (isMixerBufferAvailable())
   {
      // Do not check return value. Nothing fatal may happen inside.
      freeMixerBuffer();
   }

   // Initialize variables.
   mMixerBufferLength = mixerBufferLength;
   mpMixerBuffer = new MpAudioSample[mMixerBufferLength];
   mMixerBufferBegin = 0;

   // Clear buffer data.
   memset(mpMixerBuffer, 0, mMixerBufferLength*sizeof(MpAudioSample));

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::freeMixerBuffer()
{
   OsStatus result = OS_FAILED;

   // Free only if there is something to free.
   if (isMixerBufferAvailable())
   {
      mMixerBufferLength = 0;
      if (mpMixerBuffer != NULL)
      {
         delete[] mpMixerBuffer;
         mpMixerBuffer = NULL;
      }
      mMixerBufferBegin = 0;

      result = OS_SUCCESS;
   }

   return result;
}

OsStatus MpAudioOutputConnection::mixFrame(unsigned frameOffset,
                                           const MpAudioSample* samples,
                                           unsigned numSamples)
{
   assert(numSamples > 0);
   assert(samples != NULL);

   // Check for late frame. Whole frame should fit into buffer to be accepted.
   if (frameOffset+numSamples > mMixerBufferLength)
   {
      debugPrintf("MpAudioOutputConnection::mixFrame()"
                  " OS_LIMIT_REACHED offset=%d, samples=%d, bufferLength=%d\n",
                  frameOffset, numSamples, mMixerBufferLength);
      return OS_LIMIT_REACHED;
   }

   // Calculate frame start as if buffer is linear
   unsigned frameBegin = mMixerBufferBegin+frameOffset;
   // and wrap it because it is circular actually.
   if (frameBegin >= mMixerBufferLength)
   {
      frameBegin -= mMixerBufferLength;
   }

   // Calculate size of first chunk to mix.
   unsigned firstChunkSize = sipx_min(numSamples, mMixerBufferLength-frameBegin);

   // Counter variables for next two loops
   unsigned srcIndex, dstIndex;

   // from frame begin to buffer wrap
   for (srcIndex=0, dstIndex=frameBegin;
        srcIndex<firstChunkSize;
        srcIndex++, dstIndex++)
   {
      mpMixerBuffer[dstIndex] += samples[srcIndex];
   }

   // from buffer wrap to frame end
   for (dstIndex=0;
        srcIndex<numSamples;
        srcIndex++, dstIndex++)
   {
      mpMixerBuffer[dstIndex] += samples[srcIndex];
   }

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::advanceMixerBuffer(unsigned numSamples)
{
   assert(numSamples > 0 && numSamples <= mMixerBufferLength);

   // If buffer could be copied in one pass
   if (mMixerBufferBegin+numSamples <= mMixerBufferLength)
   {
      memset(&mpMixerBuffer[mMixerBufferBegin],
             0,
             numSamples*sizeof(MpAudioSample));
      mMixerBufferBegin += numSamples;
      mMixerBufferBegin %= mMixerBufferLength;
   }
   else
   {
      unsigned firstChunkSize = mMixerBufferLength-mMixerBufferBegin;
      memset(&mpMixerBuffer[mMixerBufferBegin],
             0,
             firstChunkSize*sizeof(MpAudioSample));
      memset(&mpMixerBuffer[0],
             0,
             (numSamples-firstChunkSize)*sizeof(MpAudioSample));

      mMixerBufferBegin = numSamples - firstChunkSize;
   }

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::setDeviceTicker()
{
   // Do driver support ticker callback?
   if (!mpDeviceDriver->isFrameTickerSupported())
   {
      return OS_NOT_SUPPORTED;
   }

   // Create callback and register it with device driver
   mpTickerCallback = new OsCallback((int)this, tickerCallback);
   assert(mpTickerCallback != NULL);
   if (mpDeviceDriver->setTickerNotification(mpTickerCallback) != OS_SUCCESS)
   {
      delete mpTickerCallback;
      mpTickerCallback = NULL;
      freeMixerBuffer();
      return OS_FAILED;
   }

   return OS_SUCCESS;
}

OsStatus MpAudioOutputConnection::clearDeviceTicker()
{
   assert(mpTickerCallback != NULL);

   mpDeviceDriver->setTickerNotification(NULL);
   delete mpTickerCallback;
   mpTickerCallback = NULL;

   return OS_SUCCESS;
}

void MpAudioOutputConnection::tickerCallback(const int userData, const int eventData)
{
   OsStatus result;
   MpAudioOutputConnection *pConnection = (MpAudioOutputConnection*)userData;
   RTL_BLOCK("MpAudioOutputConnection::tickerCallBack");

   if (pConnection->mMutex.acquire(OsTime(5)) == OS_SUCCESS)
   {

      // If we're in mixer mode - push frame to device.
      if (pConnection->isMixerBufferAvailable())
      {
         // So, push data to device driver and forget.
         result = pConnection->mpDeviceDriver->pushFrame(
                        pConnection->mpDeviceDriver->getSamplesPerFrame(),
                        pConnection->mpMixerBuffer+pConnection->mMixerBufferBegin,
                        pConnection->mCurrentFrameTime);
         debugPrintf("MpAudioOutputConnection::tickerCallback()"
                     " frame=%d, pushFrame result=%d\n",
                     pConnection->mCurrentFrameTime, result);
//       assert(result == OS_SUCCESS);

         // Advance mixer buffer and frame time.
         pConnection->advanceMixerBuffer(pConnection->mpDeviceDriver->getSamplesPerFrame());
         pConnection->mCurrentFrameTime +=
                              pConnection->mpDeviceDriver->getSamplesPerFrame() * 1000
                              / pConnection->mpDeviceDriver->getSamplesPerSec();
      }

      pConnection->mMutex.release();
   }

   // Signal frame processing interval start if we were asked about.
   if (pConnection->mDoFlowgraphTicker)
   {
      MpMediaTask::signalFrameStart();
   }
}

/* //////////////////////////// PRIVATE /////////////////////////////////// */

/* ============================ FUNCTIONS ================================= */

<|endoftext|>


<commit_before>#include "nw_screen_api.h"

#include "base/lazy_instance.h"
#include "base/values.h"
#include "content/nw/src/api/nw_screen.h"
#include "extensions/browser/extensions_browser_client.h"
#include "ui/display/display_observer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"

// For desktop capture APIs
#include "base/base64.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
#include "chrome/browser/media/webrtc/desktop_streams_registry.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"

using namespace extensions::nwapi::nw__screen;
using namespace content;

namespace extensions {

  class NwDesktopCaptureMonitor : public DesktopMediaListObserver {
  public:
    static NwDesktopCaptureMonitor* GetInstance();

    NwDesktopCaptureMonitor();
    void Start(bool screens, bool windows);
    void Stop();
    bool IsStarted();

  private:
    int GetPrimaryMonitorIndex();
    // DesktopMediaListObserver implementation.
    void OnSourceAdded(DesktopMediaList* list, int index) override;
    void OnSourceRemoved(DesktopMediaList* list, int index) override;
    void OnSourceMoved(DesktopMediaList* list, int old_index, int new_index) override;
    void OnSourceNameChanged(DesktopMediaList* list, int index) override;
    void OnSourceThumbnailChanged(DesktopMediaList* list, int index) override;

    bool started_;
    std::unique_ptr<DesktopMediaList> media_list_;

    DISALLOW_COPY_AND_ASSIGN(NwDesktopCaptureMonitor);
  };

  class NwScreenDisplayObserver: public display::DisplayObserver {
  public:
    static NwScreenDisplayObserver* GetInstance();
    NwScreenDisplayObserver();

  private:
    ~NwScreenDisplayObserver() override;
    // gfx::DisplayObserver implementation.
    void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override;
    void OnDisplayAdded(const display::Display& new_display) override;
    void OnDisplayRemoved(const display::Display& old_display) override;

    DISALLOW_COPY_AND_ASSIGN(NwScreenDisplayObserver);
  };

  namespace {

    // Helper function to convert display::Display to nwapi::nw__screen::Display
    std::unique_ptr<nwapi::nw__screen::Display> ConvertGfxDisplay(const display::Display& gfx_display) {
      std::unique_ptr<nwapi::nw__screen::Display> displayResult(new nwapi::nw__screen::Display);

      displayResult->id = gfx_display.id();
      displayResult->scale_factor = gfx_display.device_scale_factor();
      displayResult->is_built_in = gfx_display.IsInternal();
      displayResult->rotation = gfx_display.RotationAsDegree();
      displayResult->touch_support = gfx_display.touch_support();

      gfx::Rect rect = gfx_display.bounds();
      DisplayGeometry& bounds = displayResult->bounds;
      bounds.x = rect.x();
      bounds.y = rect.y();
      bounds.width = rect.width();
      bounds.height = rect.height();

      rect = gfx_display.work_area();
      DisplayGeometry& work_area = displayResult->work_area;
      work_area.x = rect.x();
      work_area.y = rect.y();
      work_area.width = rect.width();
      work_area.height = rect.height();

      return displayResult;
    }

    void DispatchEvent(
        events::HistogramValue histogram_value,
        const std::string& event_name,
        std::unique_ptr<base::ListValue> args) {
      DCHECK_CURRENTLY_ON(BrowserThread::UI);
      ExtensionsBrowserClient::Get()->BroadcastEventToRenderers(
                                                                histogram_value, event_name, std::move(args));
    }

    // Lazy initialize screen event listeners until first call
    base::LazyInstance<NwScreenDisplayObserver>::Leaky
      g_display_observer = LAZY_INSTANCE_INITIALIZER;

    base::LazyInstance<NwDesktopCaptureMonitor>::Leaky
      g_desktop_capture_monitor = LAZY_INSTANCE_INITIALIZER;

  }

  // static
  NwScreenDisplayObserver* NwScreenDisplayObserver::GetInstance() {
    return g_display_observer.Pointer();
  }

  NwScreenDisplayObserver::NwScreenDisplayObserver() {
    display::Screen* screen = display::Screen::GetScreen();
    if (screen) {
      screen->AddObserver(this);
    }
  }

  NwScreenDisplayObserver::~NwScreenDisplayObserver() {
    display::Screen* screen = display::Screen::GetScreen();
    if (screen) {
      screen->RemoveObserver(this);
    }
  }

  // Called when the |display|'s bound has changed.
  void NwScreenDisplayObserver::OnDisplayMetricsChanged(const display::Display& display,
    uint32_t changed_metrics) {
    std::unique_ptr<base::ListValue> args =
      nwapi::nw__screen::OnDisplayBoundsChanged::Create(*ConvertGfxDisplay(display),
                                                        changed_metrics);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnDisplayBoundsChanged::kEventName,
      std::move(args));
  }

  // Called when |new_display| has been added.
  void NwScreenDisplayObserver::OnDisplayAdded(const display::Display& new_display) {
    std::unique_ptr<base::ListValue> args =
      nwapi::nw__screen::OnDisplayAdded::Create(*ConvertGfxDisplay(new_display));
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnDisplayAdded::kEventName,
      std::move(args));
  }

  // Called when |old_display| has been removed.
  void NwScreenDisplayObserver::OnDisplayRemoved(const display::Display& old_display) {
    std::unique_ptr<base::ListValue> args =
      nwapi::nw__screen::OnDisplayRemoved::Create(*ConvertGfxDisplay(old_display));
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnDisplayRemoved::kEventName,
      std::move(args));
  }

  NwScreenGetScreensFunction::NwScreenGetScreensFunction() {}

  bool NwScreenGetScreensFunction::RunNWSync(base::ListValue* response, std::string* error) {
    const std::vector<display::Display>& displays = display::Screen::GetScreen()->GetAllDisplays();

    for (size_t i=0; i<displays.size(); i++) {
      response->Append(ConvertGfxDisplay(displays[i])->ToValue());
    }

    return true;
  }

  NwScreenInitEventListenersFunction::NwScreenInitEventListenersFunction() {}

  bool NwScreenInitEventListenersFunction::RunNWSync(base::ListValue* response, std::string* error) {
    NwScreenDisplayObserver::GetInstance();
    return true;
  }

  NwDesktopCaptureMonitor* NwDesktopCaptureMonitor::GetInstance() {
    return g_desktop_capture_monitor.Pointer();
  }

  NwDesktopCaptureMonitor::NwDesktopCaptureMonitor()
      : started_(false)
      , media_list_(nullptr) {
  }

  void NwDesktopCaptureMonitor::Start(bool screens, bool windows) {
    if (started_) {
      return;
    }

    started_ = true;

    webrtc::DesktopCaptureOptions options = webrtc::DesktopCaptureOptions::CreateDefault();
    options.set_disable_effects(false);

    if (screens)
      media_list_.reset(new NativeDesktopMediaList(content::DesktopMediaID::TYPE_SCREEN, webrtc::DesktopCapturer::CreateScreenCapturer(options)));
    else if (windows)
      media_list_.reset(new NativeDesktopMediaList(content::DesktopMediaID::TYPE_WINDOW, webrtc::DesktopCapturer::CreateWindowCapturer(options)));

    media_list_->StartUpdating(this);
  }

  void NwDesktopCaptureMonitor::Stop() {
    started_ = false;
    media_list_.reset();
  }

  bool NwDesktopCaptureMonitor::IsStarted() {
    return started_;
  }

  int NwDesktopCaptureMonitor::GetPrimaryMonitorIndex() {
  #ifdef _WIN32
    int count=0;
    for (int i = 0;; ++i) {
      DISPLAY_DEVICE device;
      device.cb = sizeof(device);
      BOOL ret = EnumDisplayDevices(NULL, i, &device, 0);
      if(!ret)
        break;
      if (device.StateFlags & DISPLAY_DEVICE_ACTIVE){
        if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE){
          return count;
        }
        count++;
      }
    }
  #endif
    return -1;
  }

void NwDesktopCaptureMonitor::OnSourceAdded(DesktopMediaList* list, int index) {
    DesktopMediaList::Source src = media_list_->GetSource(index);

    std::string type;
    switch(src.id.type) {
    case content::DesktopMediaID::TYPE_WINDOW:
      type = "window";
      break;
    case content::DesktopMediaID::TYPE_SCREEN:
      type = "screen";
      break;
    case content::DesktopMediaID::TYPE_NONE:
      type = "none";
      break;
    default:
      type = "unknown";
      break;
    }

    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceAdded::Create(
      src.id.ToString(),
      base::UTF16ToUTF8(src.name),
      index,
      type,
      src.id.type == content::DesktopMediaID::TYPE_SCREEN && GetPrimaryMonitorIndex() == index);

    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceAdded::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceRemoved(DesktopMediaList* list, int index) {
    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceRemoved::Create(index);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceRemoved::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceMoved(DesktopMediaList* list, int old_index, int new_index) {
    DesktopMediaList::Source src = media_list_->GetSource(new_index);
    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceOrderChanged::Create(
      src.id.ToString(),
      new_index,
      old_index);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceOrderChanged::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceNameChanged(DesktopMediaList* list, int index) {
    DesktopMediaList::Source src = media_list_->GetSource(index);
    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceNameChanged::Create(
      src.id.ToString(),
      base::UTF16ToUTF8(src.name));
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceNameChanged::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceThumbnailChanged(DesktopMediaList* list, int index) {
    std::string base64;

    DesktopMediaList::Source src = media_list_->GetSource(index);
    SkBitmap bitmap = src.thumbnail.GetRepresentation(1).sk_bitmap();
    std::vector<unsigned char> data;
    bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data);
    if (success){
      base::StringPiece raw_str(reinterpret_cast<const char*>(&data[0]), data.size());
      base::Base64Encode(raw_str, &base64);
    }

    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceThumbnailChanged::Create(
      src.id.ToString(),
      base64);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceThumbnailChanged::kEventName,
      std::move(args));
  }

  NwScreenStartMonitorFunction::NwScreenStartMonitorFunction() {}

  bool NwScreenStartMonitorFunction::RunNWSync(base::ListValue* response, std::string* error) {
    bool screens, windows;
    EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &screens));
    EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &windows));
    NwDesktopCaptureMonitor::GetInstance()->Start(screens, windows);
    return true;
  }

  NwScreenStopMonitorFunction::NwScreenStopMonitorFunction() {}

  bool NwScreenStopMonitorFunction::RunNWSync(base::ListValue* response, std::string* error) {
    NwDesktopCaptureMonitor::GetInstance()->Stop();
    return true;
  }

  NwScreenIsMonitorStartedFunction::NwScreenIsMonitorStartedFunction() {}

  bool NwScreenIsMonitorStartedFunction::RunNWSync(base::ListValue* response, std::string* error) {
    response->AppendBoolean(NwDesktopCaptureMonitor::GetInstance()->IsStarted());
    return true;
  }

  NwScreenRegisterStreamFunction::NwScreenRegisterStreamFunction() {}

  bool NwScreenRegisterStreamFunction::RunNWSync(base::ListValue* response, std::string* error) {
    std::string id;
    EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id));

    // following code is modified from `DesktopCaptureChooseDesktopMediaFunctionBase::OnPickerDialogResults`
    // in chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc

    content::DesktopMediaID source = content::DesktopMediaID::Parse(id);
    content::WebContents* web_contents = GetSenderWebContents();
    if (!source.is_null() && web_contents) {
      std::string result;
      source.audio_share = true;
      DesktopStreamsRegistry* registry =
        MediaCaptureDevicesDispatcher::GetInstance()->
        GetDesktopStreamsRegistry();
      // TODO(miu): Once render_frame_host() is being set, we should register the
      // exact RenderFrame requesting the stream, not the main RenderFrame.  With
      // that change, also update
      // MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest().
      // http://crbug.com/304341
      content::RenderFrameHost* const main_frame = web_contents->GetMainFrame();
      result = registry->RegisterStream(main_frame->GetProcess()->GetID(),
                                        main_frame->GetRoutingID(),
                                        web_contents->GetURL().GetOrigin(),
                                        source,
                                        extension()->name());
      response->AppendString(result);
    }
    return true;
  }

} // extensions
<commit_msg>DesktopCaptureMonitor: Allow screens and windows both being monitor at the same time<commit_after>#include "nw_screen_api.h"

#include "base/lazy_instance.h"
#include "base/values.h"
#include "content/nw/src/api/nw_screen.h"
#include "extensions/browser/extensions_browser_client.h"
#include "ui/display/display_observer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"

// For desktop capture APIs
#include "base/base64.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
#include "chrome/browser/media/webrtc/desktop_streams_registry.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"

using namespace extensions::nwapi::nw__screen;
using namespace content;

namespace extensions {

  class NwDesktopCaptureMonitor : public DesktopMediaListObserver {
  public:
    static NwDesktopCaptureMonitor* GetInstance();

    NwDesktopCaptureMonitor();
    void Start(bool screens, bool windows);
    void Stop();
    bool IsStarted();

  private:
    int GetPrimaryMonitorIndex();
    // DesktopMediaListObserver implementation.
    void OnSourceAdded(DesktopMediaList* list, int index) override;
    void OnSourceRemoved(DesktopMediaList* list, int index) override;
    void OnSourceMoved(DesktopMediaList* list, int old_index, int new_index) override;
    void OnSourceNameChanged(DesktopMediaList* list, int index) override;
    void OnSourceThumbnailChanged(DesktopMediaList* list, int index) override;

    bool started_;
    std::vector<std::unique_ptr<DesktopMediaList>> media_list_;

    DISALLOW_COPY_AND_ASSIGN(NwDesktopCaptureMonitor);
  };

  class NwScreenDisplayObserver: public display::DisplayObserver {
  public:
    static NwScreenDisplayObserver* GetInstance();
    NwScreenDisplayObserver();

  private:
    ~NwScreenDisplayObserver() override;
    // gfx::DisplayObserver implementation.
    void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override;
    void OnDisplayAdded(const display::Display& new_display) override;
    void OnDisplayRemoved(const display::Display& old_display) override;

    DISALLOW_COPY_AND_ASSIGN(NwScreenDisplayObserver);
  };

  namespace {

    // Helper function to convert display::Display to nwapi::nw__screen::Display
    std::unique_ptr<nwapi::nw__screen::Display> ConvertGfxDisplay(const display::Display& gfx_display) {
      std::unique_ptr<nwapi::nw__screen::Display> displayResult(new nwapi::nw__screen::Display);

      displayResult->id = gfx_display.id();
      displayResult->scale_factor = gfx_display.device_scale_factor();
      displayResult->is_built_in = gfx_display.IsInternal();
      displayResult->rotation = gfx_display.RotationAsDegree();
      displayResult->touch_support = gfx_display.touch_support();

      gfx::Rect rect = gfx_display.bounds();
      DisplayGeometry& bounds = displayResult->bounds;
      bounds.x = rect.x();
      bounds.y = rect.y();
      bounds.width = rect.width();
      bounds.height = rect.height();

      rect = gfx_display.work_area();
      DisplayGeometry& work_area = displayResult->work_area;
      work_area.x = rect.x();
      work_area.y = rect.y();
      work_area.width = rect.width();
      work_area.height = rect.height();

      return displayResult;
    }

    void DispatchEvent(
        events::HistogramValue histogram_value,
        const std::string& event_name,
        std::unique_ptr<base::ListValue> args) {
      DCHECK_CURRENTLY_ON(BrowserThread::UI);
      ExtensionsBrowserClient::Get()->BroadcastEventToRenderers(
                                                                histogram_value, event_name, std::move(args));
    }

    // Lazy initialize screen event listeners until first call
    base::LazyInstance<NwScreenDisplayObserver>::Leaky
      g_display_observer = LAZY_INSTANCE_INITIALIZER;

    base::LazyInstance<NwDesktopCaptureMonitor>::Leaky
      g_desktop_capture_monitor = LAZY_INSTANCE_INITIALIZER;

  }

  // static
  NwScreenDisplayObserver* NwScreenDisplayObserver::GetInstance() {
    return g_display_observer.Pointer();
  }

  NwScreenDisplayObserver::NwScreenDisplayObserver() {
    display::Screen* screen = display::Screen::GetScreen();
    if (screen) {
      screen->AddObserver(this);
    }
  }

  NwScreenDisplayObserver::~NwScreenDisplayObserver() {
    display::Screen* screen = display::Screen::GetScreen();
    if (screen) {
      screen->RemoveObserver(this);
    }
  }

  // Called when the |display|'s bound has changed.
  void NwScreenDisplayObserver::OnDisplayMetricsChanged(const display::Display& display,
    uint32_t changed_metrics) {
    std::unique_ptr<base::ListValue> args =
      nwapi::nw__screen::OnDisplayBoundsChanged::Create(*ConvertGfxDisplay(display),
                                                        changed_metrics);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnDisplayBoundsChanged::kEventName,
      std::move(args));
  }

  // Called when |new_display| has been added.
  void NwScreenDisplayObserver::OnDisplayAdded(const display::Display& new_display) {
    std::unique_ptr<base::ListValue> args =
      nwapi::nw__screen::OnDisplayAdded::Create(*ConvertGfxDisplay(new_display));
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnDisplayAdded::kEventName,
      std::move(args));
  }

  // Called when |old_display| has been removed.
  void NwScreenDisplayObserver::OnDisplayRemoved(const display::Display& old_display) {
    std::unique_ptr<base::ListValue> args =
      nwapi::nw__screen::OnDisplayRemoved::Create(*ConvertGfxDisplay(old_display));
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnDisplayRemoved::kEventName,
      std::move(args));
  }

  NwScreenGetScreensFunction::NwScreenGetScreensFunction() {}

  bool NwScreenGetScreensFunction::RunNWSync(base::ListValue* response, std::string* error) {
    const std::vector<display::Display>& displays = display::Screen::GetScreen()->GetAllDisplays();

    for (size_t i=0; i<displays.size(); i++) {
      response->Append(ConvertGfxDisplay(displays[i])->ToValue());
    }

    return true;
  }

  NwScreenInitEventListenersFunction::NwScreenInitEventListenersFunction() {}

  bool NwScreenInitEventListenersFunction::RunNWSync(base::ListValue* response, std::string* error) {
    NwScreenDisplayObserver::GetInstance();
    return true;
  }

  NwDesktopCaptureMonitor* NwDesktopCaptureMonitor::GetInstance() {
    return g_desktop_capture_monitor.Pointer();
  }

  NwDesktopCaptureMonitor::NwDesktopCaptureMonitor()
      : started_(false) {
  }

  void NwDesktopCaptureMonitor::Start(bool screens, bool windows) {
    if (started_) {
      return;
    }

    started_ = true;

    webrtc::DesktopCaptureOptions options = webrtc::DesktopCaptureOptions::CreateDefault();
    options.set_disable_effects(false);

    if (screens) {
      std::unique_ptr<DesktopMediaList> screen_media_list =
        base::MakeUnique<NativeDesktopMediaList>(
          content::DesktopMediaID::TYPE_SCREEN,
          webrtc::DesktopCapturer::CreateScreenCapturer(options));
      media_list_.push_back(std::move(screen_media_list));
    }

    if (windows) {
      std::unique_ptr<DesktopMediaList> window_media_list =
        base::MakeUnique<NativeDesktopMediaList>(
          content::DesktopMediaID::TYPE_WINDOW,
          webrtc::DesktopCapturer::CreateWindowCapturer(options));
      media_list_.push_back(std::move(window_media_list));
    }

    for (auto& media_list : media_list_) {
      media_list->StartUpdating(this);
    }
  }

  void NwDesktopCaptureMonitor::Stop() {
    started_ = false;
    media_list_.clear();
  }

  bool NwDesktopCaptureMonitor::IsStarted() {
    return started_;
  }

  int NwDesktopCaptureMonitor::GetPrimaryMonitorIndex() {
  #ifdef _WIN32
    int count=0;
    for (int i = 0;; ++i) {
      DISPLAY_DEVICE device;
      device.cb = sizeof(device);
      BOOL ret = EnumDisplayDevices(NULL, i, &device, 0);
      if(!ret)
        break;
      if (device.StateFlags & DISPLAY_DEVICE_ACTIVE){
        if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE){
          return count;
        }
        count++;
      }
    }
  #endif
    return -1;
  }

void NwDesktopCaptureMonitor::OnSourceAdded(DesktopMediaList* list, int index) {
    DesktopMediaList::Source src = list->GetSource(index);

    std::string type;
    switch(src.id.type) {
    case content::DesktopMediaID::TYPE_WINDOW:
      type = "window";
      break;
    case content::DesktopMediaID::TYPE_SCREEN:
      type = "screen";
      break;
    case content::DesktopMediaID::TYPE_NONE:
      type = "none";
      break;
    default:
      type = "unknown";
      break;
    }

    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceAdded::Create(
      src.id.ToString(),
      base::UTF16ToUTF8(src.name),
      index,
      type,
      src.id.type == content::DesktopMediaID::TYPE_SCREEN && GetPrimaryMonitorIndex() == index);

    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceAdded::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceRemoved(DesktopMediaList* list, int index) {
    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceRemoved::Create(index);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceRemoved::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceMoved(DesktopMediaList* list, int old_index, int new_index) {
    DesktopMediaList::Source src = list->GetSource(new_index);
    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceOrderChanged::Create(
      src.id.ToString(),
      new_index,
      old_index);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceOrderChanged::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceNameChanged(DesktopMediaList* list, int index) {
    DesktopMediaList::Source src = list->GetSource(index);
    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceNameChanged::Create(
      src.id.ToString(),
      base::UTF16ToUTF8(src.name));
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceNameChanged::kEventName,
      std::move(args));
  }

void NwDesktopCaptureMonitor::OnSourceThumbnailChanged(DesktopMediaList* list, int index) {
    std::string base64;

    DesktopMediaList::Source src = list->GetSource(index);
    SkBitmap bitmap = src.thumbnail.GetRepresentation(1).sk_bitmap();
    std::vector<unsigned char> data;
    bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data);
    if (success){
      base::StringPiece raw_str(reinterpret_cast<const char*>(&data[0]), data.size());
      base::Base64Encode(raw_str, &base64);
    }

    std::unique_ptr<base::ListValue> args = nwapi::nw__screen::OnSourceThumbnailChanged::Create(
      src.id.ToString(),
      base64);
    DispatchEvent(
      events::HistogramValue::UNKNOWN,
      nwapi::nw__screen::OnSourceThumbnailChanged::kEventName,
      std::move(args));
  }

  NwScreenStartMonitorFunction::NwScreenStartMonitorFunction() {}

  bool NwScreenStartMonitorFunction::RunNWSync(base::ListValue* response, std::string* error) {
    bool screens, windows;
    EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &screens));
    EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &windows));
    NwDesktopCaptureMonitor::GetInstance()->Start(screens, windows);
    return true;
  }

  NwScreenStopMonitorFunction::NwScreenStopMonitorFunction() {}

  bool NwScreenStopMonitorFunction::RunNWSync(base::ListValue* response, std::string* error) {
    NwDesktopCaptureMonitor::GetInstance()->Stop();
    return true;
  }

  NwScreenIsMonitorStartedFunction::NwScreenIsMonitorStartedFunction() {}

  bool NwScreenIsMonitorStartedFunction::RunNWSync(base::ListValue* response, std::string* error) {
    response->AppendBoolean(NwDesktopCaptureMonitor::GetInstance()->IsStarted());
    return true;
  }

  NwScreenRegisterStreamFunction::NwScreenRegisterStreamFunction() {}

  bool NwScreenRegisterStreamFunction::RunNWSync(base::ListValue* response, std::string* error) {
    std::string id;
    EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id));

    // following code is modified from `DesktopCaptureChooseDesktopMediaFunctionBase::OnPickerDialogResults`
    // in chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc

    content::DesktopMediaID source = content::DesktopMediaID::Parse(id);
    content::WebContents* web_contents = GetSenderWebContents();
    if (!source.is_null() && web_contents) {
      std::string result;
      source.audio_share = true;
      DesktopStreamsRegistry* registry =
        MediaCaptureDevicesDispatcher::GetInstance()->
        GetDesktopStreamsRegistry();
      // TODO(miu): Once render_frame_host() is being set, we should register the
      // exact RenderFrame requesting the stream, not the main RenderFrame.  With
      // that change, also update
      // MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest().
      // http://crbug.com/304341
      content::RenderFrameHost* const main_frame = web_contents->GetMainFrame();
      result = registry->RegisterStream(main_frame->GetProcess()->GetID(),
                                        main_frame->GetRoutingID(),
                                        web_contents->GetURL().GetOrigin(),
                                        source,
                                        extension()->name());
      response->AppendString(result);
    }
    return true;
  }

} // extensions
<|endoftext|>


<commit_before>/*****************************************************************************
 * qt4.hpp : QT4 interface
 ****************************************************************************
 * Copyright (C) 2006-2009 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          Jean-Baptiste Kempf <jb@videolan.org>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef QVLC_H_
#define QVLC_H_

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>    /* VLC_COMMON_MEMBERS for vlc_interface.h */
#include <vlc_interface.h> /* intf_thread_t */
#include <vlc_playlist.h>  /* playlist_t */

#include <QString>

#if ( QT_VERSION < 0x040400 )
# error Update your Qt version to at least 4.4.0
#endif
#if QT_VERSION == 0x040500
# error Please update Qt version to 4.5.1. 4.5.0 is too buggy
#endif

#define HAS_QT45 ( QT_VERSION >= 0x040500 )

enum {
    QT_NORMAL_MODE = 0,
    QT_ALWAYS_VIDEO_MODE,
    QT_MINIMAL_MODE
};

enum {
    DialogEventType = 0,
    IMEventType     = 100,
    PLEventType     = 200,
    MsgEventType    = 300,
};

class QVLCApp;
class QMenu;
class MainInterface;
class QSettings;

struct intf_sys_t
{
    vlc_thread_t thread;

    QVLCApp *p_app;          /* Main Qt Application */
    MainInterface *p_mi;     /* Main Interface, NULL if DialogProvider Mode */

    QSettings *mainSettings; /* Qt State settings not messing main VLC ones */

    bool b_isDialogProvider; /* Qt mode or Skins mode */

    int  i_screenHeight;     /* Detection of Small screens */

    playlist_t *p_playlist;  /* Core Playlist discussion */

    QString filepath;        /* Last path used in dialogs */

    QMenu * p_popup_menu;    /* The right click menu */
};

#define THEPL p_intf->p_sys->p_playlist
#define QPL_LOCK playlist_Lock( THEPL );
#define QPL_UNLOCK playlist_Unlock( THEPL );

#define THEDP DialogsProvider::getInstance()
#define THEMIM MainInputManager::getInstance( p_intf )
#define THEAM ActionsManager::getInstance( p_intf )

#define qfu( i ) QString::fromUtf8( i )
#define qtr( i ) QString::fromUtf8( vlc_gettext(i) )
#define qtu( i ) ((i).toUtf8().constData())

#define CONNECT( a, b, c, d ) \
        connect( a, SIGNAL( b ), c, SLOT(d) )
#define DCONNECT( a, b, c, d ) \
        connect( a, SIGNAL( b ), c, SLOT(d), Qt::DirectConnection )
#define BUTTONACT( b, a ) connect( b, SIGNAL( clicked() ), this, SLOT(a) )

#define BUTTON_SET( button, text, tooltip )  \
    button->setText( text );                 \
    button->setToolTip( tooltip );

#define BUTTON_SET_ACT( button, text, tooltip, thisslot ) \
    BUTTON_SET( button, text, tooltip );                  \
    BUTTONACT( button, thisslot );

#define BUTTON_SET_IMG( button, text, image, tooltip )    \
    BUTTON_SET( button, text, tooltip );                  \
    button->setIcon( QIcon( ":/"#image ) );

#define BUTTON_SET_ACT_I( button, text, image, tooltip, thisslot ) \
    BUTTON_SET_IMG( button, text, image, tooltip );                \
    BUTTONACT( button, thisslot );

#define VISIBLE(i) (i && i->isVisible())

#define TOGGLEV( x ) { if( x->isVisible() ) x->hide();          \
            else  x->show(); }

#define getSettings() p_intf->p_sys->mainSettings

static inline QString QVLCUserDir( vlc_userdir_t type )
{
    char *dir = config_GetUserDir( type );
    if( !dir )
        abort();
    QString res = qfu( dir );
    free( dir );
    return res;
}

#endif
<commit_msg>Qt4: disable implicit cast from QString to (const) char *<commit_after>/*****************************************************************************
 * qt4.hpp : QT4 interface
 ****************************************************************************
 * Copyright (C) 2006-2009 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          Jean-Baptiste Kempf <jb@videolan.org>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef QVLC_H_
#define QVLC_H_

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>    /* VLC_COMMON_MEMBERS for vlc_interface.h */
#include <vlc_interface.h> /* intf_thread_t */
#include <vlc_playlist.h>  /* playlist_t */

#define QT_NO_CAST_TO_ASCII
#include <QString>

#if ( QT_VERSION < 0x040400 )
# error Update your Qt version to at least 4.4.0
#endif
#if QT_VERSION == 0x040500
# error Please update Qt version to 4.5.1. 4.5.0 is too buggy
#endif

#define HAS_QT45 ( QT_VERSION >= 0x040500 )

enum {
    QT_NORMAL_MODE = 0,
    QT_ALWAYS_VIDEO_MODE,
    QT_MINIMAL_MODE
};

enum {
    DialogEventType = 0,
    IMEventType     = 100,
    PLEventType     = 200,
    MsgEventType    = 300,
};

class QVLCApp;
class QMenu;
class MainInterface;
class QSettings;

struct intf_sys_t
{
    vlc_thread_t thread;

    QVLCApp *p_app;          /* Main Qt Application */
    MainInterface *p_mi;     /* Main Interface, NULL if DialogProvider Mode */

    QSettings *mainSettings; /* Qt State settings not messing main VLC ones */

    bool b_isDialogProvider; /* Qt mode or Skins mode */

    int  i_screenHeight;     /* Detection of Small screens */

    playlist_t *p_playlist;  /* Core Playlist discussion */

    QString filepath;        /* Last path used in dialogs */

    QMenu * p_popup_menu;    /* The right click menu */
};

#define THEPL p_intf->p_sys->p_playlist
#define QPL_LOCK playlist_Lock( THEPL );
#define QPL_UNLOCK playlist_Unlock( THEPL );

#define THEDP DialogsProvider::getInstance()
#define THEMIM MainInputManager::getInstance( p_intf )
#define THEAM ActionsManager::getInstance( p_intf )

#define qfu( i ) QString::fromUtf8( i )
#define qtr( i ) QString::fromUtf8( vlc_gettext(i) )
#define qtu( i ) ((i).toUtf8().constData())

#define CONNECT( a, b, c, d ) \
        connect( a, SIGNAL( b ), c, SLOT(d) )
#define DCONNECT( a, b, c, d ) \
        connect( a, SIGNAL( b ), c, SLOT(d), Qt::DirectConnection )
#define BUTTONACT( b, a ) connect( b, SIGNAL( clicked() ), this, SLOT(a) )

#define BUTTON_SET( button, text, tooltip )  \
    button->setText( text );                 \
    button->setToolTip( tooltip );

#define BUTTON_SET_ACT( button, text, tooltip, thisslot ) \
    BUTTON_SET( button, text, tooltip );                  \
    BUTTONACT( button, thisslot );

#define BUTTON_SET_IMG( button, text, image, tooltip )    \
    BUTTON_SET( button, text, tooltip );                  \
    button->setIcon( QIcon( ":/"#image ) );

#define BUTTON_SET_ACT_I( button, text, image, tooltip, thisslot ) \
    BUTTON_SET_IMG( button, text, image, tooltip );                \
    BUTTONACT( button, thisslot );

#define VISIBLE(i) (i && i->isVisible())

#define TOGGLEV( x ) { if( x->isVisible() ) x->hide();          \
            else  x->show(); }

#define getSettings() p_intf->p_sys->mainSettings

static inline QString QVLCUserDir( vlc_userdir_t type )
{
    char *dir = config_GetUserDir( type );
    if( !dir )
        abort();
    QString res = qfu( dir );
    free( dir );
    return res;
}

#endif
<|endoftext|>


<commit_before>class RMM_ui_help { // by Rommel
	idd = 80599;
	movingEnable = 1;
	enableSimulation = 1;
	onLoad = "0 spawn help_fnc_onload;";

	class controls {
		class Background : CUI_Frame {
			y = CUI_Row_Y(0);
			h = safeH;
			w = safeW;
		};
		class Group : CUI_ControlGroup {
			y = CUI_Row_Y(0);
			w = safeW;
			h = safeH;
			class controls {
				class Page : CUI_StructText {
					idc = 1;
					text = "Error";
					x = 0;
					y = 0;
					w = safeW;
					h = safeH * 4;
				};
			};
		};
	};
};<commit_msg>- Changed spawn to call<commit_after>class RMM_ui_help { // by Rommel
	idd = 80599;
	movingEnable = 1;
	enableSimulation = 1;
	onLoad = "0 call help_fnc_onload;";

	class controls {
		class Background : CUI_Frame {
			y = CUI_Row_Y(0);
			h = safeH;
			w = safeW;
		};
		class Group : CUI_ControlGroup {
			y = CUI_Row_Y(0);
			w = safeW;
			h = safeH;
			class controls {
				class Page : CUI_StructText {
					idc = 1;
					text = "Error";
					x = 0;
					y = 0;
					w = safeW;
					h = safeH * 4;
				};
			};
		};
	};
};<|endoftext|>


<commit_before>/**
 * @file profiling.hpp
 *
 * @brief wrappers for the CUDA profiler API functions,
 * and convenience RAII classes for profiler-output-marked
 * time range and points.
 *
 */
#pragma once
#ifndef CUDA_API_WRAPPERS_PROFILING_HPP_
#define CUDA_API_WRAPPERS_PROFILING_HPP_

#include <cuda/api/types.hpp>
#include <cstdint>
#include <string>

namespace cuda {

namespace profiling {

struct color_t {
	using underlying_type = uint32_t;
	unsigned char alpha, red, green, blue;

	static constexpr color_t from_hex(underlying_type raw_argb) noexcept {
		return {
			(unsigned char) ((raw_argb >> 24) & 0xFF),
			(unsigned char) ((raw_argb >> 16) & 0xFF),
			(unsigned char) ((raw_argb >>  8) & 0xFF),
			(unsigned char) ((raw_argb >>  0) & 0xFF),
		};
	}
	operator underlying_type() const noexcept { return as_hex(); }
	underlying_type as_hex() const noexcept
	{
		return
			((underlying_type) alpha)  << 24 |
			((underlying_type) red  )  << 16 |
			((underlying_type) green)  <<  8 |
			((underlying_type) blue )  <<  0;
	}
	static constexpr color_t Black()       noexcept { return from_hex(0x00000000); }
	static constexpr color_t White()       noexcept { return from_hex(0x00FFFFFF); }
	static constexpr color_t FullRed()     noexcept { return from_hex(0x00FF0000); }
	static constexpr color_t FullGreen()   noexcept { return from_hex(0x0000FF00); }
	static constexpr color_t FullBlue()    noexcept { return from_hex(0x000000FF); }
	static constexpr color_t FullYellow()  noexcept { return from_hex(0x00FFFF00); }
	static constexpr color_t LightRed()    noexcept { return from_hex(0x00FFDDDD); }
	static constexpr color_t LightGreen()  noexcept { return from_hex(0x00DDFFDD); }
	static constexpr color_t LightBlue()   noexcept { return from_hex(0x00DDDDFF); }
	static constexpr color_t LightYellow() noexcept { return from_hex(0x00FFFFDD); }
	static constexpr color_t DarkRed()     noexcept { return from_hex(0x00880000); }
	static constexpr color_t DarkGreen()   noexcept { return from_hex(0x00008800); }
	static constexpr color_t DarkBlue()    noexcept { return from_hex(0x00000088); }
	static constexpr color_t DarkYellow()  noexcept { return from_hex(0x00888800); }
};

namespace range {
enum class Type { unspecified, kernel, pci_express_transfer	};
/**
 * The range handle is actually `nvtxRangeId_t`; but - other than this typedef,
 * we don't need to include the nVIDIA Toolkit Extensions headers at all here,
 * and can leave them within the implementation only.
 */
using handle_t = uint64_t;
} // namespace range

namespace mark {

void point (const std::string& message, color_t color);

inline void point (const std::string& message)
{
	point(message, color_t::Black());
}

range::handle_t range_start (
	const std::string&  description,
	range::Type         type,
	color_t             color);

inline range::handle_t range_start (
	const std::string&  description,
	range::Type         type)
{
	return range_start(description, type, color_t::LightRed());
}

inline range::handle_t range_start (
	const std::string&  description)
{
	return range_start(description, range::Type::unspecified);
}

void range_end (range::handle_t range);

} // namespace mark

/**
 * A RAII class whose scope of existence is reflected as a range in the profiler.
 * Use it in the scope in which you perform some interesting operation, e.g.
 * perform a synchronous I/O operation (and have it conclude of course), or
 * launch and synch several related kernels.
 */
class scoped_range_marker {
public:
	scoped_range_marker(
		const std::string& description,
		profiling::range::Type type = profiling::range::Type::unspecified);
	~scoped_range_marker();
protected:
	profiling::range::handle_t range;
};

/**
 * Start CUDA profiling for the current process
 */
void start();

/**
 * Sttop CUDA profiling for the current process
 */
void stop();

/**
 * A class to instantiate in the part of your application
 * which does any work you intend to use the CUDA profiler
 * to profile. This could well be your main() function.
 */
class scope {
public:
	scope() { start(); }
	~scope() { stop(); }
};

namespace naming {

/**
 * @brief Have the profiler refer to a thread using a specified string
 * identifier (rather than its numeric ID).
 *
 * @param[in] thread_id  A native numeric ID of the thread; on Linux systems
 * this would be a `pthread_t`, and on Windows - a DWORD (as is returned,
 * for example, by `GetCurrentThreadId()`)
 * @param[in] name The string identifier to use for the specified thread
 */
template <typename CharT>
void name_host_thread(uint32_t thread_id, const std::basic_string<CharT>& name);
#if defined(__unix__) || defined(_WIN32)
template <typename CharT>
void name_this_thread(const std::basic_string<CharT>& name);
#endif

//void name_device_stream(device::id_t  device, stream::id_t stream);

} // namespace naming

} // namespace profiling

} // namespace cuda

#endif // CUDA_API_WRAPPERS_PROFILING_HPP_
<commit_msg>Spacing and comment tweaks.<commit_after>/**
 * @file profiling.hpp
 *
 * @brief wrappers for the CUDA profiler API functions,
 * and convenience RAII classes for profiler-output-marked
 * time range and points.
 *
 */
#pragma once
#ifndef CUDA_API_WRAPPERS_PROFILING_HPP_
#define CUDA_API_WRAPPERS_PROFILING_HPP_

#include <cuda/api/types.hpp>
#include <cstdint>
#include <string>

namespace cuda {

namespace profiling {

struct color_t {
	using underlying_type = uint32_t;
	unsigned char alpha, red, green, blue;

	static constexpr color_t from_hex(underlying_type raw_argb) noexcept {
		return {
			(unsigned char) ((raw_argb >> 24) & 0xFF),
			(unsigned char) ((raw_argb >> 16) & 0xFF),
			(unsigned char) ((raw_argb >>  8) & 0xFF),
			(unsigned char) ((raw_argb >>  0) & 0xFF),
		};
	}
	operator underlying_type() const noexcept { return as_hex(); }
	underlying_type as_hex() const noexcept
	{
		return
			((underlying_type) alpha)  << 24 |
			((underlying_type) red  )  << 16 |
			((underlying_type) green)  <<  8 |
			((underlying_type) blue )  <<  0;
	}
	static constexpr color_t Black()       noexcept { return from_hex(0x00000000); }
	static constexpr color_t White()       noexcept { return from_hex(0x00FFFFFF); }
	static constexpr color_t FullRed()     noexcept { return from_hex(0x00FF0000); }
	static constexpr color_t FullGreen()   noexcept { return from_hex(0x0000FF00); }
	static constexpr color_t FullBlue()    noexcept { return from_hex(0x000000FF); }
	static constexpr color_t FullYellow()  noexcept { return from_hex(0x00FFFF00); }
	static constexpr color_t LightRed()    noexcept { return from_hex(0x00FFDDDD); }
	static constexpr color_t LightGreen()  noexcept { return from_hex(0x00DDFFDD); }
	static constexpr color_t LightBlue()   noexcept { return from_hex(0x00DDDDFF); }
	static constexpr color_t LightYellow() noexcept { return from_hex(0x00FFFFDD); }
	static constexpr color_t DarkRed()     noexcept { return from_hex(0x00880000); }
	static constexpr color_t DarkGreen()   noexcept { return from_hex(0x00008800); }
	static constexpr color_t DarkBlue()    noexcept { return from_hex(0x00000088); }
	static constexpr color_t DarkYellow()  noexcept { return from_hex(0x00888800); }
};

namespace range {

enum class Type { unspecified, kernel, pci_express_transfer	};

/**
 * The range handle is actually `nvtxRangeId_t`; but - other than this typedef,
 * we don't need to include the nVIDIA Toolkit Extensions headers at all here,
 * and can leave them within the implementation only.
 */
using handle_t = uint64_t;

} // namespace range

namespace mark {

void point (const std::string& message, color_t color);

inline void point (const std::string& message)
{
	point(message, color_t::Black());
}

range::handle_t range_start (
	const std::string&  description,
	range::Type         type,
	color_t             color);

inline range::handle_t range_start (
	const std::string&  description,
	range::Type         type)
{
	return range_start(description, type, color_t::LightRed());
}

inline range::handle_t range_start (
	const std::string&  description)
{
	return range_start(description, range::Type::unspecified);
}

void range_end (range::handle_t range);

} // namespace mark

/**
 * A RAII class whose scope of existence is reflected as a range in the profiler.
 * Use it in the scope in which you perform some interesting operation, e.g.
 * perform a synchronous I/O operation (and have it conclude of course), or
 * launch and synch several related kernels.
 */
class scoped_range_marker {
public:
	scoped_range_marker(
		const std::string& description,
		profiling::range::Type type = profiling::range::Type::unspecified);
	~scoped_range_marker();
protected:
	profiling::range::handle_t range;
};

/**
 * Start CUDA profiling for the current process
 */
void start();

/**
 * Sttop CUDA profiling for the current process
 */
void stop();

/**
 * A class to instantiate in the part of your application
 * which does any work you intend to use the CUDA profiler
 * to profile. This could well be your main() function.
 */
class scope {
public:
	scope() { start(); }
	~scope() { stop(); }
};

namespace naming {

/**
 * @brief Have the profiler refer to a thread using a specified string
 * identifier (rather than its numeric ID).
 *
 * @param[in] thread_id  A native numeric ID of the thread; on Linux systems
 * this would be a `pthread_t`, and on Windows - a DWORD (as is returned,
 * for example, by `GetCurrentThreadId()`)
 * @param[in] name The string identifier to use for the specified thread
 */
template <typename CharT>
void name_host_thread(uint32_t thread_id, const std::basic_string<CharT>& name);

#if defined(__unix__) || defined(_WIN32)
template <typename CharT>
void name_this_thread(const std::basic_string<CharT>& name);
#endif

} // namespace naming

} // namespace profiling

} // namespace cuda

#endif // CUDA_API_WRAPPERS_PROFILING_HPP_
<|endoftext|>


<commit_before>#include "mmsapt.h"
using namespace std;
using namespace Moses;

// currently broken

Mmsapt* PT;
int main(int argc, char* argv[])
{
  // string base = argv[1];
  // string L1   = argv[2];
  // string L2   = argv[3];
  // ostringstream buf;
  // buf << "Mmsapt name=PT0 output-factor=0 num-features=5 base="
  //     << base << " L1=" << L1 << " L2=" << L2;
  // string configline = buf.str();
  // PT = new Mmsapt(configline);
  // PT->Load();
  // float w[] = { 0.0582634, 0.0518865, 0.0229819, 0.00640856,  0.647506 };
  // vector<float> weights(w,w+5);
  // PT->setWeights(weights);
  // // these values are taken from a moses.ini file;
  // // is there a convenient way of accessing them from within mmsapt ???
  // string eline,fline;
  // // TokenIndex V; V.open("crp/trn/mm/de.tdx");
  // while (getline(cin,eline) && getline(cin,fline))
  //   {
  //     cout << eline << endl;
  //     cout << fline << endl;
  //     PT->align(eline,fline);
  //   }
  // delete PT;
}

<commit_msg>Work in progress.<commit_after>#include "mm/ug_bitext.h"
#include <boost/format.hpp>
using namespace std;
using namespace Moses;
using namespace ugdiss;

typedef L2R_Token<SimpleWordId> Token;
typedef mmTtrack<Token> ttrack_t;
typedef mmTSA<Token>     tsa_t;

TokenIndex V1,V2;
boost::shared_ptr<ttrack_t> T1,T2;
tsa_t I1,I2;

namespace stats
{
  using namespace Moses::bitext;
  float
  pmi(size_t j,size_t m1, size_t m2, size_t N)
  {
    float p1 = lbop(N,m1,.1);
    float p2 = lbop(N,m2,.1);
    float p12 = lbop(N,j,.1);
    return log(p12) - log(p1) - log(p2);
    // return log(j) + log(N) - log(m1) - log(m2);
  }

  float
  npmi(size_t j,size_t m1, size_t m2, size_t N)
  {

    float p1 = lbop(N,m1,.1);
    float p2 = lbop(N,m2,.1);
    float p12 = lbop(N,j,.1);
    return (log(p12) - log(p1) - log(p2)) / -log(p12);
    // return pmi(j,m1,m2,N) / (log(N) - log(j));
  }

  float
  mi(size_t j,size_t m1, size_t m2, size_t N)
  {
    float ret = 0;
    if (j)    ret += float(j)/N * pmi(j,m1,m2,N);
    if (m1>j) ret += float(m1-j)/N * pmi(m1-j,m1,N-m2,N);
    if (m2>j) ret += float(m2-j)/N * pmi(m2-j,N-m1,m2,N);
    if (N>m1+m2-j) ret += float(N-m1-m2+j)/N * pmi(N-m1-m2+j,N-m1,N-m2,N);
    return ret;
  }
}

struct SinglePhrase
{
  typedef map<uint64_t,sptr<SinglePhrase> > cache_t;
  uint64_t pid; // phrase id
  vector<ttrack::Position> occs; // occurrences
};

struct PhrasePair
{
  struct score_t;
  uint64_t p1,p2;
  ushort s1,e1,s2,e2;
  int parent;

  struct stats_t
  {
    typedef map<pair<uint64_t,uint64_t>, sptr<stats_t> > cache_t;
    size_t m1,m2,j;
    float  npmi; // normalized point-wise mutual information
    float   pmi; // point-wise mutual information
    float    mi; // mutual information
    float score;

    void
    set(vector<ttrack::Position> const& o1,
	vector<ttrack::Position> const& o2,
	size_t const N)
    {
      m1 = m2 = j = 0;
      size_t i1=0,i2=0;
      while (i1 < o1.size() && i2 < o2.size())
	{
	  if (i1 && o1[i1].sid == o1[i1-1].sid) { ++i1; continue; }
	  if (i2 && o2[i2].sid == o2[i2-1].sid) { ++i2; continue; }

	  if (o1[i1].sid == o2[i2].sid) { ++j; ++i1; ++i2; ++m1; ++m2; }
	  else if (o1[i1].sid < o2[i2].sid) { ++i1; ++m1; }
	  else { ++i2; ++m2; }
	}
      // for (++i1; i1 < o1.size(); ++i1)
      // 	if (o1[i1-1].sid != o1[i1].sid) ++m1;
      // for (++i2; i2 < o2.size(); ++i2)
      // 	if (o2[i2-1].sid != o2[i2].sid) ++m2;

      m1 = 1; m2 = 1;
      for (i1=1; i1 < o1.size(); ++i1)
       	if (o1[i1-1].sid != o1[i1].sid) ++m1;
      for (i2=1; i2 < o2.size(); ++i2)
	if (o2[i2-1].sid != o2[i2].sid) ++m2;

      this->mi = stats::mi(j,m1,m2,N);
      this->pmi = stats::pmi(j,m1,m2,N);
      this->npmi = stats::npmi(j,m1,m2,N);
      // float z = float(m1)/N * float(m2)/N;
      float hmean = 2.*j/(m1+m2);
      this->score = npmi; // hmean; // /sqrt(z);
    }
  } stats;

  PhrasePair(ushort s1_=0, ushort e1_=0, ushort s2_=0, ushort e2_=0)
    : s1(s1_), e1(e1_), s2(s2_), e2(e2_), parent(-1) { }

  bool
  operator<(PhrasePair const& other) const
  {
    return (this->stats.score == other.stats.score
	    ? (e1-s1 + e2-s2 > other.e1-other.s1 + other.e2-other.s2)
	    : (this->stats.score > other.stats.score));
  }

};

SinglePhrase::cache_t cache1,cache2;
PhrasePair::stats_t::cache_t ppcache;

struct SortByPositionInCorpus
{
  bool
  operator()(ttrack::Position const& a,
	     ttrack::Position const& b) const
  {
    return a.sid != b.sid ? a.sid < b.sid : a.offset < b.offset;
  }
};

void
getoccs(tsa_t::tree_iterator const& m,
	vector<ttrack::Position>& occs)
{
  occs.clear();
  occs.reserve(m.approxOccurrenceCount()+10);
  tsa::ArrayEntry I(m.lower_bound(-1));
  char const* stop = m.upper_bound(-1);
  do {
    m.root->readEntry(I.next,I);
    occs.push_back(I);
  } while (I.next != stop);
  sort(occs.begin(),occs.end(),SortByPositionInCorpus());
}

void
lookup_phrases(vector<id_type> const& snt,
	       TokenIndex& V, ttrack_t const& T,
	       tsa_t const& I, SinglePhrase::cache_t& cache,
	       vector<vector<sptr<SinglePhrase> > >& dest)
{
  dest.resize(snt.size());
  for (size_t i = 0; i < snt.size(); ++i)
    {
      tsa_t::tree_iterator m(&I);
      dest[i].clear();
      for (size_t k = i; k < snt.size() && m.extend(snt[k]); ++k)
	{
	  sptr<SinglePhrase>& o = cache[m.getPid()];
	  if (!o)
	    {
	      o.reset(new SinglePhrase());
	      o->pid = m.getPid();
	      getoccs(m,o->occs);
	    }
	  dest[i].push_back(o);
	}
    }
}

struct
RowIndexSorter
{
  vector<vector<float> > const& M;
  size_t const my_col;
  RowIndexSorter(vector<vector<float> > const& m, size_t const c)
    : M(m), my_col(c) { }

  template<typename T>
  bool
  operator()(T const& a, T const& b) const
  {
    return M.at(a).at(my_col) > M.at(b).at(my_col);
  }
};

struct
ColIndexSorter
{
  vector<vector<float> > const& M;
  size_t const my_row;
  ColIndexSorter(vector<vector<float> > const& m, size_t const r)
    : M(m), my_row(r) { }

  template<typename T>
  bool
  operator()(T const& a, T const& b) const
  {
    return M.at(my_row).at(a) > M[my_row].at(b);
  }

};

int main(int argc, char* argv[])
{
  string base = argv[1];
  string L1   = argv[2];
  string L2   = argv[3];

  T1.reset(new ttrack_t());
  T2.reset(new ttrack_t());

  V1.open(base + L1 + ".tdx");
  T1->open(base + L1 + ".mct");
  I1.open(base + L1 + ".sfa", T1);

  V2.open(base + L2 + ".tdx");
  T2->open(base + L2 + ".mct");
  I2.open(base + L2 + ".sfa", T2);

  tsa_t::tree_iterator m1(&I1);
  tsa_t::tree_iterator m2(&I1);
  string line1, line2;
  while (getline(cin,line1) and getline(cin,line2))
    {
      cout << line1 << "\n" << line2 << endl;
      vector<vector<sptr<SinglePhrase> > > M1,M2;
      vector<id_type> snt1,snt2;
      V1.fillIdSeq(line1,snt1);
      V2.fillIdSeq(line2,snt2);
      lookup_phrases(snt1,V1,*T1,I1,cache1,M1);
      lookup_phrases(snt2,V2,*T2,I2,cache2,M2);

      vector<PhrasePair> pp_all,pp_good;
      vector<int> a1(snt1.size(),-1);
      vector<int> a2(snt2.size(),-1);

      vector<vector<int> > z1(snt1.size(),vector<int>(snt1.size(),-1));
      vector<vector<int> > z2(snt2.size(),vector<int>(snt2.size(),-1));
      vector<vector<vector<PhrasePair> > >ppm1(M1.size()),ppm2(M2.size());
      vector<vector<float> >  M(snt1.size(), vector<float>(snt2.size(),0));
      vector<vector<size_t> > best1(snt1.size()), best2(snt2.size());
      for (size_t i1 = 0; i1 < M1.size(); ++i1)
	{
	  PhrasePair pp;
	  pp.s1 = i1;
	  ppm1[i1].resize(M1[i1].size());
	  for (size_t i2 = 0; i2 < M2.size(); ++i2)
	    {
	      pp.s2 = i2;
	      pp.stats.j = 1;
	      ppm2[i2].resize(M2[i2].size());
	      for (size_t k1 = 0; k1 < M1[i1].size(); ++k1)
		{
		  pp.e1 = i1 + k1 + 1;
		  // if (pp.stats.j == 0) break;
		  for (size_t k2 = 0; k2 < M2[i2].size(); ++k2)
		    {
		      pp.e2 = i2 + k2 + 1;
		      sptr<PhrasePair::stats_t> & s
			= ppcache[make_pair(M1[i1][k1]->pid,M2[i2][k2]->pid)];
		      if (!s)
			{
			  s.reset(new PhrasePair::stats_t());
			  s->set(M1[i1][k1]->occs,M2[i2][k2]->occs,T1->size());
			}
		      pp.stats = *s;
		      if (pp.stats.j == 0) break;
		      // ppm1[i1][k1].push_back(pp);
		      // ppm2[i2][k2].push_back(pp);
		      if (pp.stats.score > 0)
			pp_all.push_back(pp);
		    }
		}
	    }
	}
      sort(pp_all.begin(),pp_all.end());
      BOOST_FOREACH(PhrasePair const& pp,pp_all)
	{
	  if (pp.stats.npmi < 0) continue;
	  for (size_t r = pp.s1; r < pp.e1; ++r)
	    for (size_t c = pp.s2; c < pp.e2; ++c)
	      {
		// M[r][c] += log(1-pp.stats.npmi);
		M[r][c] += log(1-pp.stats.mi);
	      }
	}
      for (size_t r = 0; r < M.size(); ++r)
	for (size_t c = 0; c < M[r].size(); ++c)
	  M[r][c] = 1.-exp(M[r][c]);
      for (size_t r = 0; r < best1.size(); ++r)
	{
	  best1[r].resize(snt2.size());
	  for (size_t c = 0; c < best1[r].size(); ++c)
	    best1[r][c] = c;
	  sort(best1[r].begin(),best1[r].end(),ColIndexSorter(M,r));
	}
      for (size_t c = 0; c < best2.size(); ++c)
	{
	  best2[c].resize(snt1.size());
	  for (size_t r = 0; r < best2[c].size(); ++r)
	    best2[c][r] = r;
	  sort(best2[c].begin(),best2[c].end(),RowIndexSorter(M,c));
	}
      for (size_t r = 0; r < best1.size(); ++r)
	{
	  cout << V1[snt1[r]] << ":";
	  for (size_t i = 0; i < min(3UL,M[r].size()); ++i)
	    {
	      size_t k = best1[r][i];
	      // if (M[r][k] >= M[best2[k][min(2UL,M.size())]][k])
	      cout << " " << k << ":" << V2[snt2[k]] << " " << M[r][k];
	    }
	  cout << endl;
	}

#if 0
      for (size_t k = 1; k < pp_all.size(); ++k)
	for (size_t i = k; i--;)
	  if (pp_all[i].s1 >= pp_all[k].s1 &&
	      pp_all[i].e1 <= pp_all[k].e1 &&
	      pp_all[i].s2 >= pp_all[k].s2 &&
	      pp_all[i].e2 <= pp_all[k].e2)
	    pp_all[i].stats.score += pp_all[k].stats.score;
      sort(pp_all.begin(),pp_all.end());
#endif

#if 1
      for (size_t p = 0; p < pp_all.size(); ++p)
	{
	  PhrasePair const& x = pp_all[p];
	  // if (x.stats.npmi < .7) break;
	  // if (z1[x.s1][x.e1-1] >= 0 || z2[x.s2][x.e2-1] >=0)
	  // continue;
	  z1[x.s1][x.e1-1] = p;
	  z2[x.s2][x.e2-1] = p;
	  cout << (boost::format("%.4f %.4f %.4f")
		   % x.stats.score
		   % x.stats.mi
		   % x.stats.npmi);
	  for (size_t z = x.s1; z < x.e1; ++z)
	    cout << " " << V1[snt1[z]];
	  cout << " :::";
	  for (size_t z = x.s2; z < x.e2; ++z)
	    cout << " " << V2[snt2[z]];
	  cout << " ["
	       << x.stats.m1 << "/" << x.stats.j << "/" << x.stats.m2
	       << "]" << endl;
	}
#endif
      // sort(pp_all.begin(),pp_all.end());
      // BOOST_FOREACH(PhrasePair const& pp, pp_all)
      // 	{
      // 	  while (ppm1[pp.s1].size() < pp.e1 - pp.s1)
      // 	    ppm1[pp.s1].push_back(vector<PhrasePair>());
      // 	  vector<PhrasePair>& v1 = ppm1[pp.s1][pp.e1-pp.s1-1];
      // 	  if (v1.size() && v1[0].stats.score > pp.stats.score)
      // 	    continue;
      // 	  while (ppm2[pp.s2].size() < pp.e2 - pp.s2)
      // 	    ppm2[pp.s2].push_back(vector<PhrasePair>());
      // 	  vector<PhrasePair>& v2 = ppm2[pp.s2][pp.e2-pp.s2-1];
      // 	  if (v2.size() && v2[0].stats.score > pp.stats.score)
      // 	    continue;
      // 	  v1.push_back(pp);
      // 	  v2.push_back(pp);
      // 	}

      // BOOST_FOREACH(vector<vector<PhrasePair> >& vv, ppm1)
      // 	{
      // 	  BOOST_FOREACH(vector<PhrasePair>& v, vv)
      // 	    {
      // 	      sort(v.begin(),v.end());
      // 	      if (v.size() > 1 && v[0].stats.score == v[1].stats.score)
      // 		v.clear();
      // 	    }
      // 	}
      // for (size_t i2 = 0; i2 < ppm2.size(); ++i2)
      // 	{
      // 	  for (size_t k2 = 0; k2 < ppm2[i2].size(); ++k2)
      // 	    {
      // 	      vector<PhrasePair>& v2 = ppm2[i2][k2];
      // 	      sort(v2.begin(),v2.end());
      // 	      if (v2.size() > 1 && v2[0].stats.score == v2[1].stats.score)
      // 		{
      // 		  v2.clear();
      // 		  continue;
      // 		}
      // 	      ushort i1 = v2[0].s1;
      // 	      ushort k1 = v2[0].e1 - i1 -1;

      // 	      if (ppm1[i1][k1].size() == 0 ||
      // 		  ppm1[i1][k1][0].s2 != i2 ||
      // 		  ppm1[i1][k1][0].e2 != i2 + k2 + 1)
      // 		{ v2.clear(); }
      // 	      else pp_good.push_back(ppm2[i2][k2][0]);
      // 	    }
      // 	}
      // BOOST_FOREACH(PhrasePair const& pp, pp_good)
      // 	{
      // 	  cout << pp.stats.mi << " ";
      // 	  for (size_t z = pp.s1; z < pp.e1; ++z)
      // 	    cout << V1[snt1[z]] << " ";
      // 	  cout << " ::: ";
      // 	  for (size_t z = pp.s2; z < pp.e2; ++z)
      // 	    cout << V2[snt2[z]] << " ";
      // 	  cout << pp.stats.m1 << "/" << pp.stats.j << "/" << pp.stats.m2 << endl;
      // 	}
      // // cout << string(80,'=') << endl;
      // // sort(pp_all.begin(),pp_all.end());
      // // BOOST_FOREACH(PhrasePair const& pp, pp_all)
      // // 	{
      // // 	  cout << pp.mi << " ";
      // // 	  for (size_t z = pp.s1; z < pp.e1; ++z)
      // // 	    cout << V1[snt1[z]] << " ";
      // // 	  cout << " ::: ";
      // // 	  for (size_t z = pp.s2; z < pp.e2; ++z)
      // // 	    cout << V2[snt2[z]] << " ";
      // // 	  cout << pp.m1 << "/" << pp.j << "/" << pp.m2 << endl;
      // // 	}

    }
}

<|endoftext|>


<commit_before>// @(#)root/base:$Name$:$Id$
// Author: Rene Brun   12/12/94

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <fstream.h>

#include "TROOT.h"
#include "TAttFill.h"
#include "TVirtualPad.h"
#include "TStyle.h"
#include "TVirtualX.h"

ClassImp(TAttFill)

//______________________________________________________________________________
//*-*-*-*-*-*-*-*-*-*-*-*-*Fill Area Attributes class*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ==========================
//*-*  Fill Area attributes are:
//*-*    Fill Color
//*-*    Fill Style
//*-*
//*-*  This class is used (in general by secondary inheritance)
//*-*  by many other classes (graphics, histograms).
//*-*
//*-*  The following table shows the list of default colors.
//Begin_Html
/*

*/
//End_Html
//*-*
//*-*  Conventions for fill styles:
//*-*    0 = hollow
//*-*    1001 : Solid
//*-*    2001 : hatch style
//*-*    3000+pattern_number (see below)
//*-*  The following table shows the list of pattern styles.
//Begin_Html
/*

*/
//End_Html
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

//______________________________________________________________________________
TAttFill::TAttFill()
{
//*-*-*-*-*-*-*-*-*-*-*-*-*AttFill default constructor*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ===========================
//*-*  Default fill attributes are taking from the current style
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
   if (!gStyle) return;
   fFillColor = gStyle->GetFillColor();
   fFillStyle = gStyle->GetFillStyle();
}

//______________________________________________________________________________
TAttFill::TAttFill(Color_t color, Style_t style)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*AttFill normal constructor*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ===========================
//*-*    color Fill Color
//*-*    style Fill Style
//*-*
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
   fFillColor = color;
   fFillStyle = style;
}

//______________________________________________________________________________
TAttFill::~TAttFill()
{
//*-*-*-*-*-*-*-*-*-*-*-*-*AttFill destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      =================
}

//______________________________________________________________________________
void TAttFill::Copy(TAttFill &attfill)
{
//*-*-*-*-*-*-*-*-*Copy this fill attributes to a new attfill*-*-*-*-*-*-*-*-*
//*-*              ==========================================
   attfill.fFillColor  = fFillColor;
   attfill.fFillStyle  = fFillStyle;
}

//______________________________________________________________________________
void TAttFill::Modify()
{
//*-*-*-*-*-*-*-*Change current fill area attributes if necessary*-*-*-*-*-*-*
//*-*            ================================================

   if (!gPad) return;
   if (!gPad->IsBatch()) {
      gVirtualX->SetFillColor(fFillColor);
      gVirtualX->SetFillStyle(fFillStyle);
   }

   gPad->SetAttFillPS(fFillColor,fFillStyle);
}

//______________________________________________________________________________
void TAttFill::ResetAttFill(Option_t *)
{
//*-*-*-*-*-*-*-*-*Reset this fill attributes to default values*-*-*-*-*-*-*
//*-*              ============================================
  fFillColor = 1;
  fFillStyle = 0;
}

//______________________________________________________________________________
void TAttFill::SaveFillAttributes(ofstream &out, const char *name, Int_t coldef, Int_t stydef)
{
    // Save fill attributes as C++ statement(s) on output stream out

   if (fFillColor != coldef) {
      out<<"   "<<name<<"->SetFillColor("<<fFillColor<<");"<<endl;
   }
   if (fFillStyle != stydef) {
      out<<"   "<<name<<"->SetFillStyle("<<fFillStyle<<");"<<endl;
   }
}

//______________________________________________________________________________
void TAttFill::SetFillAttributes()
{
//*-*-*-*-*-*-*-*-*Invoke the DialogCanvas Fill attributes*-*-*-*-*-*-*
//*-*              =======================================

   if (gPad) gROOT->SetSelectedPad(gPad->GetSelectedPad());

   TList *lc = (TList*)gROOT->GetListOfCanvases();
   if (!lc->FindObject("R__attfill")) {
      gROOT->ProcessLine("TAttFillCanvas *R__attfill = "
                         "new TAttFillCanvas(\"R__attfill\",\"Fill Attributes\","
                         "250,400);");
   }
   gROOT->ProcessLine(Form("R__attfill->UpdateFillAttributes(%d,%d);"
                           "R__attfill->Show();",fFillColor,fFillStyle));
}
<commit_msg>Add description for fill styles 4000->4100 (the opaque modes)<commit_after>// @(#)root/base:$Name:  $:$Id: TAttFill.cxx,v 1.1.1.1 2000/05/16 17:00:38 rdm Exp $
// Author: Rene Brun   12/12/94

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <fstream.h>

#include "TROOT.h"
#include "TAttFill.h"
#include "TVirtualPad.h"
#include "TStyle.h"
#include "TVirtualX.h"

ClassImp(TAttFill)

//______________________________________________________________________________
//*-*-*-*-*-*-*-*-*-*-*-*-*Fill Area Attributes class*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ==========================
//*-*  Fill Area attributes are:
//*-*    Fill Color
//*-*    Fill Style
//*-*
//*-*  This class is used (in general by secondary inheritance)
//*-*  by many other classes (graphics, histograms).
//*-*
//*-*  The following table shows the list of default colors.
//Begin_Html
/*

*/
//End_Html
//
//  Conventions for fill styles:
//    0    : hollow
//    1001 : Solid
//    2001 : hatch style
//    3000+pattern_number (see below)
//    4000 :the window is transparent.
//    4000 to 4100 the window is 100% transparent to 100% opaque
//
//*-*  The following table shows the list of pattern styles.
//Begin_Html
/*

*/
//End_Html
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

//______________________________________________________________________________
TAttFill::TAttFill()
{
//*-*-*-*-*-*-*-*-*-*-*-*-*AttFill default constructor*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ===========================
//*-*  Default fill attributes are taking from the current style
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
   if (!gStyle) return;
   fFillColor = gStyle->GetFillColor();
   fFillStyle = gStyle->GetFillStyle();
}

//______________________________________________________________________________
TAttFill::TAttFill(Color_t color, Style_t style)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*AttFill normal constructor*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ===========================
//*-*    color Fill Color
//*-*    style Fill Style
//*-*
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
   fFillColor = color;
   fFillStyle = style;
}

//______________________________________________________________________________
TAttFill::~TAttFill()
{
//*-*-*-*-*-*-*-*-*-*-*-*-*AttFill destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      =================
}

//______________________________________________________________________________
void TAttFill::Copy(TAttFill &attfill)
{
//*-*-*-*-*-*-*-*-*Copy this fill attributes to a new attfill*-*-*-*-*-*-*-*-*
//*-*              ==========================================
   attfill.fFillColor  = fFillColor;
   attfill.fFillStyle  = fFillStyle;
}

//______________________________________________________________________________
void TAttFill::Modify()
{
//*-*-*-*-*-*-*-*Change current fill area attributes if necessary*-*-*-*-*-*-*
//*-*            ================================================

   if (!gPad) return;
   if (!gPad->IsBatch()) {
      gVirtualX->SetFillColor(fFillColor);
      gVirtualX->SetFillStyle(fFillStyle);
   }

   gPad->SetAttFillPS(fFillColor,fFillStyle);
}

//______________________________________________________________________________
void TAttFill::ResetAttFill(Option_t *)
{
//*-*-*-*-*-*-*-*-*Reset this fill attributes to default values*-*-*-*-*-*-*
//*-*              ============================================
  fFillColor = 1;
  fFillStyle = 0;
}

//______________________________________________________________________________
void TAttFill::SaveFillAttributes(ofstream &out, const char *name, Int_t coldef, Int_t stydef)
{
    // Save fill attributes as C++ statement(s) on output stream out

   if (fFillColor != coldef) {
      out<<"   "<<name<<"->SetFillColor("<<fFillColor<<");"<<endl;
   }
   if (fFillStyle != stydef) {
      out<<"   "<<name<<"->SetFillStyle("<<fFillStyle<<");"<<endl;
   }
}

//______________________________________________________________________________
void TAttFill::SetFillAttributes()
{
//*-*-*-*-*-*-*-*-*Invoke the DialogCanvas Fill attributes*-*-*-*-*-*-*
//*-*              =======================================

   if (gPad) gROOT->SetSelectedPad(gPad->GetSelectedPad());

   TList *lc = (TList*)gROOT->GetListOfCanvases();
   if (!lc->FindObject("R__attfill")) {
      gROOT->ProcessLine("TAttFillCanvas *R__attfill = "
                         "new TAttFillCanvas(\"R__attfill\",\"Fill Attributes\","
                         "250,400);");
   }
   gROOT->ProcessLine(Form("R__attfill->UpdateFillAttributes(%d,%d);"
                           "R__attfill->Show();",fFillColor,fFillStyle));
}
<|endoftext|>