/// <summary> /// COM entry point for IMediaParams.FlushEnvelope /// </summary> /// <remarks> /// There should be no need to modify or override this method. See /// <see cref="IMediaObjectImpl.ParamDefine"/> and <see cref="IMediaObjectImpl.ParamCalcValueForTime"/> /// for details about how this works. /// </remarks> public int FlushEnvelope(int dwParamIndex, long refTimeStart, long refTimeEnd) { int hr; try { lock(this) { m_Log.Write("FlushEnvelope\r\n"); // If the time range makes sense if ( (refTimeStart >= 0) && (refTimeEnd >= refTimeStart) ) { if (dwParamIndex == ALLPARAMS) { hr = S_OK; // Apply the flush to all parameters for (int x=0; x < m_Params.Parms.Length && hr >= 0; x++) { MPEnvelopeSegment m = new MPEnvelopeSegment(); m.flags = MPFlags.Standard; m.iCurve = MPCaps.Jump; m.rtStart = refTimeStart; m.rtEnd = refTimeEnd; m.valStart = m_Params.Parms[x].mpdNeutralValue; m.valEnd = m_Params.Parms[x].mpdNeutralValue; hr = m_Params.Envelopes[dwParamIndex].AddSegment(m); } } else if (dwParamIndex < m_Params.Parms.Length) { // Apply the flush to the specified parameter MPEnvelopeSegment m = new MPEnvelopeSegment(); m.flags = MPFlags.Standard; m.iCurve = MPCaps.Jump; m.rtStart = refTimeStart; m.rtEnd = refTimeEnd; m.valStart = m_Params.Parms[dwParamIndex].mpdNeutralValue; m.valEnd = m_Params.Parms[dwParamIndex].mpdNeutralValue; hr = m_Params.Envelopes[dwParamIndex].AddSegment(m); } else { hr = E_INVALIDARG; } } else { hr = E_INVALIDARG; } } } catch (Exception e) { // Generic handling of all exceptions. While .NET will turn exceptions into // HRESULTS "automatically", I prefer to have some place I can set a breakpoint. hr = CatFail(e); } return hr; }
/// <summary> /// Make sure the envelope parameters are valid /// </summary> /// <param name="m">Envelope segment to check</param> /// <returns>E_INVALIDARG if parameters are incorrect, else S_OK</returns> public int ValidateEnvelopeSegment(MPEnvelopeSegment m) { int hr; // The start time cannot be MAX_TIME // The end time must be >= start time // The iCurve must be one of the recognized formats // The iCurve must be one of the supported formats // The iCurve can only be one format // The flags must be one of the recognized formats // The flags can only be one value if ( (m.rtStart == MAX_TIME) || (m.rtEnd < m.rtStart) || ((m.iCurve & (~(MPCaps.InvSquare | MPCaps.Jump | MPCaps.Linear | MPCaps.Sine | MPCaps.Square))) > 0) || ((((int)m.iCurve) & (~(m_ValidCaps))) > 0) || (IMediaObjectImpl.CountBits((int)m.iCurve) > 1) || ((m.flags & (~(MPFlags.BeginCurrentVal | MPFlags.BeginNeutralVal | MPFlags.Standard))) > 0) || (IMediaObjectImpl.CountBits((int)m.flags) > 1) ) { hr = E_INVALIDARG; } else { hr = S_OK; } return hr; }
private void UpdateSegment(int y, ref MPEnvelopeSegment m) { if ((m.flags & MPFlags.BeginNeutralVal) > 0) { m.valStart = m_DefaultValue; } else if ((m.flags & MPFlags.BeginCurrentVal) > 0) { if (y > 0) { MPEnvelopeSegment mOld = (MPEnvelopeSegment)m_Envelope[y-1]; m.valStart = mOld.valEnd; } else { m.valStart = m_DefaultValue; } } }
/// <summary> /// Add a segment to the envelope. If this segment overlaps other segments, /// the other segments are deleted or shortened, and this segment is inserted /// </summary> /// <param name="mNew">The segment to add</param> /// <returns>HRESULT</returns> public int AddSegment(MPEnvelopeSegment mNew) { int hr; int y; MPEnvelopeSegment mOld; hr = ValidateEnvelopeSegment(mNew); if (hr >= 0) { // Find the first record to modify. There is always // at least one record, and ValidateEnvelopeSegment ensures // that the start time is less than the endtime of the last // record (MAX_TIME) y = 0; do { mOld = (MPEnvelopeSegment)m_Envelope[y]; if (mNew.rtStart <= mOld.rtEnd) { break; } y++; } while (true); // Process the flags on mNew UpdateSegment(y, ref mNew); // Depending on how the new segment overlaps, adjust the // other segments and add it if (mNew.rtStart <= mOld.rtStart) { if (mNew.rtEnd >= mOld.rtEnd) { // Existing segment is completely replaced m_Envelope.RemoveAt(y); m_Envelope.Insert(y, mNew); // Subsequent records may need to be deleted/adjusted if (mNew.rtEnd > mOld.rtEnd) { DeleteRest(y+1, mNew.rtEnd); } } else { // Existing segment is shortened from the left mOld.rtStart = mNew.rtEnd + 1; m_Envelope[y] = mOld; m_Envelope.Insert(y, mNew); } } else { if (mNew.rtEnd >= mOld.rtEnd) { // Existing segment is truncated mOld.rtEnd = mNew.rtStart - 1; m_Envelope[y] = mOld; m_Envelope.Insert(y+1, mNew); if (mNew.rtEnd > mOld.rtEnd) { DeleteRest(y+2, mNew.rtEnd); } } else { // Split a segment MPEnvelopeSegment mAppend = mOld; mAppend.rtStart = mNew.rtEnd + 1; mOld.rtEnd = mNew.rtStart - 1; m_Envelope[y] = mOld; m_Envelope.Insert(y+1, mNew); m_Envelope.Insert(y+2, mAppend); } } } return hr; }
/// <summary> /// COM entry point for IMediaParams.AddEnvelope /// </summary> /// <remarks> /// There should be no need to modify or override this method. See /// <see cref="IMediaObjectImpl.ParamDefine"/> and <see cref="IMediaObjectImpl.ParamCalcValueForTime"/> /// for details about how this works. /// </remarks> public int AddEnvelope(int dwParamIndex, int cSegments, MPEnvelopeSegment[] pEnvelopeSegments) { int hr; try { lock(this) { m_Log.Write("AddEnvelope\r\n"); hr = S_OK; if (dwParamIndex == ALLPARAMS) { // Add all the envelopes to all the parameters for (int y = 0; y < m_Params.Parms.Length && hr >= 0; y++) { for (int x = 0; x < cSegments && hr >= 0; x++) { // Add the struct to the envelope hr = m_Params.Envelopes[y].AddSegment(pEnvelopeSegments[x]); } } } else if (dwParamIndex < m_Params.Parms.Length && dwParamIndex >= 0) { // Add all the envelopes to the specified parameter for (int x = 0; x < cSegments && hr >= 0; x++) { // Add the struct to the envelope hr = m_Params.Envelopes[dwParamIndex].AddSegment(pEnvelopeSegments[x]); } } else { hr = E_INVALIDARG; } } } catch (Exception e) { // Generic handling of all exceptions. While .NET will turn exceptions into // HRESULTS "automatically", I prefer to have some place I can set a breakpoint. hr = CatFail(e); } return hr; }
/// <summary> /// COM entry point for IMediaParams.SetParam /// </summary> /// <remarks> /// There should be no need to modify or override this method. See /// <see cref="IMediaObjectImpl.ParamDefine"/> and <see cref="IMediaObjectImpl.ParamCalcValueForTime"/> /// for details about how this works. /// </remarks> public int SetParam(int dwParamIndex, MPData value) { int hr; try { lock(this) { m_Log.Write("SetParam\r\n"); // Check to see if the index is in range if (dwParamIndex < m_Params.Parms.Length && dwParamIndex >= 0) { // Make an envelope that spans from current to end of stream MPEnvelopeSegment m = new MPEnvelopeSegment(); m.flags = MPFlags.Standard; m.iCurve = MPCaps.Jump; m.rtStart = 0; m.rtEnd = long.MaxValue; m.valStart = value; m.valEnd = value; // Add the struct to the envelope hr = m_Params.Envelopes[dwParamIndex].AddSegment(m); } else { hr = E_INVALIDARG; } } } catch (Exception e) { // Generic handling of all exceptions. While .NET will turn exceptions into // HRESULTS "automatically", I prefer to have some place I can set a breakpoint. hr = CatFail(e); } return hr; }
public MPEnvelopes(MPData iDefaultValue, MPCaps iValidCaps, MPType mt, MPData min, MPData max) { // Store the neutralValue, min/max value range, data type and supported curve types m_DefaultValue = iDefaultValue; m_ValidCaps = (int)iValidCaps; m_DataType = mt; m_MinVal = min; m_MaxVal = max; // Create an array to hold the segments (size = 3 was chosen arbitrarily) m_Envelope = new ArrayList(3); // Create one segment that spans all time containing the default values MPEnvelopeSegment e = new MPEnvelopeSegment(); e.flags = MPFlags.BeginNeutralVal; e.iCurve = MPCaps.Jump; e.rtStart = 0; e.rtEnd = MAX_TIME; e.valStart = m_DefaultValue; e.valEnd = m_DefaultValue; m_Envelope.Add(e); }
/// <summary> /// Updates the given <see cref="MPEnvelopeSegment"/> /// with the new value /// </summary> /// <param name="y">The new value</param> /// <param name="m">Ref. The <see cref="MPEnvelopeSegment"/> /// to be updated.</param> private void UpdateSegment(int y, ref MPEnvelopeSegment m) { if ((m.flags & MPFlags.BeginNeutralVal) > 0) { m.valStart = this.defaultValue; } else if ((m.flags & MPFlags.BeginCurrentVal) > 0) { if (y > 0) { MPEnvelopeSegment oldSegment = (MPEnvelopeSegment)this.envelope[y - 1]; m.valStart = oldSegment.valEnd; } else { m.valStart = this.defaultValue; } } }
/// <summary> /// Make sure the envelope parameters are valid /// </summary> /// <param name="m">Envelope segment to check</param> /// <returns>E_INVALIDARG if parameters are incorrect, else S_OK</returns> public int ValidateEnvelopeSegment(MPEnvelopeSegment m) { int hr; // The start time cannot be MAX_TIME // The end time must be >= start time // The iCurve must be one of the recognized formats // The iCurve must be one of the supported formats // The iCurve can only be one format // The flags must be one of the recognized formats // The flags can only be one value if (m.rtStart == MaxTime || m.rtEnd < m.rtStart || (m.iCurve & ~(MPCaps.InvSquare | MPCaps.Jump | MPCaps.Linear | MPCaps.Sine | MPCaps.Square)) > 0 || ((int)m.iCurve & ~this.validCaps) > 0 || CountBits((int)m.iCurve) > 1 || (m.flags & (~(MPFlags.BeginCurrentVal | MPFlags.BeginNeutralVal | MPFlags.Standard))) > 0 || CountBits((int)m.flags) > 1) { hr = EINVALIDARG; } else { hr = SOk; } return hr; }
/////////////////////////////////////////////////////////////////////////////// // Defining Enumerations // /////////////////////////////////////////////////////////////////////////////// #region ENUMS #endregion ENUMS /////////////////////////////////////////////////////////////////////////////// // Defining Properties // /////////////////////////////////////////////////////////////////////////////// #region PROPERTIES #endregion //PROPERTIES /////////////////////////////////////////////////////////////////////////////// // Public methods // /////////////////////////////////////////////////////////////////////////////// #region PUBLICMETHODS /// <summary> /// Add a segment to the envelope. If this segment overlaps other segments, /// the other segments are deleted or shortened, and this segment is inserted /// </summary> /// <param name="newSegment">The segment to add</param> /// <returns>The HRESULT of the method.</returns> public int AddSegment(MPEnvelopeSegment newSegment) { int hr; int y; MPEnvelopeSegment oldSegment; hr = this.ValidateEnvelopeSegment(newSegment); if (hr >= 0) { // Find the first record to modify. There is always // at least one record, and ValidateEnvelopeSegment ensures // that the start time is less than the endtime of the last // record (MAX_TIME) y = 0; do { oldSegment = (MPEnvelopeSegment)this.envelope[y]; if (newSegment.rtStart <= oldSegment.rtEnd) { break; } y++; } while (true); // Process the flags on mNew this.UpdateSegment(y, ref newSegment); // Depending on how the new segment overlaps, adjust the // other segments and add it if (newSegment.rtStart <= oldSegment.rtStart) { if (newSegment.rtEnd >= oldSegment.rtEnd) { // Existing segment is completely replaced this.envelope.RemoveAt(y); this.envelope.Insert(y, newSegment); // Subsequent records may need to be deleted/adjusted if (newSegment.rtEnd > oldSegment.rtEnd) { this.DeleteRest(y + 1, newSegment.rtEnd); } } else { // Existing segment is shortened from the left oldSegment.rtStart = newSegment.rtEnd + 1; this.envelope[y] = oldSegment; this.envelope.Insert(y, newSegment); } } else { if (newSegment.rtEnd >= oldSegment.rtEnd) { // Existing segment is truncated oldSegment.rtEnd = newSegment.rtStart - 1; this.envelope[y] = oldSegment; this.envelope.Insert(y + 1, newSegment); if (newSegment.rtEnd > oldSegment.rtEnd) { this.DeleteRest(y + 2, newSegment.rtEnd); } } else { // Split a segment MPEnvelopeSegment appendSegment = oldSegment; appendSegment.rtStart = newSegment.rtEnd + 1; oldSegment.rtEnd = newSegment.rtStart - 1; this.envelope[y] = oldSegment; this.envelope.Insert(y + 1, newSegment); this.envelope.Insert(y + 2, appendSegment); } } } return hr; }
/////////////////////////////////////////////////////////////////////////////// // Construction and Initializing methods // /////////////////////////////////////////////////////////////////////////////// #region CONSTRUCTION /// <summary> /// Initializes a new instance of the MPEnvelopes class. /// </summary> /// <param name="newDefaultValue">An <see cref="MPData"/> with the default value</param> /// <param name="newValidCaps">The valid capabilities</param> /// <param name="newMPType">The <see cref="MPType"/> of the envelope.</param> /// <param name="newMinValue">The <see cref="MPData"/> with the minimal value for the envelope.</param> /// <param name="newMaxValue">The <see cref="MPData"/> with the maximal value for the envelope.</param> public MPEnvelopes( MPData newDefaultValue, MPCaps newValidCaps, MPType newMPType, MPData newMinValue, MPData newMaxValue) { // Store the neutralValue, min/max value range, data type and supported curve types this.defaultValue = newDefaultValue; this.validCaps = (int)newValidCaps; this.dataType = newMPType; this.minValue = newMinValue; this.maxValue = newMaxValue; // Create an array to hold the segments (size = 3 was chosen arbitrarily) this.envelope = new ArrayList(3); // Create one segment that spans all time containing the default values MPEnvelopeSegment e = new MPEnvelopeSegment(); e.flags = MPFlags.BeginNeutralVal; e.iCurve = MPCaps.Jump; e.rtStart = 0; e.rtEnd = MaxTime; e.valStart = this.defaultValue; e.valEnd = this.defaultValue; this.envelope.Add(e); }
/// <summary> /// COM entry point for IMediaParams.AddEnvelope /// </summary> /// <param name="paramIndex">[in] Zero-based index of the parameter, /// or DWORD_ALLPARAMS to apply the value to every parameter.</param> /// <param name="segments">[in] Number of segments in the envelope.</param> /// <param name="envelopeSegments">[in] Pointer to an array /// of <see cref="MPEnvelopeSegment"/> structures that define the /// envelope segments. The size of the array is given in the cPoints parameter.</param> /// <returns>Returns an HRESULT value.</returns> /// <remarks> /// There should be no need to modify or override this method. See /// <see cref="IMediaObjectImpl.ParamDefine"/> and <see cref="IMediaObjectImpl.ParamCalcValueForTime"/> /// for details about how this works. /// </remarks> public int AddEnvelope(int paramIndex, int segments, MPEnvelopeSegment[] envelopeSegments) { int hr; try { lock (this) { hr = SOK; if (paramIndex == ALLPARAMS) { // Add all the envelopes to all the parameters for (int y = 0; y < this.paramsClass.Parms.Length && hr >= 0; y++) { for (int x = 0; x < segments && hr >= 0; x++) { // Add the struct to the envelope hr = this.paramsClass.Envelopes[y].AddSegment(envelopeSegments[x]); } } } else if (paramIndex < this.paramsClass.Parms.Length && paramIndex >= 0) { // Add all the envelopes to the specified parameter for (int x = 0; x < segments && hr >= 0; x++) { // Add the struct to the envelope hr = this.paramsClass.Envelopes[paramIndex].AddSegment(envelopeSegments[x]); } } else { hr = EINVALIDARG; } } } catch (Exception e) { // Generic handling of all exceptions. While .NET will turn exceptions into // HRESULTS "automatically", I prefer to have some place I can set a breakpoint. hr = this.CatFail(e); } return hr; }