NetWrite.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  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. getmem(pwszURL, cchURL * sizeof(WCHAR));
  146. if (pwszURL = nil) then
  147. begin
  148. result := E_OUTOFMEMORY; // Insufficient Memory
  149. exit;
  150. end;
  151. result := m_pNetSink.GetHostURL(pwszURL, cchURL);
  152. if (FAILED(result)) then
  153. begin
  154. writeln('Could not get the host URL from IWMWriterNEtworkSink');
  155. FreeMem(pwszURL);
  156. exit;
  157. end;
  158. writeln('Connect to '+pwszURL);
  159. // Sleep(1000);
  160. FreeMem(pwszURL);
  161. // Set the max no of clients that can connect to the port
  162. result := m_pNetSink.SetMaximumClients(nMaxClient);
  163. if (FAILED(result)) then
  164. begin
  165. writeln('Could not Set maximum clients');
  166. exit;
  167. end;
  168. // Add the network sink to the Writer Advanced
  169. result := m_pWriterAdvanced.AddSink(m_pNetSink);
  170. if (FAILED(result)) then
  171. begin
  172. writeln('Could not Add Sink');
  173. exit;
  174. end;
  175. // Open the requested file
  176. result := m_pReader.Open(pwszFile, self, nil);
  177. if (FAILED(result)) then
  178. begin
  179. writeln('Could not open file');
  180. exit;
  181. end;
  182. // Wait for the open to finish
  183. WaitForSingleObject(m_hEvent, INFINITE);
  184. if (FAILED(m_hrAsync)) then
  185. begin
  186. writeln(format('Open failed (hr=$%x)',[m_hrAsync]));
  187. result := m_hrAsync;
  188. exit;
  189. end;
  190. // Turn on manual stream selection, so we get all streams.
  191. result := m_pReaderAdvanced.SetManualStreamSelection(TRUE);
  192. if (FAILED(result)) then
  193. begin
  194. writeln('Failed to set manual stream selection');
  195. exit;
  196. end; //
  197. // Get the profile interface, loop thru all the
  198. // streams and request the reader to deliver compressed samples
  199. result := m_pReader.QueryInterface(IID_IWMProfile, pProfile);
  200. if (FAILED(result)) then
  201. begin
  202. writeln('Could not Query for IWMProfile');
  203. exit;
  204. end;
  205. dwStreams := 0;
  206. result := pProfile.GetStreamCount(dwStreams);
  207. if (FAILED(result)) then
  208. begin
  209. writeln(format('GetStreamCount on IWMProfile failed (hr=$%x)', [result]));
  210. exit;
  211. end;
  212. for i := 0 to dwStreams - 1 do
  213. begin
  214. result := pProfile.GetStream(i, pStream);
  215. if (FAILED(result)) then
  216. begin
  217. writeln(format('Could not get Stream %d of %d from IWMProfile (hr=0x%08x)',[i,dwStreams,result]));
  218. break;
  219. end;
  220. wStreamNumber := 0;
  221. //Get the stream number of the current stream
  222. result := pStream.GetStreamNumber(wStreamNumber);
  223. if (FAILED(result)) then
  224. begin
  225. writeln(format('Could not get stream number from IWMStreamConfig %d of %d (hr=$%x)',
  226. [i, dwStreams, result]));
  227. break;
  228. end;
  229. pStream := nil;
  230. //Set the stream to be recieved in compressed mode
  231. result := m_pReaderAdvanced.SetReceiveStreamSamples(wStreamNumber, TRUE);
  232. if (FAILED(result)) then
  233. begin
  234. writeln(format('Could not SetReceivedStreamSamples for stream number %d (hr=$%x)',
  235. [wStreamNumber, result]));
  236. break;
  237. end;
  238. end;
  239. pStream := nil;
  240. if (FAILED(result)) then exit;
  241. // Turn on the user clock
  242. result := m_pReaderAdvanced.SetUserProvidedClock(TRUE);
  243. if (FAILED(result)) then
  244. begin
  245. writeln(format('SetUserProvidedClock failed (hr=$%x)', [result]));
  246. exit;
  247. end;
  248. // Now set the writers properties
  249. result := m_pWriter.SetProfile(pProfile);
  250. if(FAILED(result)) then
  251. begin
  252. writeln(format('Could not set profile on IWMWriter (hr=$%x)',[result]));
  253. exit;
  254. end;
  255. pProfile := nil;
  256. cInputs := 0;
  257. result := m_pWriter.GetInputCount(cInputs);
  258. if(FAILED(result)) then
  259. begin
  260. writeln(format('Could not get input count from IWMWriter (hr=$%x)',[result]));
  261. exit;
  262. end;
  263. for i := 0 to cInputs -1 do
  264. // Set the input props to NULL to indicate that we don't need a codec
  265. // because we are writing compressed samples to the port
  266. m_pWriter.SetInputProps(i, nil);
  267. // Write all the header attributes, which can be set, from the
  268. // input file to the output port.
  269. result := WriteHeader(g_wszWMTitle);
  270. if(FAILED(result)) then exit;
  271. result := WriteHeader( g_wszWMAuthor) ;
  272. if(FAILED(result)) then exit;
  273. result := WriteHeader( g_wszWMDescription) ;
  274. if(FAILED(result)) then exit;
  275. result := WriteHeader( g_wszWMRating) ;
  276. if(FAILED(result)) then exit;
  277. result := WriteHeader( g_wszWMCopyright) ;
  278. if(FAILED(result)) then exit;
  279. result := WriteHeader( g_wszWMAlbumTitle) ;
  280. if(FAILED(result)) then exit;
  281. result := WriteHeader( g_wszWMTrack) ;
  282. if(FAILED(result)) then exit;
  283. result := WriteHeader( g_wszWMPromotionURL) ;
  284. if(FAILED(result)) then exit;
  285. result := WriteHeader( g_wszWMAlbumCoverURL) ;
  286. if(FAILED(result)) then exit;
  287. result := WriteHeader( g_wszWMGenre) ;
  288. if(FAILED(result)) then exit;
  289. result := WriteHeader( g_wszWMYear) ;
  290. if(FAILED(result)) then exit;
  291. result := WriteHeader( g_wszWMGenreID) ;
  292. if(FAILED(result)) then exit;
  293. result := WriteHeader( g_wszWMMCDI) ;
  294. if(FAILED(result)) then exit;
  295. result := WriteHeader( g_wszWMBannerImageType ) ;
  296. if(FAILED(result)) then exit;
  297. result := WriteHeader( g_wszWMBannerImageData ) ;
  298. if(FAILED(result)) then exit;
  299. result := WriteHeader( g_wszWMBannerImageURL ) ;
  300. if(FAILED(result)) then exit;
  301. result := WriteHeader( g_wszWMCopyrightURL ) ;
  302. if(FAILED(result)) then exit;
  303. //Header has been written. Lets write the script
  304. result := WriteScript;
  305. end;
  306. function TWMFNetWrite.WritetoNet: HRESULT;
  307. begin
  308. if ((m_hEvent = 0) or
  309. (m_pWriterAdvanced = nil) or
  310. (m_pReaderAdvanced = nil) or
  311. (m_pNetSink = nil)) then
  312. begin
  313. result := E_UNEXPECTED;
  314. exit;
  315. end;
  316. // Start Writing
  317. result := m_pWriter.BeginWriting;
  318. if (FAILED(result)) then
  319. begin
  320. writeln(format('BeginWriting on IWMWriter failed (hr=$%x)',[result]));
  321. exit;
  322. end;
  323. result := m_pReader.Start(0, 0, 1.0, nil);
  324. if (FAILED(result)) then
  325. begin
  326. writeln(format('Could not start IWMReader (hr=$%x)',[result]));
  327. exit;
  328. end;
  329. // not usefull with Windowed app
  330. { // Wait for it to finish
  331. WaitForSingleObject(m_hEvent, INFINITE);
  332. if (FAILED(m_hrAsync)) then
  333. begin
  334. result := m_hrAsync;
  335. exit; // Net writing failed ????? not logic for hresult
  336. end;}
  337. end;
  338. function TWMFNetWrite.CloseAll: HRESULT;
  339. begin
  340. // Stop stuff
  341. if assigned(m_pReader) then
  342. begin
  343. result := m_pReader.Stop;
  344. if (FAILED(result)) then
  345. begin
  346. writeln(format('Could not Stop IWMReader (hr=$%x)',[result]));
  347. exit;
  348. end; // Could not Stop IWMReader
  349. end;
  350. if assigned(m_pWriter) then
  351. begin
  352. result := m_pWriter.Flush;
  353. if (FAILED(result)) then
  354. begin
  355. writeln(format('Could not Flush on IWMWriter (hr=$%x)',[result]));
  356. exit;
  357. end;
  358. result := m_pWriter.EndWriting;
  359. if (FAILED(result)) then
  360. begin
  361. writeln(format('Could not EndWriting on IWMWriter (hr=$%x)',[result]));
  362. exit;
  363. end;
  364. end;
  365. if assigned(m_pReader) then
  366. begin
  367. result := m_pReader.Close;
  368. if (FAILED(result)) then
  369. begin
  370. writeln(format('Could not close the file (hr=$%x)',[result]));
  371. exit;
  372. end;
  373. end;
  374. if assigned(m_pWriterAdvanced) then
  375. begin
  376. result := m_pWriterAdvanced.RemoveSink(m_pNetSink);
  377. if (FAILED(result)) then
  378. begin
  379. writeln(format('Could not remove the Network Sink (hr=$%x)',[result]));
  380. exit;
  381. end;
  382. end;
  383. if assigned(m_pNetSink) then
  384. begin
  385. result := m_pNetSink.Close;
  386. if (FAILED(result)) then
  387. begin
  388. writeln(format('Could not close on IWMWriterNetworkSink (hr=$%x)',[result]));
  389. exit;
  390. end;
  391. end;
  392. result := s_ok;
  393. //Wait for sometime till all the data gets read from the port
  394. //Sleep(20000);
  395. end;
  396. function TWMFNetWrite.Init: HRESULT;
  397. begin
  398. // Create the reader, writer and network sink.
  399. result := WMCreateReader( nil, 0, m_pReader);
  400. if (FAILED(result)) then
  401. begin
  402. writeln(format('Could not create reader (hr=$%x)',[result]));
  403. exit;
  404. end;
  405. result := m_pReader.QueryInterface(IID_IWMReaderAdvanced, m_pReaderAdvanced);
  406. if (FAILED(result)) then
  407. begin
  408. writeln(format('Could not QI for IWMReaderAdvanced (hr=$%x)',[result]));
  409. exit;
  410. end;
  411. result := WMCreateWriter(nil, m_pWriter);
  412. if (FAILED(result)) then
  413. begin
  414. writeln(format('Could not create Writer (hr=$%x)',[result]));
  415. exit;
  416. end;
  417. result := m_pWriter.QueryInterface(IID_IWMWriterAdvanced, m_pWriterAdvanced);
  418. if (FAILED(result)) then
  419. begin
  420. writeln(format('Could not QI for IWMWriterAdvanced (hr=$%x)',[result]));
  421. exit;
  422. end;
  423. result := WMCreateWriterNetworkSink(m_pNetSink);
  424. if (FAILED(result)) then
  425. begin
  426. writeln(format('Could not create Writer Network Sink (hr=$%x)',[result]));
  427. exit;
  428. end;
  429. result := m_pReader.QueryInterface(IID_IWMHeaderInfo, m_pReaderHeaderInfo);
  430. if (FAILED(result)) then
  431. begin
  432. writeln(format('Could not QI for IWMHeaderInfo (hr=$%x)',[result]));
  433. exit;
  434. end;
  435. result := m_pWriter.QueryInterface(IID_IWMHeaderInfo, m_pWriterHeaderInfo);
  436. if (FAILED(result)) then
  437. begin
  438. writeln(format('Could not QI for IWMHeaderInfo (hr=$%x)',[result]));
  439. exit;
  440. end;
  441. end;
  442. function TWMFNetWrite.OnSample(dwOutputNum: DWORD; cnsSampleTime, cnsSampleDuration: int64;
  443. dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT;
  444. begin
  445. if (m_hEvent <> 0) then
  446. begin
  447. //The samples are expected in OnStreamSample
  448. writeln('Error: Received a decompressed sample from the reader');
  449. m_hrAsync := E_UNEXPECTED;
  450. SetEvent(m_hEvent);
  451. end;
  452. result := S_OK;
  453. end;
  454. function TWMFNetWrite.OnStatus(Status: TWMTSTATUS; hr: HRESULT; dwType: TWMTATTRDATATYPE;
  455. pValue: PBYTE; pvContext: pointer): HRESULT;
  456. begin
  457. case Status of
  458. WMT_OPENED:
  459. begin
  460. m_hrAsync := hr;
  461. SetEvent(m_hEvent);
  462. end;
  463. WMT_END_OF_FILE:
  464. begin
  465. m_bEOF := true;
  466. writeln('EndOfStream detected in reader');
  467. m_hrAsync := hr;
  468. SetEvent(m_hEvent);
  469. end;
  470. WMT_STARTED:
  471. begin
  472. //Ask for the specific duration of the stream to be delivered
  473. m_qwTime := 0;
  474. m_qwTime := m_qwTime + (1000 * 10000);
  475. hr := m_pReaderAdvanced.DeliverTime(m_qwTime);
  476. assert(SUCCEEDED(hr));
  477. end;
  478. end;
  479. result := S_OK;
  480. end;
  481. function TWMFNetWrite.OnStreamSample(wStreamNum: WORD; cnsSampleTime, cnsSampleDuration: int64;
  482. dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT;
  483. begin
  484. writeln(format('StreamSample: num=%d, time=%d, duration=%d, flags=%d',
  485. [wStreamNum, cnsSampleTime, cnsSampleDuration, dwFlags]));
  486. //We've got a sample. Lets write it
  487. m_pWriterAdvanced.WriteStreamSample( wStreamNum, cnsSampleTime, 0, cnsSampleDuration, dwFlags, pSample);
  488. result := S_OK;
  489. end;
  490. function TWMFNetWrite.OnTime(cnsCurrentTime: int64; pvContext: pointer): HRESULT;
  491. begin
  492. //Keep asking for the specific duration of the stream till EOF
  493. if( not m_bEOF) then
  494. begin
  495. m_qwTime := m_qwTime + 10000000;
  496. m_pReaderAdvanced.DeliverTime(m_qwTime);
  497. end;
  498. result := S_OK;
  499. end;
  500. function TWMFNetWrite.OnStreamSelection( wStreamCount: Word; pStreamNumbers: PWORD;
  501. pSelections: PWMTSTREAMSELECTION; pvContext: pointer): HRESULT;
  502. begin
  503. result := S_OK;
  504. end;
  505. function TWMFNetWrite.OnOutputPropsChanged(dwOutputNum: DWORD; pMediaType: PWMMEDIATYPE;
  506. pvContext: pointer): HRESULT;
  507. begin
  508. result := S_OK;
  509. end;
  510. function TWMFNetWrite.AllocateForStream(wStreamNum: WORD; cbBuffer: DWORD; out ppBuffer: INSSBuffer;
  511. pvContext: pointer): HRESULT;
  512. begin
  513. result := E_NOTIMPL;
  514. end;
  515. function TWMFNetWrite.AllocateForOutput(dwOutputNum, cbBuffer: DWORD; out ppBuffer: INSSBuffer;
  516. pvContext: pointer): HRESULT;
  517. begin
  518. result := E_NOTIMPL;
  519. end;
  520. function TWMFNetWrite.WriteHeader (const pwszName: PWideChar): HRESULT;
  521. var
  522. nstreamNum : WORD;
  523. cbLength : WORD;
  524. _type : TWMTAttrDataType;
  525. hr : HRESULT;
  526. pValue : PBYTE;
  527. begin
  528. nstreamNum := 0;
  529. cbLength := 0;
  530. result := S_OK;
  531. pValue := nil;
  532. // Get the no of bytes to be allocated for pValue
  533. result := m_pReaderHeaderInfo.GetAttributeByName(nstreamNum, pwszName, _type, nil, cbLength);
  534. if (FAILED(result) and (result <> longint(ASF_E_NOTFOUND))) then
  535. begin
  536. writeln(format('GetAttributeByName failed for Attribute name %s (hr=$%x)',[pwszName, result]));
  537. exit;
  538. end;
  539. if ((cbLength = 0) or (result = longint(ASF_E_NOTFOUND))) then
  540. begin
  541. result := S_OK;
  542. exit;
  543. end;
  544. getmem(pValue, cbLength);
  545. if (pValue = nil) then
  546. begin
  547. writeln(format('Unable to allocate memory for the Attribute name %s', [pwszName]));
  548. result := E_OUTOFMEMORY;
  549. exit;
  550. end;
  551. //Dummy do-while loop
  552. repeat
  553. // Get the value
  554. hr := m_pReaderHeaderInfo.GetAttributeByName(nstreamNum, pwszName, _type, pValue, cbLength);
  555. if (FAILED(hr)) then
  556. begin
  557. writeln(format('GetAttributeByName failed for Attribute name %s (hr=$%x)', [pwszName, hr]));
  558. break;
  559. end;
  560. // Set the attribute
  561. hr := m_pWriterHeaderInfo.SetAttribute(nstreamNum, pwszName, _type, pValue, cbLength);
  562. if (FAILED(hr)) then
  563. begin
  564. writeln(format('SetAttribute failed for Attribute name %s (hr=$%x)',[pwszName, hr]));
  565. break;
  566. end;
  567. until (FALSE);
  568. freemem(pValue);
  569. pValue := nil;
  570. result := hr;
  571. end;
  572. function TWMFNetWrite.WriteScript: HRESULT;
  573. var
  574. hr : HRESULT;
  575. pwszCommand : PWideChar;
  576. pwszType : PWideChar;
  577. cnsScriptTime : int64;
  578. cScript : WORD;
  579. cchTypeLen : WORD;
  580. cchCommandLen : WORD;
  581. i : integer;
  582. begin
  583. hr := S_OK;
  584. pwszCommand := nil;
  585. pwszType := nil;
  586. cnsScriptTime := 0;
  587. cScript := 0;
  588. cchTypeLen := 0;
  589. cchCommandLen := 0;
  590. result := m_pReaderHeaderInfo.GetScriptCount(cScript);
  591. if (FAILED(result)) then
  592. begin
  593. writeln(format('GetScriptCount failed (hr=$%x)',[result]));
  594. exit;
  595. end;
  596. for i := 0 to cScript - 1 do
  597. begin
  598. // Get the memory reqd for this script
  599. hr := m_pReaderHeaderInfo.GetScript(i, nil, cchTypeLen, nil, cchCommandLen, cnsScriptTime);
  600. if (FAILED(hr)) then
  601. begin
  602. writeln(format('GetScript failed for Script no %d (hr=$%x)',[i, hr]));
  603. break;
  604. end;
  605. getmem(pwszType, cchTypeLen * sizeof(WORD));
  606. getmem(pwszCommand, cchCommandLen * sizeof(WORD));
  607. if ((pwszType = nil) or (pwszCommand = nil)) then
  608. begin
  609. hr := E_OUTOFMEMORY;
  610. break;
  611. end;
  612. // Now, get the script
  613. hr := m_pReaderHeaderInfo.GetScript(i, pwszType, cchTypeLen, pwszCommand, cchCommandLen, cnsScriptTime);
  614. if (FAILED(hr)) then
  615. begin
  616. writeln(format('GetScript failed for Script no %d (hr=$%x)', [i, hr]));
  617. break;
  618. end; // GetScript failed for Script no %d
  619. // Add the script to the writer
  620. hr := m_pWriterHeaderInfo.AddScript(pwszType, pwszCommand, cnsScriptTime);
  621. if (FAILED(hr)) then
  622. begin
  623. Writeln(format('AddScript failed for Script no %d (hr=$%x)', [i, hr]));
  624. break;
  625. end;
  626. if pwszType <> nil then freemem(pwszType);
  627. if pwszCommand <> nil then freemem(pwszCommand);
  628. pwszType := nil;
  629. pwszCommand := nil;
  630. cchTypeLen := 0 ;
  631. cchCommandLen := 0 ;
  632. end;
  633. if pwszType <> nil then freemem(pwszType);
  634. if pwszCommand <> nil then freemem(pwszCommand);
  635. pwszType := nil;
  636. pwszCommand := nil;
  637. result := hr;
  638. end;
  639. function TWMFNetWrite.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  640. begin
  641. if IsEqualGUID(IID, IID_IWMReaderCallback) then
  642. IWMReaderCallback(Obj) := self
  643. else
  644. if IsEQualGUID(IID, IID_IWMReaderCallbackAdvanced) then
  645. IWMReaderCallbackAdvanced(obj) := self
  646. else
  647. begin
  648. result := E_NOINTERFACE;
  649. exit;
  650. end;
  651. result := S_OK;
  652. end;
  653. function TWMFNetWrite._AddRef: Integer; stdcall;
  654. begin
  655. result := 1;
  656. end;
  657. function TWMFNetWrite._Release: Integer; stdcall;
  658. begin
  659. result := 1;
  660. end;
  661. end.