NetWrite.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:23k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit NetWrite;
  2. interface
  3. uses Windows, wmf9, SysUtils, activex, Classes;
  4. const
  5.   NETWRITE_ASYNC_EVENT : PCHAR = '{6d12fe9b-d029-4d08-b2eb-92c8cab323c7}';
  6. type
  7.   TWMFNetWrite = class(TObject, IWMReaderCallback, IWMReaderCallbackAdvanced)
  8.   public
  9.     constructor Create;
  10.     destructor  Destroy; override;
  11.     function    Configure(dwPortNum: DWORD; const pwszFile: PWideChar; nMaxClient: cardinal): HRESULT;
  12.     function    WritetoNet: HRESULT;
  13.     function    Init: HRESULT;
  14.     //Methods of IWMReaderCallback
  15.     function OnSample(dwOutputNum: DWORD; cnsSampleTime, cnsSampleDuration: int64;
  16.                dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT; stdcall;
  17.     function OnStatus(Status: TWMTSTATUS; hr: HRESULT; dwType: TWMTATTRDATATYPE;
  18.                pValue: PBYTE; pvContext: pointer): HRESULT; stdcall;
  19.     //Methhods of IWMReaderCallbackAdvanced
  20.     // Receive a sample directly from the ASF. To get this call, the user
  21.     // must register himself to receive samples for a particular stream.
  22.     function OnStreamSample(wStreamNum: WORD; cnsSampleTime, cnsSampleDuration: int64;
  23.                dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT; stdcall;
  24.     // In some cases, the user may want to get callbacks telling what the
  25.     // reader thinks the current time is. This is interesting in 2 cases:
  26.     // - If the ASF has gaps in it; say no audio for 10 seconds. This call
  27.     //   will continue to be called, while OnSample won't be called.
  28.     // - If the user is driving the clock, the reader needs to communicate
  29.     //   back to the user its time, to avoid the user overrunning the reader.
  30.     function OnTime(cnsCurrentTime: int64; pvContext: pointer): HRESULT; stdcall;
  31.     // The user can also get callbacks when stream selection occurs.
  32.     function OnStreamSelection(wStreamCount: Word; pStreamNumbers: PWord;
  33.                                pSelections: PWMTSTREAMSELECTION; pvContext: Pointer): HResult; stdcall;
  34.     // Will be called if the user got an async result from their
  35.     // call to SetOutputProps.  The next sample you receive for
  36.     // this output will have these properties.  The contents of the
  37.     // media type after calling SetOutputProps and before receiving
  38.     // an OutputPropsChanged notification are undefined.
  39.     function OnOutputPropsChanged(dwOutputNum: DWORD; pMediaType: PWMMediaType;
  40.                pvContext: pointer): HRESULT; stdcall;
  41.     // If the user has registered to allocate buffers, this is where he must
  42.     // do it.
  43.     function AllocateForStream(wStreamNum: WORD; cbBuffer: DWORD; out ppBuffer: INSSBuffer;
  44.                pvContext: pointer): HRESULT; stdcall;
  45.     function AllocateForOutput(dwOutputNum, cbBuffer: DWORD; out ppBuffer: INSSBuffer;
  46.                pvContext: pointer): HRESULT; stdcall;
  47.     function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  48.     function _AddRef: Integer; stdcall;
  49.     function _Release: Integer; stdcall;
  50.   private
  51.     function WriteHeader (const pwszName: PWideChar): HRESULT;
  52.     function WriteScript: HRESULT;
  53.   private
  54.     m_hEvent            : THANDLE;
  55.     m_hrAsync           : HRESULT;
  56.     m_qwTime            : Int64;
  57.     m_pWriterAdvanced   : IWMWriterAdvanced;
  58.     m_pReaderAdvanced   : IWMReaderAdvanced;
  59.     m_pReader           : IWMReader;
  60.     m_pWriter           : IWMWriter;
  61.     m_pNetSink          : IWMWriterNetworkSink;
  62.     m_bEOF              : bool;
  63.     m_pReaderHeaderInfo : IWMHeaderInfo;
  64.     m_pWriterHeaderInfo : IWMHeaderInfo;
  65.   public
  66.     function CloseAll: HRESULT;
  67.   end;
  68. implementation
  69.   constructor TWMFNetWrite.Create;
  70.   begin
  71.     m_pReaderHeaderInfo := nil;
  72.     m_pWriterHeaderInfo := nil;
  73.     m_pWriterAdvanced   := nil;
  74.     m_pReaderAdvanced   := nil;
  75.     m_pReader           := nil;
  76.     m_pWriter           := nil;
  77.     m_pNetSink          := nil;
  78.     m_hEvent            := 0;
  79.     m_bEOF              := false;
  80.     m_qwTime            := 0;
  81.     m_hrAsync           := S_OK;
  82.   end;
  83.   destructor TWMFNetWrite.Destroy;
  84.   begin
  85.     CloseAll;
  86.     CloseHandle(m_hEvent);
  87.     m_pWriterAdvanced := nil;
  88.     m_pWriter := nil;
  89.     m_pNetSink := nil;
  90.     m_pReaderAdvanced := nil;
  91.     m_pReader := nil;
  92.     inherited destroy;
  93.   end;
  94.   function TWMFNetWrite.Configure(dwPortNum: DWORD; const pwszFile: PWideChar; nMaxClient: cardinal): HRESULT;
  95.   var
  96.     pProfile : IWMProfile;
  97.     pStream  : IWMStreamConfig;
  98.     err, cchURL, dwStreams, i, cInputs : DWORD;
  99.     pwszURL : PWideChar;
  100.     wStreamNumber: WORD;
  101.   begin
  102.     if((dwPortNum = 0) or (pwszFile = nil)) then
  103.     begin
  104.       result := E_INVALIDARG;
  105.       exit;
  106.     end;
  107.     if ((m_pWriterAdvanced = nil) or (m_pReaderAdvanced = nil) or (m_pNetSink = nil)) then
  108.     begin
  109.       result := E_UNEXPECTED;
  110.       exit;
  111.     end;
  112.     // Create event for handling asynchronous calls
  113.     result   := S_OK;
  114.     pProfile := nil;
  115.     pStream  := nil;
  116.     m_hrAsync := S_OK;
  117.     m_hEvent := CreateEvent(nil, FALSE, FALSE, NETWRITE_ASYNC_EVENT);
  118.     if (m_hEvent = 0) then
  119.     begin
  120.       err := GetLastError;
  121.       writeln(format('Could not Create Event: (hr=$%x)',[err]));
  122.       result := err;
  123.       exit;
  124.     end;
  125.     // Configure the Net Sink
  126.     result := m_pNetSink.SetNetworkProtocol(WMT_PROTOCOL_HTTP);
  127.     if (FAILED(result)) then
  128.     begin
  129.       writeln('Could not Set Network protocol');
  130.       exit;
  131.     end;
  132.     result := m_pNetSink.Open(dwPortNum);
  133.     if (FAILED(result)) then
  134.     begin
  135.       writeln(format('Network sink failed to open port no %d',[dwPortNum]));
  136.       exit;
  137.     end; 
  138.     cchURL := 0;
  139.     result := m_pNetSink.GetHostURL(nil, cchURL);
  140.     if(FAILED(result)) then
  141.     begin
  142.       writeln('Could not get the host URL from IWMWriterNEtworkSink');
  143.       exit;
  144.     end;
  145.      
  146.     getmem(pwszURL, cchURL * sizeof(WCHAR));
  147.     if (pwszURL = nil) then
  148.     begin
  149.       result := E_OUTOFMEMORY; // Insufficient Memory
  150.       exit;
  151.     end;
  152.     result := m_pNetSink.GetHostURL(pwszURL, cchURL);
  153.     if (FAILED(result)) then
  154.     begin
  155.       writeln('Could not get the host URL from IWMWriterNEtworkSink');
  156.       FreeMem(pwszURL);
  157.       exit;
  158.     end;
  159.     writeln('Connect to '+pwszURL);
  160.  //   Sleep(1000);
  161.     FreeMem(pwszURL);
  162.     // Set the max no of clients that can connect to the port
  163.     result := m_pNetSink.SetMaximumClients(nMaxClient);
  164.     if (FAILED(result)) then
  165.     begin
  166.       writeln('Could not Set maximum clients');
  167.       exit;
  168.     end;
  169.     // Add the network sink to the Writer Advanced
  170.     result := m_pWriterAdvanced.AddSink(m_pNetSink);
  171.     if (FAILED(result)) then
  172.     begin
  173.       writeln('Could not Add Sink');
  174.       exit;
  175.     end;   
  176.     // Open the requested file
  177.     result := m_pReader.Open(pwszFile, self, nil);
  178.     if (FAILED(result)) then
  179.     begin
  180.       writeln('Could not open file');
  181.       exit;
  182.     end;
  183.     // Wait for the open to finish
  184.     WaitForSingleObject(m_hEvent, INFINITE);
  185.     if (FAILED(m_hrAsync)) then
  186.     begin
  187.       writeln(format('Open failed (hr=$%x)',[m_hrAsync]));
  188.       result := m_hrAsync;
  189.       exit;
  190.     end;
  191.     // Turn on manual stream selection, so we get all streams.
  192.     result := m_pReaderAdvanced.SetManualStreamSelection(TRUE);
  193.     if (FAILED(result)) then
  194.     begin
  195.       writeln('Failed to set manual stream selection');
  196.       exit;
  197.     end; // 
  198.     // Get the profile interface, loop thru all the
  199.     // streams and request the reader to deliver compressed samples
  200.     result := m_pReader.QueryInterface(IID_IWMProfile, pProfile);
  201.     if (FAILED(result)) then
  202.     begin
  203.       writeln('Could not Query for IWMProfile');
  204.       exit;
  205.     end;   
  206.     dwStreams := 0;
  207.     result := pProfile.GetStreamCount(dwStreams);
  208.     if (FAILED(result)) then
  209.     begin
  210.       writeln(format('GetStreamCount on IWMProfile failed (hr=$%x)', [result]));
  211.       exit;
  212.     end; 
  213.     for i := 0 to dwStreams - 1 do
  214.     begin
  215.       result := pProfile.GetStream(i, pStream);
  216.       if (FAILED(result)) then
  217.       begin
  218.         writeln(format('Could not get Stream %d of %d from IWMProfile (hr=0x%08x)',[i,dwStreams,result]));
  219.         break;
  220.       end;
  221.       wStreamNumber := 0;
  222.       //Get the stream number of the current stream
  223.       result := pStream.GetStreamNumber(wStreamNumber);
  224.       if (FAILED(result)) then
  225.       begin
  226.         writeln(format('Could not get stream number from IWMStreamConfig %d of %d (hr=$%x)',
  227. [i, dwStreams, result]));
  228.         break;
  229.       end;
  230.       pStream := nil;
  231.       //Set the stream to be recieved in compressed mode
  232.       result := m_pReaderAdvanced.SetReceiveStreamSamples(wStreamNumber, TRUE);
  233.       if (FAILED(result)) then
  234.       begin
  235.         writeln(format('Could not SetReceivedStreamSamples for stream number %d (hr=$%x)',
  236.                        [wStreamNumber, result]));
  237.         break;
  238.       end;
  239.     end;
  240.     pStream := nil;
  241.     if (FAILED(result)) then exit;
  242.     // Turn on the user clock
  243.     result := m_pReaderAdvanced.SetUserProvidedClock(TRUE);
  244.     if (FAILED(result)) then
  245.     begin
  246.       writeln(format('SetUserProvidedClock failed (hr=$%x)', [result]));
  247.       exit;
  248.     end; 
  249.     // Now set the writers properties
  250.     result := m_pWriter.SetProfile(pProfile);
  251.     if(FAILED(result)) then
  252.     begin
  253.       writeln(format('Could not set profile on IWMWriter (hr=$%x)',[result]));
  254.       exit;
  255.     end;
  256.     pProfile := nil;
  257.     cInputs := 0;
  258.     result := m_pWriter.GetInputCount(cInputs);
  259.     if(FAILED(result)) then
  260.     begin
  261.       writeln(format('Could not get input count from IWMWriter (hr=$%x)',[result]));
  262.       exit;
  263.     end;
  264.     for i := 0 to cInputs -1 do
  265.       // Set the input props to NULL to indicate that we don't need a codec
  266.       // because we are writing compressed samples to the port
  267.        m_pWriter.SetInputProps(i, nil);
  268.     // Write all the header attributes, which can be set, from the
  269.     // input file to the output port.
  270.     result := WriteHeader(g_wszWMTitle);
  271.     if(FAILED(result)) then exit;
  272.     result := WriteHeader( g_wszWMAuthor) ;
  273.     if(FAILED(result)) then exit;
  274.     result := WriteHeader( g_wszWMDescription) ;
  275.     if(FAILED(result)) then exit;
  276.     result := WriteHeader( g_wszWMRating) ;
  277.     if(FAILED(result)) then exit;
  278.     result := WriteHeader( g_wszWMCopyright) ;
  279.     if(FAILED(result)) then exit;
  280.     result := WriteHeader( g_wszWMAlbumTitle) ;
  281.     if(FAILED(result)) then exit;
  282.     result := WriteHeader( g_wszWMTrack) ;
  283.     if(FAILED(result)) then exit;
  284.     result := WriteHeader( g_wszWMPromotionURL) ;
  285.     if(FAILED(result)) then exit;
  286.     result := WriteHeader( g_wszWMAlbumCoverURL) ;
  287.     if(FAILED(result)) then exit;
  288.     result := WriteHeader( g_wszWMGenre) ;
  289.     if(FAILED(result)) then exit;
  290.     result := WriteHeader( g_wszWMYear) ;
  291.     if(FAILED(result)) then exit;
  292.     result := WriteHeader( g_wszWMGenreID) ;
  293.     if(FAILED(result)) then exit;
  294.     result := WriteHeader( g_wszWMMCDI) ;
  295.     if(FAILED(result)) then exit;
  296.     result := WriteHeader( g_wszWMBannerImageType ) ;
  297.     if(FAILED(result)) then exit;
  298.     result := WriteHeader( g_wszWMBannerImageData ) ;
  299.     if(FAILED(result)) then exit;
  300.     result := WriteHeader( g_wszWMBannerImageURL ) ;
  301.     if(FAILED(result)) then exit;
  302.     result := WriteHeader( g_wszWMCopyrightURL ) ;
  303.     if(FAILED(result)) then exit;
  304.     //Header has been written. Lets write the script
  305.     result := WriteScript;
  306.   end;
  307.   function TWMFNetWrite.WritetoNet: HRESULT;
  308.   begin
  309.     if ((m_hEvent          = 0)   or
  310.         (m_pWriterAdvanced = nil) or
  311.         (m_pReaderAdvanced = nil) or
  312.         (m_pNetSink        = nil)) then
  313.     begin
  314.       result := E_UNEXPECTED;
  315.       exit;
  316.     end;
  317.     // Start Writing
  318.     result := m_pWriter.BeginWriting;
  319.     if (FAILED(result)) then
  320.     begin
  321.       writeln(format('BeginWriting on IWMWriter failed (hr=$%x)',[result]));
  322.       exit;
  323.     end;
  324.     result := m_pReader.Start(0, 0, 1.0, nil);
  325.     if (FAILED(result)) then
  326.     begin
  327.       writeln(format('Could not start IWMReader (hr=$%x)',[result]));
  328.       exit;
  329.     end;
  330.    // not usefull with Windowed app
  331.   { // Wait for it to finish
  332.     WaitForSingleObject(m_hEvent, INFINITE);
  333.     if (FAILED(m_hrAsync)) then
  334.     begin
  335.       result := m_hrAsync;
  336.       exit; // Net writing failed  ????? not logic for hresult
  337.     end;}
  338.   end;
  339.   function TWMFNetWrite.CloseAll: HRESULT;
  340.   begin
  341.     // Stop stuff
  342.     if assigned(m_pReader) then
  343.     begin
  344.       result := m_pReader.Stop;
  345.       if (FAILED(result)) then
  346.       begin
  347.         writeln(format('Could not Stop IWMReader (hr=$%x)',[result]));
  348.         exit;
  349.       end; // Could not Stop IWMReader
  350.     end;
  351.     if assigned(m_pWriter) then
  352.     begin
  353.       result := m_pWriter.Flush;
  354.       if (FAILED(result)) then
  355.       begin
  356.         writeln(format('Could not Flush on IWMWriter (hr=$%x)',[result]));
  357.         exit;
  358.       end;
  359.       result := m_pWriter.EndWriting;
  360.       if (FAILED(result)) then
  361.       begin
  362.         writeln(format('Could not EndWriting on IWMWriter (hr=$%x)',[result]));
  363.         exit;
  364.       end;
  365.     end;
  366.     if assigned(m_pReader) then
  367.     begin
  368.       result := m_pReader.Close;
  369.       if (FAILED(result)) then
  370.       begin
  371.         writeln(format('Could not close the file (hr=$%x)',[result]));
  372.         exit;
  373.       end; 
  374.     end;
  375.     if assigned(m_pWriterAdvanced) then
  376.     begin
  377.       result := m_pWriterAdvanced.RemoveSink(m_pNetSink);
  378.       if (FAILED(result)) then
  379.       begin
  380.         writeln(format('Could not remove the Network Sink (hr=$%x)',[result]));
  381.         exit;
  382.       end;
  383.     end;
  384.     if assigned(m_pNetSink) then
  385.     begin
  386.       result := m_pNetSink.Close;
  387.       if (FAILED(result)) then
  388.       begin
  389.         writeln(format('Could not close on IWMWriterNetworkSink (hr=$%x)',[result]));
  390.         exit;
  391.       end;
  392.     end;
  393.     result := s_ok;
  394.     //Wait for sometime till all the data gets read from the port
  395.     //Sleep(20000);
  396.   end;
  397.   function TWMFNetWrite.Init: HRESULT;
  398.   begin
  399.     // Create the reader, writer and network sink.
  400.     result := WMCreateReader( nil, 0, m_pReader);
  401.     if (FAILED(result)) then
  402.     begin
  403.       writeln(format('Could not create reader (hr=$%x)',[result]));
  404.       exit;
  405.     end; 
  406.     result := m_pReader.QueryInterface(IID_IWMReaderAdvanced, m_pReaderAdvanced);
  407.     if (FAILED(result)) then
  408.     begin
  409.       writeln(format('Could not QI for IWMReaderAdvanced (hr=$%x)',[result]));
  410.       exit;
  411.     end;
  412.     result := WMCreateWriter(nil, m_pWriter);
  413.     if (FAILED(result)) then
  414.     begin
  415.       writeln(format('Could not create Writer (hr=$%x)',[result]));
  416.       exit;
  417.     end;
  418.     result := m_pWriter.QueryInterface(IID_IWMWriterAdvanced, m_pWriterAdvanced);
  419.     if (FAILED(result)) then
  420.     begin
  421.       writeln(format('Could not QI for IWMWriterAdvanced (hr=$%x)',[result]));
  422.       exit;
  423.     end;  
  424.     result := WMCreateWriterNetworkSink(m_pNetSink);
  425.     if (FAILED(result)) then
  426.     begin
  427.       writeln(format('Could not create Writer Network Sink (hr=$%x)',[result]));
  428.       exit;
  429.     end; 
  430.     result := m_pReader.QueryInterface(IID_IWMHeaderInfo, m_pReaderHeaderInfo);
  431.     if (FAILED(result)) then
  432.     begin
  433.       writeln(format('Could not QI for IWMHeaderInfo (hr=$%x)',[result]));
  434.       exit;
  435.     end;
  436.     result := m_pWriter.QueryInterface(IID_IWMHeaderInfo, m_pWriterHeaderInfo);
  437.     if (FAILED(result)) then
  438.     begin
  439.       writeln(format('Could not QI for IWMHeaderInfo (hr=$%x)',[result]));
  440.       exit;
  441.     end; 
  442.   end;
  443.   function TWMFNetWrite.OnSample(dwOutputNum: DWORD; cnsSampleTime, cnsSampleDuration: int64;
  444.              dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT;
  445.   begin
  446.     if (m_hEvent <> 0) then
  447.     begin
  448.       //The samples are expected in OnStreamSample
  449.       writeln('Error: Received a decompressed sample from the reader');
  450.       m_hrAsync := E_UNEXPECTED;
  451.       SetEvent(m_hEvent);
  452.     end;
  453.     result := S_OK;
  454.   end;
  455.   function TWMFNetWrite.OnStatus(Status: TWMTSTATUS; hr: HRESULT; dwType: TWMTATTRDATATYPE;
  456.              pValue: PBYTE; pvContext: pointer): HRESULT;
  457.   begin
  458.     case Status of
  459.       WMT_OPENED:
  460.         begin
  461.           m_hrAsync := hr;
  462.           SetEvent(m_hEvent);
  463.         end;
  464.       WMT_END_OF_FILE:
  465.         begin
  466.           m_bEOF := true;
  467.           writeln('EndOfStream detected in reader');
  468.           m_hrAsync := hr;
  469.           SetEvent(m_hEvent);
  470.         end;
  471.       WMT_STARTED:
  472.         begin
  473.           //Ask for the specific duration of the stream to be delivered
  474.           m_qwTime := 0;
  475.           m_qwTime := m_qwTime + (1000 * 10000);
  476.           hr := m_pReaderAdvanced.DeliverTime(m_qwTime);
  477.           assert(SUCCEEDED(hr));
  478.         end;
  479.       end;
  480.       result :=  S_OK;
  481.   end;
  482.   function TWMFNetWrite.OnStreamSample(wStreamNum: WORD; cnsSampleTime, cnsSampleDuration: int64;
  483.                dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT;
  484.   begin
  485.      writeln(format('StreamSample: num=%d, time=%d, duration=%d, flags=%d',
  486.                      [wStreamNum, cnsSampleTime, cnsSampleDuration, dwFlags]));
  487.     //We've got a sample. Lets write it
  488.     m_pWriterAdvanced.WriteStreamSample( wStreamNum, cnsSampleTime, 0, cnsSampleDuration, dwFlags, pSample);
  489.     result := S_OK;
  490.   end;
  491.   function TWMFNetWrite.OnTime(cnsCurrentTime: int64; pvContext: pointer): HRESULT;
  492.   begin
  493.     //Keep asking for the specific duration of the stream till EOF
  494.     if( not m_bEOF) then
  495.     begin
  496.       m_qwTime := m_qwTime + 10000000;
  497.       m_pReaderAdvanced.DeliverTime(m_qwTime);
  498.     end;
  499.     result := S_OK;
  500.   end;
  501.   function TWMFNetWrite.OnStreamSelection( wStreamCount: Word; pStreamNumbers: PWORD;
  502.                pSelections: PWMTSTREAMSELECTION; pvContext: pointer): HRESULT;
  503.   begin
  504.     result := S_OK;
  505.   end;
  506.   function TWMFNetWrite.OnOutputPropsChanged(dwOutputNum: DWORD; pMediaType: PWMMEDIATYPE;
  507.                pvContext: pointer): HRESULT;
  508.   begin
  509.     result := S_OK;
  510.   end;
  511.   function TWMFNetWrite.AllocateForStream(wStreamNum: WORD; cbBuffer: DWORD; out ppBuffer: INSSBuffer;
  512.              pvContext: pointer): HRESULT;
  513.   begin
  514.     result := E_NOTIMPL;
  515.   end;
  516.   function TWMFNetWrite.AllocateForOutput(dwOutputNum, cbBuffer: DWORD; out ppBuffer: INSSBuffer;
  517.              pvContext: pointer): HRESULT;
  518.   begin
  519.     result := E_NOTIMPL;
  520.   end;
  521.   function TWMFNetWrite.WriteHeader (const pwszName: PWideChar): HRESULT;
  522.   var
  523.     nstreamNum : WORD;
  524.     cbLength   : WORD;
  525.     _type      : TWMTAttrDataType;
  526.     hr         : HRESULT;
  527.     pValue     : PBYTE;
  528.   begin
  529.     nstreamNum := 0;
  530.     cbLength   := 0;
  531.     result     := S_OK;
  532.     pValue     := nil;
  533.     // Get the no of bytes to be allocated for pValue
  534.     result := m_pReaderHeaderInfo.GetAttributeByName(nstreamNum, pwszName, _type, nil, cbLength);
  535.     if (FAILED(result) and (result <> longint(ASF_E_NOTFOUND))) then
  536.     begin
  537.       writeln(format('GetAttributeByName failed for Attribute name %s (hr=$%x)',[pwszName, result]));
  538.       exit;
  539.     end;
  540.     if ((cbLength = 0) or (result = longint(ASF_E_NOTFOUND))) then
  541.     begin
  542.       result := S_OK;
  543.       exit;
  544.     end;
  545.     getmem(pValue, cbLength);
  546.     if (pValue = nil) then
  547.     begin
  548.       writeln(format('Unable to allocate memory for the Attribute name %s', [pwszName]));
  549.       result := E_OUTOFMEMORY; 
  550.       exit;
  551.     end;
  552.     //Dummy do-while loop
  553.     repeat
  554.       // Get the value
  555.       hr := m_pReaderHeaderInfo.GetAttributeByName(nstreamNum, pwszName, _type, pValue, cbLength);
  556.       if (FAILED(hr)) then
  557.       begin
  558.         writeln(format('GetAttributeByName failed for Attribute name %s (hr=$%x)', [pwszName, hr]));
  559.         break;
  560.       end; 
  561.       // Set the attribute
  562.       hr := m_pWriterHeaderInfo.SetAttribute(nstreamNum, pwszName, _type, pValue, cbLength);
  563.       if (FAILED(hr)) then
  564.       begin
  565.         writeln(format('SetAttribute failed for Attribute name %s (hr=$%x)',[pwszName, hr]));
  566.         break;
  567.       end; 
  568.     until (FALSE);
  569.     freemem(pValue);
  570.     pValue := nil;
  571.     result := hr;
  572.   end;
  573.   function TWMFNetWrite.WriteScript: HRESULT;
  574.   var
  575.     hr            : HRESULT;
  576.     pwszCommand   : PWideChar;
  577.     pwszType      : PWideChar;
  578.     cnsScriptTime : int64;
  579.     cScript       : WORD;
  580.     cchTypeLen    : WORD;
  581.     cchCommandLen : WORD;
  582.     i             : integer;
  583.   begin
  584.     hr            := S_OK;
  585.     pwszCommand   := nil;
  586.     pwszType      := nil;
  587.     cnsScriptTime := 0;
  588.     cScript       := 0;
  589.     cchTypeLen    := 0;
  590.     cchCommandLen := 0;
  591.     result := m_pReaderHeaderInfo.GetScriptCount(cScript);
  592.     if (FAILED(result)) then
  593.     begin
  594.       writeln(format('GetScriptCount failed (hr=$%x)',[result]));
  595.       exit;
  596.     end;
  597.     for i := 0 to cScript - 1 do
  598.     begin
  599.       // Get the memory reqd for this script
  600.       hr := m_pReaderHeaderInfo.GetScript(i, nil, cchTypeLen, nil, cchCommandLen, cnsScriptTime);
  601.       if (FAILED(hr)) then
  602.       begin
  603.         writeln(format('GetScript failed for Script no %d (hr=$%x)',[i, hr]));
  604.         break;
  605.       end;
  606.       getmem(pwszType, cchTypeLen * sizeof(WORD));
  607.       getmem(pwszCommand, cchCommandLen * sizeof(WORD));
  608.       if ((pwszType = nil) or (pwszCommand = nil)) then
  609.       begin
  610.         hr := E_OUTOFMEMORY;
  611.         break;
  612.       end;
  613.       // Now, get the script
  614.       hr := m_pReaderHeaderInfo.GetScript(i, pwszType, cchTypeLen, pwszCommand, cchCommandLen, cnsScriptTime);
  615.       if (FAILED(hr)) then
  616.       begin
  617.         writeln(format('GetScript failed for Script no %d (hr=$%x)', [i, hr]));
  618.         break;
  619.       end;  // GetScript failed for Script no %d
  620.       // Add the script to the writer
  621.       hr := m_pWriterHeaderInfo.AddScript(pwszType, pwszCommand, cnsScriptTime);
  622.       if (FAILED(hr)) then
  623.       begin
  624.         Writeln(format('AddScript failed for Script no %d (hr=$%x)', [i, hr]));
  625.         break;
  626.       end;
  627.       if pwszType <> nil then freemem(pwszType);
  628.       if pwszCommand <> nil then freemem(pwszCommand);
  629.       pwszType    := nil;
  630.       pwszCommand := nil;
  631.       cchTypeLen    := 0 ;
  632.       cchCommandLen := 0 ;
  633.     end;
  634.     if pwszType <> nil then freemem(pwszType);
  635.     if pwszCommand <> nil then freemem(pwszCommand);
  636.     pwszType    := nil;
  637.     pwszCommand := nil;
  638.     result := hr;
  639.   end;
  640.   function TWMFNetWrite.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  641.   begin
  642.     if IsEqualGUID(IID, IID_IWMReaderCallback) then
  643.        IWMReaderCallback(Obj) := self
  644.     else
  645.       if IsEQualGUID(IID, IID_IWMReaderCallbackAdvanced) then
  646.         IWMReaderCallbackAdvanced(obj) := self
  647.       else
  648.       begin
  649.         result := E_NOINTERFACE;
  650.         exit;
  651.       end;
  652.     result := S_OK;
  653.   end;
  654.   function TWMFNetWrite._AddRef: Integer; stdcall;
  655.   begin
  656.     result := 1;
  657.   end;
  658.   function TWMFNetWrite._Release: Integer; stdcall;
  659.   begin
  660.     result := 1;
  661.   end;
  662. end.