source: branches/classes/c/c_audio/cwaudio.c

Last change on this file was 171, checked in by gyoung, 18 months ago

Remove static from a function so symbols for it are generated

File size: 155.0 KB
Line 
1
2/*
3 * This file was generated by the SOM Compiler.
4 * Generated using:
5 * SOM incremental update: 2.47
6 */
7
8
9/*
10 * (C) Chris Wohlgemuth 2002-2004
11 *
12 */
13/*
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; see the file COPYING. If not, write to
26 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28/*
29 * If you need another license for your project/product contact me at
30 *
31 * http://www.os2world.com/cdwriting
32 * http://www.geocities.com/SiliconValley/Sector/5785/
33 */
34
35/*
36 * This file was generated by the SOM Compiler and Emitter Framework.
37 * Generated using:
38 * SOM Emitter emitctm: 2.42
39 */
40
41#ifndef SOM_Module_cwaudio_Source
42#define SOM_Module_cwaudio_Source
43#endif
44#define CWAudio_Class_Source
45#define M_CWAudio_Class_Source
46
47#define INCL_PM
48#define INCL_DOS
49#define INCL_WINWORKPLACE
50#define INCL_MMIOOS2
51#define INCL_DOSDEVIOCTL
52#define INCL_MCIOS2
53#define INCL_ERRORS
54
55#include <os2.h>
56#include <stdio.h>
57#include "os2me.h"
58#include "cwmmdataf.h"
59#include "cwaudio.ih"
60#include "except.h"
61#include "cwaudioinc.h"
62#include "cwmp3inc.h" /* */
63#include "cwogginc.h" /* */
64#include <wpdisk.h>
65#include <wpfolder.h>
66
67#include "ea_funcs.h" /* Functions to read and write EA of file system objects */
68#include "som_wps_funcs.h"
69#include "sys_funcs.h"
70
71#if 0
72#define _PMPRINTF_
73#include "PMPRINTF.H"
74#endif
75/* Redefine function names */
76#define cwGetStringFromEA EARestoreString
77#define cwSaveStringToEA EASaveString
78
79char classDLLPath[CCHMAXPATH]={0};
80char chrHelpLibrary[CCHMAXPATH]={0};
81char chrInstallDir[CCHMAXPATH]={0};
82char chrMMAudioExt[400]={0};/* Array holding the extensions for wpclsQueryInstanceFilter() */
83char resDLLPath[CCHMAXPATH]={0};
84
85static PSZ pszAudioColTitles[NUM_AUDIO_FIELDS]= {"Playtime", "Bitrate", "Samplerate", "Channels", "Bits per sample",
86"Track Name","Artist","Album","Year","Comment","Genre"};
87
88char chrPlayTime[SIZE_TITLE]="";
89char chrBitRate[SIZE_TITLE]=""; /* New with 0.2.7 */
90char chrSampleRate[SIZE_TITLE]="";
91char chrChannels[SIZE_TITLE]="";
92char chrBPS[SIZE_TITLE]="";
93char chrName[SIZE_TITLE]="";
94char chrArtist[SIZE_TITLE]="";
95char chrAlbum[SIZE_TITLE]="";
96char chrYear[SIZE_TITLE]="";
97char chrComment[SIZE_TITLE]="";
98char chrGenre[SIZE_TITLE]="";
99
100static CLASSFIELDINFO cfiFieldInfo[NUM_AUDIO_FIELDS];
101
102extern PMMFORMATINFO g_pmmFormatInfoArray; /* in cwimage.c */
103extern LONG lNumIOProcs;/* Needed to know how many convert menus we have */
104int iRunningAudioFiles=0; /* Used to check if there's already an audio file started */
105
106extern char *genreList[];
107extern int iGenreLast;
108
109/* Global var with HAB */
110extern HAB globalHab;
111
112extern ULONG globalClassVolume;
113
114HWND globalHwndObjectPlay;
115MMAudio* globalObjectPlay;
116
117BOOL globalHaveTimidity=0;
118
119HMODULE queryModuleHandle(void);
120HMODULE queryResModuleHandle(void);
121PSZ queryModuleName(void);
122BOOL getMessage(char* text,ULONG ulID, LONG lSizeText, HMODULE hResource,HWND hwnd);
123ULONG messageBox( char* text, ULONG ulTextID , LONG lSizeText,
124 char* title, ULONG ulTitleID, LONG lSizeTitle,
125 HMODULE hResource, HWND hwnd, ULONG ulFlags);
126
127void HlpSendCommandToObject(char* chrObject, char* command);
128PSZ _queryMp3HelpLibraryName(void);
129BOOL cwMoveNotebookButtonsWarp4(HWND hwndDlg, USHORT usID, USHORT usDelta);
130BOOL cwObjectIsOnCD(WPObject * somSelf);
131BOOL cwObjectIsOnInvalidDrive(WPObject * somSelf);
132PSZ queryInstallDir(void);
133
134BOOL mmclsSetObjectType(WPFileSystem * somSelf);
135BOOL mmclsCreateTheDefaultTemplate(M_WPObject *somSelf,
136 WPObject* Folder);
137ULONG launchPMProg(PSZ pszTitle, PSZ wrapperExe, PSZ parameters, WPObject *thisPtr, ULONG ulView);
138BOOL getStringFromRexxScript(PSZ rexxFile, char* chrResult, ULONG ulSize);
139
140/* Max string length for the EA values e.g. the trackname. If this value is increased the
141 retstring length in the REXX function handler rxCallCWMMFunc() must also be increased! */
142#define MAX_EA_SIZE 256
143
144
145
146static PBYTE _readTrackInfoIntoMem(MMAudio *somSelf, char * chrEAName, PBYTE pByte, ULONG ulSize)
147{
148 if(cwGetStringFromEA(somSelf, chrEAName , pByte, ulSize))
149 {
150 PBYTE pEAValue;
151 ULONG ul, len;
152
153 len=strlen(pByte);
154 if( (pEAValue=_wpAllocMem(somSelf, len+1, &ul))!=NULLHANDLE) {
155 strncpy(pEAValue, pByte, len);
156 pEAValue[len]=0;
157 return pEAValue;
158 }
159 }
160 return NULLHANDLE;
161}
162
163void _fillEntryfieldsWithCurrentTrackNames( MMAudio *cwAudio, HWND hwnd)
164{
165 MMAudioData *somThis = MMAudioGetData(cwAudio);
166
167 if(_pszName)
168 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3NAME), _pszName);
169 else
170 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3NAME), "");
171
172 if(_pszArtist)
173 WinSetWindowText(WinWindowFromID(hwnd, IDEF_ID3ARTIST), _pszArtist);
174 else
175 WinSetWindowText(WinWindowFromID(hwnd, IDEF_ID3ARTIST), "");
176
177 if(_pszAlbum)
178 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3ALBUM), _pszAlbum);
179 else
180 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3ALBUM), "");
181
182 if(_pszComment)
183 WinSetWindowText(WinWindowFromID(hwnd, IDEF_ID3COMMENT), _pszComment);
184 else
185 WinSetWindowText(WinWindowFromID(hwnd, IDEF_ID3COMMENT), "");
186
187 if(_pszYear)
188 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3YEAR), _pszYear);
189 else
190 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3YEAR), "");
191
192 if(_pszGenre)
193 WinSetWindowText(WinWindowFromID(hwnd,IDDD_ID3GENRE), _pszGenre);
194 else
195 WinSetWindowText(WinWindowFromID(hwnd,IDDD_ID3GENRE), "");
196
197#if 0
198 if(_cwmmQueryTrackInfo(cwAudio, &chr, sizeof(tempChar), IDINFO_NAME))
199 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3NAME), chr);
200 if(_cwmmQueryTrackInfo(cwAudio, &chr, sizeof(tempChar), IDINFO_ARTIST))
201 WinSetWindowText(WinWindowFromID(hwnd, IDEF_ID3ARTIST),tempChar);
202 if(_cwmmQueryTrackInfo(cwAudio, &chr, sizeof(tempChar), IDINFO_ALBUM))
203 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3ALBUM),tempChar);
204 if(_cwmmQueryTrackInfo(cwAudio, &chr, sizeof(tempChar), IDINFO_COMMENT))
205 WinSetWindowText(WinWindowFromID(hwnd, IDEF_ID3COMMENT),tempChar);
206 if(_cwmmQueryTrackInfo(cwAudio, &chr, sizeof(tempChar), IDINFO_YEAR))
207 WinSetWindowText(WinWindowFromID(hwnd,IDEF_ID3YEAR),tempChar);
208 if(_cwmmQueryTrackInfo(cwAudio, &chr, sizeof(tempChar), IDINFO_GENRE))
209 WinSetWindowText(WinWindowFromID(hwnd,IDDD_ID3GENRE),tempChar);
210#endif
211}
212
213/****************************************************************/
214/* */
215/* */
216/* */
217/* */
218/****************************************************************/
219static PBYTE _readTrackInfoFromTextFieldIntoMem(MMAudio *somSelf, PBYTE pByte, HWND hwnd)
220{
221 ULONG ulLen;
222 PBYTE pNewText;
223 ULONG ul;
224
225 ulLen=WinQueryWindowTextLength(hwnd)+1;
226
227 /* Alloc mem for new string */
228 if( (pNewText=_wpAllocMem(somSelf, ulLen, &ul))!=NULLHANDLE) {
229 WinQueryWindowText(hwnd, ulLen, pNewText);
230 _wpFreeMem(somSelf, pByte);
231
232 return pNewText;
233 }
234
235 return pByte;
236}
237
238/****************************************************************/
239/* */
240/* WNDPROC: trackNameDlgProc() */
241/* */
242/* Window procedure handling the track information settings */
243/* page. The user may use the page to edit the information. */
244/* */
245/****************************************************************/
246static MRESULT EXPENTRY trackNameDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
247{
248 MMAudio *cwAudio;
249
250
251 switch(msg) {
252 case WM_INITDLG :
253 cwAudio=(MMAudio*)PVOIDFROMMP(mp2);
254
255 WinSetWindowULong(WinWindowFromID(hwnd,IDEF_ID3NAME),
256 QWL_USER,(ULONG)cwAudio);//Save object ptr.
257
258 if(somIsObj(cwAudio)) {
259 int a;
260 HWND hwndTemp;
261 char name[50];
262 MMAudioData *somThis = MMAudioGetData(cwAudio);
263 /* Move default buttons on Warp 4 */
264 cwMoveNotebookButtonsWarp4(hwnd, IDPB_ID3HELP, 15);
265
266 /*if(!getMessage(name, IDSTR_TRACKNAME, sizeof(name), queryResModuleHandle(), hwnd))
267 strcpy(name, "Track name");*/
268 WinSetWindowText(WinWindowFromID(hwnd,IDGB_ID3TAGS), "");
269
270 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3NAME),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)MAX_EA_SIZE-1),0);
271 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3ARTIST),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)MAX_EA_SIZE-1),0);
272 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3ALBUM),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)MAX_EA_SIZE-1),0);
273 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3COMMENT),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)MAX_EA_SIZE-1),0);
274 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3YEAR),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)MAX_EA_SIZE-1),0);
275 WinSendMsg(WinWindowFromID(hwnd,IDDD_ID3GENRE),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)MAX_EA_SIZE-1),0);
276 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3NAME),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)30),0);
277 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3ARTIST),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)30),0);
278 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3ALBUM),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)30),0);
279 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3COMMENT),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)30),0);
280 WinSendMsg(WinWindowFromID(hwnd,IDEF_ID3YEAR),EM_SETTEXTLIMIT,MPFROMSHORT((SHORT)4),0);
281 /* Fill drop downlist with knwon genres */
282 hwndTemp=WinWindowFromID(hwnd, IDDD_ID3GENRE);
283 for(a=0;a<=iGenreLast;a++)
284 WinSendMsg(hwndTemp, LM_INSERTITEM, MPFROMSHORT(LIT_SORTASCENDING),MPFROMP(genreList[a]));
285 _fillEntryfieldsWithCurrentTrackNames( cwAudio, hwnd);
286 }
287 WinSetWindowULong(WinQueryWindow(hwnd, QW_PARENT), QWL_HWNDFOCUSSAVE, hwnd);
288 return (MRESULT)TRUE;
289 /* This prevents switching the notebook page behind the open folder */
290 case WM_WINDOWPOSCHANGED:
291 {
292 MRESULT mr;
293
294 if(WinQueryFocus(HWND_DESKTOP)!=
295 WinQueryWindow(WinQueryWindow(hwnd, QW_PARENT), QW_PARENT)) {
296 mp2=MPFROMLONG(LONGFROMMP(mp2)|0x80000);/*AWP_ACTIVATE 0x00080000L*/
297 mr=WinDefDlgProc(hwnd, msg, mp1, mp2);
298 return mr;
299 }
300 break;
301 }
302 case WM_FOCUSCHANGE:
303 {
304 if(!SHORT1FROMMP(mp2)) {
305 if(HWNDFROMMP(mp1)==hwnd) {
306 MRESULT mr;
307
308 mr=WinDefDlgProc(hwnd, msg, mp1, mp2);
309 WinSendMsg(WinQueryWindow(WinQueryWindow(hwnd, QW_PARENT), QW_PARENT), WM_SETFOCUS, MPFROMHWND(hwnd),
310 (MPARAM)TRUE);
311 return mr;
312 }
313 }
314 break;
315 }
316 case WM_DESTROY:
317 /* The notebook closes and gets destroyed */
318 /* Set focus to desktop to prevent PM freeze */
319 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
320 break;
321 case WM_COMMAND:
322 cwAudio=(MMAudio*) WinQueryWindowULong(WinWindowFromID(hwnd, IDEF_ID3NAME),QWL_USER);
323 if(somIsObj(cwAudio)) {
324 switch(SHORT1FROMMP(mp1))
325 {
326 case IDPB_CANCEL:
327 _fillEntryfieldsWithCurrentTrackNames( cwAudio, hwnd);
328 break;
329 case IDPB_ID3SAVE:
330 {
331 MMAudioData *somThis = MMAudioGetData(cwAudio);
332
333 _pszName=_readTrackInfoFromTextFieldIntoMem(cwAudio, _pszName, WinWindowFromID(hwnd, IDEF_ID3NAME));
334 _pszArtist=_readTrackInfoFromTextFieldIntoMem(cwAudio, _pszArtist, WinWindowFromID(hwnd, IDEF_ID3ARTIST));
335 _pszAlbum=_readTrackInfoFromTextFieldIntoMem(cwAudio, _pszAlbum, WinWindowFromID(hwnd, IDEF_ID3ALBUM));
336 _pszComment=_readTrackInfoFromTextFieldIntoMem(cwAudio, _pszComment, WinWindowFromID(hwnd, IDEF_ID3COMMENT));
337 _pszYear=_readTrackInfoFromTextFieldIntoMem(cwAudio, _pszYear, WinWindowFromID(hwnd, IDEF_ID3YEAR));
338 _pszGenre=_readTrackInfoFromTextFieldIntoMem(cwAudio, _pszGenre, WinWindowFromID(hwnd, IDDD_ID3GENRE));
339 _wpSaveDeferred(cwAudio);
340 }
341 break;
342 default:
343 break;
344 }
345 }
346 return (MRESULT) TRUE;
347 default:
348 break;
349 }
350 return WinDefDlgProc(hwnd, msg, mp1, mp2);
351}
352
353/****************************************************************/
354/* */
355/* METHOD: cwmmAddTrackNamePage() */
356/* */
357/* Insert new settings notebook page showing track information. */
358/* The user may use this page to edit the information */
359/* */
360/****************************************************************/
361/*!*******************************************************/
362/* */
363/* @@DESC */
364/* */
365/* This instance method is called to allow the object */
366/* to add the track name page to its Settings notebook. */
367/* :p. */
368/* This page can be used to change the track information */
369/* like title, album etc. which is stored in the EAs */
370/* of the file. */
371/* */
372/* @@USAGE */
373/* */
374/* This method must only be called from within an */
375/* override of wpAddSettingsPages(). */
376/* */
377/* @@PARAM */
378/* */
379/* MMAudio *somSelf input */
380/* */
381/* Pointer to the object on which the method is being */
382/* invoked. */
383/* :p. */
384/* Points to an object of class :hp2.MMAudio:ehp2.. */
385/* */
386/* @@PARAM */
387/* */
388/* HWND hwndNotebook input */
389/* */
390/* Settings notebook handle. */
391/* */
392/* @@OVERRIDE */
393/* */
394/* This method should always be overridden in order to */
395/* remove or replace the image information page from */
396/* the object's Settings notbook. */
397/* :p. */
398/* To remove the page from the Settings notebook, the */
399/* override method should return */
400/* :hp1.SETTINGS_PAGE_REMOVED:ehp1. without calling the */
401/* the parent method. To replace the page with another */
402/* page, the override method should call the */
403/* wpInsertSettingsPAge method without calling the */
404/* parent method. */
405/* */
406/* @@RETURNS */
407/* */
408/* ULONG rc */
409/* */
410/* :parml compact tsize=15 break=none. */
411/* :pt.0:pd.Error occurred */
412/* :pt.PageId :pd.Identifier for the inserted page. */
413/* :eparml. */
414/* */
415/*!!******************************************************/
416SOM_Scope ULONG SOMLINK cwaudio_cwmmAddTrackNamePage(MMAudio* somSelf,
417 HWND hwndNotebook)
418{
419 PAGEINFO pageinfo;
420 char pageName[100];
421
422 /* MMAudioData *somThis = MMAudioGetData(somSelf);*/
423 MMAudioMethodDebug("MMAudio","cwaudio_cwmmAddTrackNamePage");
424
425 //Clear the pageinfo structure
426 memset((PCH)&pageinfo, 0, sizeof(PAGEINFO));
427 //Fill the pageinfo structure
428 pageinfo.cb = sizeof(PAGEINFO);
429 pageinfo.hwndPage = NULLHANDLE;
430 pageinfo.usPageStyleFlags = BKA_MAJOR | BKA_STATUSTEXTON;
431 pageinfo.usPageInsertFlags = BKA_FIRST;
432 //We want page numbers
433 pageinfo.usSettingsFlags = SETTINGS_PAGE_NUMBERS;
434 //The dialog procedure for this page
435 pageinfo.pfnwp = trackNameDlgProc;
436 //The resource DLL
437 pageinfo.resid = queryResModuleHandle();
438 //pageinfo.resid = queryModuleHandle();
439 //The ID of the dialog template
440 pageinfo.dlgid = IDDLG_ID3TAGS;
441 //We need a pointer to our WPS-object in the dialog procedure
442 //to call class functions
443 pageinfo.pCreateParams = somSelf;
444 //The ID of the help panel for this page
445 pageinfo.idDefaultHelpPanel = TRACKNAME_SETTINGS_PANEL;
446 //Tell the WPS the help library name
447 pageinfo.pszHelpLibraryName = _queryMp3HelpLibraryName();
448 //We have a major tab so we need a name
449 if(!getMessage(pageName, ID_TRACKNAMEPAGENAME, sizeof(pageName), queryResModuleHandle(), hwndNotebook))
450 strcpy(pageName, "~Track meta data");
451 pageinfo.pszName = pageName;
452 //Insert the page into the settings notebook
453
454 return _wpInsertSettingsPage(somSelf,hwndNotebook,&pageinfo);
455}
456
457/* Remove all trailing spaces from a string. The string MUST be terminated by 0! */
458void _removeTrailingSpaces(char * chrString)
459{
460 char *ptr;
461
462 if((ptr=strrchr(chrString, 0))==NULLHANDLE)
463 return;
464
465 if(ptr==chrString)
466 return;
467
468 while(ptr>=chrString && (*ptr==0 || *ptr==' '))
469 ptr--;
470
471 *(++ptr)=0;
472}
473
474
475/****************************************************************/
476/* */
477/* WNDPROC: waveInfoDlgProc() */
478/* */
479/* Window procedure handling the wave information settings */
480/* page. */
481/* */
482/****************************************************************/
483MRESULT EXPENTRY waveInfoDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
484{
485 MMAudio *cwAudio;
486
487 switch(msg) {
488 case WM_INITDLG :
489 cwAudio=(MMAudio*)LONGFROMMP(mp2);
490 if(somIsObj(cwAudio)) {
491 char fName[CCHMAXPATH];
492 MMAudioData *somThis = MMAudioGetData(cwAudio);
493
494 sprintf(fName,"%d",_ulChannels);
495 WinSetWindowText(WinWindowFromID(hwnd, IDST_CHANNELS),fName);
496
497 sprintf(fName,"%d",_ulSampleRate);
498 WinSetWindowText(WinWindowFromID(hwnd, IDST_SAMPLERATE),fName);
499 sprintf(fName,"%d",_ulBPS);
500 WinSetWindowText(WinWindowFromID(hwnd, IDST_BPS),fName);
501 sprintf(fName,"%d:%02d",_ulPlaySecs/60, _ulPlaySecs%60);
502 WinSetWindowText(WinWindowFromID(hwnd, IDST_PLAYTIME),fName);
503 WinSetWindowULong(WinQueryWindow(hwnd, QW_PARENT), QWL_HWNDFOCUSSAVE, hwnd);
504 }
505 return (MRESULT)TRUE;
506 /* This prevents switching the notebook page behind the open folder */
507 case WM_WINDOWPOSCHANGED:
508 {
509 MRESULT mr;
510
511 if(WinQueryFocus(HWND_DESKTOP)!=
512 WinQueryWindow(WinQueryWindow(hwnd, QW_PARENT), QW_PARENT)) {
513 mp2=MPFROMLONG(LONGFROMMP(mp2)|0x80000);/*AWP_ACTIVATE 0x00080000L*/
514 mr=WinDefDlgProc(hwnd, msg, mp1, mp2);
515 return mr;
516 }
517 break;
518 }
519 case WM_FOCUSCHANGE:
520 {
521 if(!SHORT1FROMMP(mp2)) {
522 if(HWNDFROMMP(mp1)==hwnd) {
523 MRESULT mr;
524
525 mr=WinDefDlgProc(hwnd, msg, mp1, mp2);
526 WinSendMsg(WinQueryWindow(WinQueryWindow(hwnd, QW_PARENT), QW_PARENT),
527 WM_SETFOCUS, MPFROMHWND(hwnd), (MPARAM)TRUE);
528 return mr;
529 }
530 }
531 break;
532 }
533 case WM_DESTROY:
534 /* The notebook closes and gets destroyed */
535 /* Set focus to desktop to prevent PM freeze */
536 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
537 break;
538 default:
539 break;
540 }
541 return WinDefDlgProc(hwnd, msg, mp1, mp2);
542}
543
544
545/****************************************************************/
546/* */
547/* METHOD: cwmmAddAudioInformationPage() */
548/* */
549/* Insert new settings notebook page showing audio information. */
550/* */
551/****************************************************************/
552/*!*******************************************************/
553/* */
554/* @@DESC */
555/* */
556/* This instance method is called to allow the object */
557/* to add the audio information page to its Settings */
558/* notebook. */
559/* */
560/* @@USAGE */
561/* */
562/* This method must only be called from within an */
563/* override of wpAddSettingsPages(). */
564/* */
565/* @@PARAM */
566/* */
567/* MMAudio *somSelf input */
568/* */
569/* Pointer to the object on which the method is being */
570/* invoked. */
571/* :p. */
572/* Points to an object of class :hp2.MMAudio:ehp2.. */
573/* */
574/* @@PARAM */
575/* */
576/* HWND hwndNotebook input */
577/* */
578/* Settings notebook handle. */
579/* */
580/* @@OVERRIDE */
581/* */
582/* This method should always be overridden in order to */
583/* remove or replace the image information page from */
584/* the object's Settings notbook. */
585/* :p. */
586/* To remove the page from the Settings notebook, the */
587/* override method should return */
588/* :hp1.SETTINGS_PAGE_REMOVED:ehp1. without calling the */
589/* the parent method. To replace the page with another */
590/* page, the override method should call the */
591/* wpInsertSettingsPAge method without calling the */
592/* parent method. */
593/* */
594/* @@RETURNS */
595/* */
596/* ULONG rc */
597/* */
598/* :parml compact tsize=15 break=none. */
599/* :pt.0:pd.Error occurred */
600/* :pt.PageId :pd.Identifier for the inserted page. */
601/* :eparml. */
602/* */
603/*!!******************************************************/
604SOM_Scope ULONG SOMLINK cwaudio_cwmmAddAudioInformationPage(MMAudio* somSelf,
605 HWND hwndNotebook)
606{
607 PAGEINFO pageinfo;
608 char pageName[100];
609
610 MMAudioData *somThis = MMAudioGetData(somSelf);
611 MMAudioMethodDebug("MMAudio","cwaudio_cwmmAddWaveInformationPage");
612
613 if(_ulFileSize!=_wpQueryFileSize(somSelf)) {
614 /* The filesize changed, somebody altered the audio file so reread the info */
615 /* Get class object */
616 M_CWMMDataFile *m_cwmmDataFile=_CWMMDataFile;
617
618 /* Send the object pointer to the audio worker thread to read the audio info in the background. */
619 WinPostMsg(__get_hwndAudioWorker(_CWMMDataFile), WM_APPTERMINATENOTIFY, somSelf, 0);
620
621#if 0
622 /* The following is only important for MP3 files because gathering the audio info
623 for MP3 files is currently very slow. Will improve with future releases of MMIOMP3*/
624 if(!cwObjectIsOnCD(somSelf)) {
625 /* Only get audio info when file isn't on CD. This speeds up opening of folders on CDs filled with
626 MP3s. Doesn't hurt because folders of CDs open in normal details view as default so the audio info
627 isn't necessary. When opening the settings notebook the info is reread anyway. */
628
629 /* Get class object */
630 M_CWMMDataFile *m_cwmmDataFile=_CWMMDataFile;
631
632 /* Send the object pointer to the audio worker thread to read the audio info in the background. */
633 WinPostMsg(__get_hwndAudioWorker(_CWMMDataFile), WM_APPTERMINATENOTIFY, somSelf, 0);
634 }
635#endif
636 }
637
638
639 //Clear the pageinfo structure
640 memset((PCH)&pageinfo, 0, sizeof(PAGEINFO));
641 //Fill the pageinfo structure
642 pageinfo.cb = sizeof(PAGEINFO);
643 pageinfo.hwndPage = NULLHANDLE;
644 pageinfo.usPageStyleFlags = BKA_MAJOR | BKA_STATUSTEXTON;
645 pageinfo.usPageInsertFlags = BKA_FIRST;
646 //We want page numbers
647 pageinfo.usSettingsFlags = SETTINGS_PAGE_NUMBERS;
648 //The dialog procedure for this page
649 pageinfo.pfnwp = waveInfoDlgProc;
650 //The resource DLL
651 pageinfo.resid = queryResModuleHandle();
652 //pageinfo.resid = queryModuleHandle();
653 //The ID of the dialog template
654 pageinfo.dlgid = IDDLG_WAVEINFOPAGE;
655 //We need a pointer to our WPS-object in the dialog procedure
656 //to call class functions
657 pageinfo.pCreateParams = somSelf;
658 //The ID of the help panel for this page
659 //pageinfo.idDefaultHelpPanel = IDDLG_GENERAL2PAGE;
660 //Tell the WPS the help library name
661 pageinfo.pszHelpLibraryName = NULLHANDLE;
662 //We have a major tab so we need a name
663 if(!getMessage(pageName, ID_WAVEINFOPAGENAME, sizeof(pageName), queryResModuleHandle(), hwndNotebook))
664 strcpy(pageName, "~Audio information");
665 pageinfo.pszName = pageName;
666 //Insert the page into the settings notebook
667 return _wpInsertSettingsPage(somSelf,hwndNotebook,&pageinfo);
668}
669
670/*
671 * The prototype for cwaudio_cwmmSetTrackInfo was replaced by the following prototype:
672 */
673
674/*
675 * SOM_Scope BOOL SOMLINK cwaudio_cwmmSetTrackInfo(MMAudio *somSelf,
676 * char* chrString,
677 * ULONG ulValue,
678 * int iWhich)
679 */
680
681/*
682 * The prototype for cwaudio_cwmmSetTrackInfo was replaced by the following prototype:
683 */
684SOM_Scope BOOL SOMLINK cwaudio_cwmmSetTrackInfo(MMAudio *somSelf,
685 char* chrString,
686 ULONG ulValue,
687 ULONG iWhich)
688{
689 ULONG ulError;
690 MMAudioData *somThis = MMAudioGetData(somSelf);
691 MMAudioMethodDebug("MMAudio","cwaudio_cwmmSetIdInfo");
692
693 if(iWhich<1||iWhich>IDINFO_LASTINFO)
694 return FALSE;
695
696 switch(iWhich)
697 {
698 case IDINFO_PLAYTIME:
699 _ulPlaySecs=ulValue;
700 sprintf(_chrPlayTime, "%02d:%02d",_ulPlaySecs/60, _ulPlaySecs%60);
701 break;
702
703 case IDINFO_BPS:
704 _ulBPS=ulValue;
705 sprintf(_chrBPS, "%d",_ulBPS);
706 break;
707 case IDINFO_CHANNELS:
708 _ulChannels=ulValue;
709 sprintf(_chrChannels, "%d",_ulChannels);
710 break;
711 case IDINFO_SAMPLERATE:
712 _ulSampleRate=ulValue;
713 sprintf(_chrSampleRate, "%d",_ulSampleRate);
714 break;
715
716 case IDINFO_NAME:
717 {
718 char chrEA[MAX_EA_SIZE];
719 /* Make sure string isn't longer than defined EA size */
720 my_strlcpy(chrEA, chrString, sizeof(chrEA));
721 _pszName=somReallocString(somSelf, _pszName, chrEA, &ulError);
722 //SysWriteToTrapLog("!! %s %d\n", __FUNCTION__, __LINE__);
723 break;
724 }
725 case IDINFO_ARTIST:
726 {
727 char chrEA[MAX_EA_SIZE];
728 my_strlcpy(chrEA, chrString, sizeof(chrEA));
729 _pszArtist=somReallocString(somSelf, _pszArtist, chrEA, &ulError);
730 break;
731 }
732 case IDINFO_ALBUM:
733 {
734 char chrEA[MAX_EA_SIZE];
735 /* Make sure string isn't longer than defined EA size */
736 my_strlcpy(chrEA, chrString, sizeof(chrEA));
737 _pszAlbum=somReallocString(somSelf, _pszAlbum, chrEA, &ulError);
738 break;
739 }
740 case IDINFO_YEAR:
741 {
742 char chrEA[MAX_EA_SIZE];
743 /* Make sure string isn't longer than defined EA size */
744 my_strlcpy(chrEA, chrString, sizeof(chrEA));
745 _pszYear=somReallocString(somSelf, _pszYear, chrEA, &ulError);
746 break;
747 }
748 case IDINFO_COMMENT:
749 {
750 char chrEA[MAX_EA_SIZE];
751 /* Make sure string isn't longer than defined EA size */
752 my_strlcpy(chrEA, chrString, sizeof(chrEA));
753 _pszComment=somReallocString(somSelf, _pszComment, chrEA, &ulError);
754 break;
755 }
756 case IDINFO_GENRE:
757 {
758 char chrEA[MAX_EA_SIZE];
759 /* Make sure string isn't longer than defined EA size */
760 my_strlcpy(chrEA, chrString, sizeof(chrEA));
761 _pszGenre=somReallocString(somSelf, _pszGenre, chrEA, &ulError);
762 break;
763 }
764
765#if 0
766 case IDINFO_NAME:
767 strncpy(_id3Name,chrString,sizeof(_id3Name));
768 _id3Name[sizeof(_id3Name)-1]=0;
769 _removeTrailingSpaces(_id3Name);
770 break;
771 case IDINFO_ARTIST:
772 strncpy(_id3Artist,chrString,sizeof(_id3Artist));
773 _id3Artist[sizeof(_id3Artist)-1]=0;
774 _removeTrailingSpaces(_id3Artist);
775 break;
776 case IDINFO_ALBUM:
777 strncpy(_id3Album, chrString, sizeof(_id3Album));
778 _id3Album[sizeof(_id3Album)-1]=0;
779 _removeTrailingSpaces(_id3Album);
780 break;
781 case IDINFO_YEAR:
782 strncpy(_id3Year, chrString, sizeof(_id3Year));
783 _id3Year[sizeof(_id3Year)-1]=0;
784 _removeTrailingSpaces(_id3Year);
785 break;
786 case IDINFO_COMMENT:
787 strncpy(_id3Comment,chrString, sizeof(_id3Comment));
788 _id3Comment[sizeof(_id3Comment)]=0;
789 _removeTrailingSpaces(_id3Comment);
790 break;
791 case IDINFO_GENRE:
792 strncpy(_id3Genre, chrString, sizeof(_id3Genre));
793 _id3Genre[sizeof(_id3Genre)-1]=0;
794 _removeTrailingSpaces(_id3Genre);
795 break;
796#endif
797
798 default:
799 return FALSE;
800 }
801
802 /* Return statement to be customized: */
803 return TRUE;
804}
805
806
807/*
808 * The prototype for cwaudio_cwmmQueryTrackInfo was replaced by the following prototype:
809 */
810
811/*
812 * SOM_Scope ULONG SOMLINK cwaudio_cwmmQueryTrackInfo(MMAudio *somSelf,
813 * char** chrString,
814 * ULONG ulSize,
815 * int iWhich)
816 */
817
818/*
819 * The prototype for cwaudio_cwmmQueryTrackInfo was replaced by the following prototype:
820 */
821/*!*******************************************************/
822/* */
823/* @@DESC */
824/* */
825/* This instance method is called on an object when */
826/* information about the track is needed. */
827/* */
828/* */
829/* @@USAGE */
830/* */
831/* This method can be called at any time in order to */
832/* get information about an audio object. */
833/* :p. */
834/* The parameters :hp2.chrString:ehp2. and */
835/* :hp2.ulSize:ehp2. can be NULL if :hp2.iWhich:ehp2. */
836/* is one of the following */
837/* */
838/* :ul compact. */
839/* :li.IDINFO_PLAYTIME */
840/* :li.IDINFO_BPS */
841/* :li.IDINFO_CHANNELS */
842/* :li.IDINFO_SAMPLERATE */
843/* :li.IDINFO_BITRATE */
844/* :eul. */
845/* :p. */
846/* A numeric value is returned, for example the play */
847/* time. */
848/* :p. */
849/* For */
850/* */
851/* :ul compact. */
852/* :li.IDINFO_NAME */
853/* :li.IDINFO_ARTIST */
854/* :li.IDINFO_ALBUM */
855/* :li.IDINFO_COMMENT */
856/* :li.IDINFO_YEAR */
857/* :li.IDINFO_GENRE */
858/* :eul. */
859/* :p. */
860/* A string is copied into the buffer pointed to by */
861/* :hp2.chrString:ehp2.. At most ulSize-1 characters are */
862/* copied. The string is terminated by a trailing 0. */
863/* :p. */
864/* If both :hp2.chrString:ehp2. and :hp2.ulSize:ehp2. */
865/* are NULL the necessary buffersize for holding the */
866/* complete string (including the trailing 0) is */
867/* returned. */
868/* */
869/* @@PARAM */
870/* */
871/* MMAudio *somSelf input */
872/* */
873/* Pointer to the object on which the method is being */
874/* invoked. */
875/* :p. */
876/* Points to an object of class :hp2.MMAudio:ehp2.. */
877/* */
878/* @@PARAM */
879/* */
880/* PSZ chrString in/out */
881/* */
882/* Pointer to a buffer receiving the information. */
883/* It is only used when querying a string. The returned */
884/* string is always terminated with 0. */
885/* */
886/* @@PARAM */
887/* */
888/* ULONG ulSize input */
889/* */
890/* Size of the buffer :hp2.chrString:ehp2.. */
891/* */
892/* @@PARAM */
893/* */
894/* int iWhich input */
895/* */
896/* Parameter specifying which information is queried. */
897/* :parml compact tsize=25 break=none. */
898/* :pt.IDINFO_PLAYTIME */
899/* :pd.The running time of the track in seconds. */
900/* :pt.IDINFO_BPS */
901/* :pd.Bits per sample. */
902/* :pt.IDINFO_CHANNELS */
903/* :pd.Number of channels. For MIDI files this is the */
904/* number of MIDI tracks. */
905/* :pt.IDINFO_SAMPLERATE */
906/* :pd.Samplerate */
907/* :pt.IDINFO_BITRATE */
908/* :pd.Bitrate */
909/* :pt.IDINFO_NAME */
910/* :pd. */
911/* :pt.IDINFO_ARTIST */
912/* :pd. */
913/* :pt.IDINFO_ALBUM */
914/* :pd. */
915/* :pt.IDINFO_COMMENT */
916/* :pd. */
917/* :pt.IDINFO_YEAR */
918/* :pd. */
919/* :pt.IDINFO_GENRE */
920/* :pd. */
921/* :eparml. */
922/* */
923/* @@OVERRIDE */
924/* */
925/* This method can be overriden by child classes if */
926/* such a class adds other information. */
927/* */
928/* @@RETURNS */
929/* */
930/* ULONG rc */
931/* */
932/* A numeric value for */
933/* */
934/* :ul compact. */
935/* :li.IDINFO_PLAYTIME */
936/* :li.IDINFO_BPS */
937/* :li.IDINFO_CHANNELS */
938/* :li.IDINFO_SAMPLERATE */
939/* :li.IDINFO_BITRATE */
940/* :eul. */
941/* :p. */
942/* 0 indicates the information isn't available. */
943/* :p. */
944/* For */
945/* */
946/* :ul compact. */
947/* :li.IDINFO_NAME */
948/* :li.IDINFO_ARTIST */
949/* :li.IDINFO_ALBUM */
950/* :li.IDINFO_COMMENT */
951/* :li.IDINFO_YEAR */
952/* :li.IDINFO_GENRE */
953/* :eul. */
954/* :p. */
955/* a return value of 0 indicates an error or the */
956/* information isn't available. A value <> 0 indicates */
957/* successful completion. */
958/*!!******************************************************/
959
960/*
961 * SOM_Scope ULONG SOMLINK cwaudio_cwmmQueryTrackInfo(MMAudio *somSelf,
962 * PSZ chrString,
963 * ULONG ulSize,
964 * int iWhich)
965 */
966
967/*
968 * The prototype for cwaudio_cwmmQueryTrackInfo was replaced by the following prototype:
969 */
970SOM_Scope ULONG SOMLINK cwaudio_cwmmQueryTrackInfo(MMAudio *somSelf,
971 PSZ chrString,
972 ULONG ulSize,
973 ULONG iWhich)
974{
975 MMAudioData *somThis = MMAudioGetData(somSelf);
976 MMAudioMethodDebug("MMAudio","cwaudio_cwmmQueryTrackInfo");
977
978 switch(iWhich)
979 {
980 case IDINFO_PLAYTIME:
981 return _ulPlaySecs;
982 case IDINFO_BPS:
983 return _ulBPS;
984 case IDINFO_CHANNELS:
985 return _ulChannels;
986 case IDINFO_SAMPLERATE:
987 return _ulSampleRate;
988 case IDINFO_BITRATE:
989 return _ulBitRate;
990
991 case IDINFO_NAME:
992 {
993 if(!_pszName) /* No information yet */
994 return FALSE;
995 /* Caller asks for buffer size */
996 if(!chrString && ulSize==0)
997 return strlen(_pszName)+1;
998 if(!chrString)
999 return 0;
1000
1001 if(ulSize>strlen(_pszName)) {
1002 strcpy(chrString, _pszName);
1003 }
1004 else {
1005 strncpy(chrString, _pszName, ulSize);
1006 chrString[ulSize-1]=0;
1007 }
1008 if(chrString[0]==0)
1009 return FALSE;
1010 else
1011 return TRUE;
1012 }
1013 case IDINFO_ARTIST:
1014 {
1015 // char *chr=*chrString;
1016 if(!_pszArtist)
1017 return FALSE;
1018 /* Caller asks for buffer size */
1019 if(!chrString && ulSize==0)
1020 return strlen(_pszArtist)+1;
1021 if(!chrString)
1022 return 0;
1023
1024 if(ulSize>strlen(_pszArtist)) {
1025 strcpy(chrString, _pszArtist);
1026 }
1027 else {
1028 strncpy(chrString, _pszArtist, ulSize);
1029 chrString[ulSize-1]=0;
1030 }
1031 if(chrString[0]==0)
1032 return FALSE;
1033 else
1034 return TRUE;
1035 }
1036 case IDINFO_ALBUM:
1037 {
1038 // char *chr=*chrString;
1039 if(!_pszAlbum)
1040 return FALSE;
1041 /* Caller asks for buffer size */
1042 if(!chrString && ulSize==0)
1043 return strlen(_pszAlbum)+1;
1044 if(!chrString)
1045 return 0;
1046
1047 if(ulSize>strlen(_pszAlbum)) {
1048 strcpy(chrString, _pszAlbum);
1049 }
1050 else {
1051 strncpy(chrString, _pszAlbum, ulSize);
1052 chrString[ulSize-1]=0;
1053 }
1054 if(chrString[0]==0)
1055 return FALSE;
1056 else
1057 return TRUE;
1058 }
1059 case IDINFO_COMMENT:
1060 {
1061 // char *chr=*chrString;
1062 if(!_pszComment)
1063 return FALSE;
1064 /* Caller asks for buffer size */
1065 if(!chrString && ulSize==0)
1066 return strlen(_pszComment)+1;
1067 if(!chrString)
1068 return 0;
1069
1070 if(ulSize>strlen(_pszComment)) {
1071 strcpy(chrString, _pszComment);
1072 }
1073 else {
1074 strncpy(chrString, _pszComment, ulSize);
1075 chrString[ulSize-1]=0;
1076 }
1077 if(chrString[0]==0)
1078 return FALSE;
1079 else
1080 return TRUE;
1081 }
1082 case IDINFO_YEAR:
1083 {
1084 // char *chr=*chrString;
1085 if(!_pszYear)
1086 return FALSE;
1087 /* Caller asks for buffer size */
1088 if(!chrString && ulSize==0)
1089 return strlen(_pszYear)+1;
1090 if(!chrString)
1091 return 0;
1092
1093 if(ulSize>strlen(_pszYear)) {
1094 strcpy(chrString, _pszYear);
1095 }
1096 else {
1097 strncpy(chrString, _pszYear, ulSize);
1098 chrString[ulSize-1]=0;
1099 }
1100 if(chrString[0]==0)
1101 return FALSE;
1102 else
1103 return TRUE;
1104 }
1105 case IDINFO_GENRE:
1106 {
1107 // char *chr=*chrString;
1108 if(!_pszGenre)
1109 return FALSE;
1110 /* Caller asks for buffer size */
1111 if(!chrString && ulSize==0)
1112 return strlen(_pszGenre)+1;
1113 if(!chrString)
1114 return 0;
1115
1116 if(ulSize>=strlen(_pszGenre)) {
1117 strcpy(chrString, _pszGenre);
1118 }
1119 else {
1120 strncpy(chrString, _pszGenre, ulSize);
1121 chrString[ulSize-1]=0;
1122 }
1123 if(chrString[0]==0)
1124 return FALSE;
1125 else
1126 return TRUE;
1127 }
1128
1129#if 0
1130 case IDINFO_NAME:
1131 {
1132 char *chr=*chrString;
1133 if(ulSize>=sizeof(_id3Name)) {
1134 strncpy(chr, _id3Name, sizeof(_id3Name));
1135 chr[sizeof(_id3Name)-1]=0;
1136 }
1137 else {
1138 strncpy(chr, _id3Name, ulSize);
1139 chr[ulSize-1]=0;
1140 }
1141 if(chr[0]==0)
1142 return FALSE;
1143 else
1144 return TRUE;
1145 }
1146 case IDINFO_ARTIST:
1147 {
1148 char *chr=*chrString;
1149 if(ulSize>=sizeof(_id3Artist)) {
1150 strncpy(chr, _id3Artist, sizeof(_id3Artist));
1151 chr[sizeof(_id3Artist)-1]=0;
1152 }
1153 else {
1154 strncpy(chr, _id3Artist, ulSize);
1155 chr[ulSize-1]=0;
1156 }
1157 if(chr[0]==0)
1158 return FALSE;
1159 else
1160 return TRUE;
1161 }
1162 case IDINFO_ALBUM:
1163 {
1164 char *chr=*chrString;
1165 if(ulSize>=sizeof(_id3Album)) {
1166 strncpy(chr, _id3Album, sizeof(_id3Album));
1167 chr[sizeof(_id3Album)-1]=0;
1168 }
1169 else {
1170 strncpy(chr, _id3Album, ulSize);
1171 chr[ulSize-1]=0;
1172 }
1173 if(chr[0]==0)
1174 return FALSE;
1175 else
1176 return TRUE;
1177 }
1178 case IDINFO_COMMENT:
1179 {
1180 char *chr=*chrString;
1181 if(ulSize>=sizeof(_id3Comment)) {
1182 strncpy(chr, _id3Comment, sizeof(_id3Comment));
1183 chr[sizeof(_id3Comment)-1]=0;
1184 }
1185 else {
1186 strncpy(chr, _id3Comment, ulSize);
1187 chr[ulSize-1]=0;
1188 }
1189 if(chr[0]==0)
1190 return FALSE;
1191 else
1192 return TRUE;
1193 }
1194 case IDINFO_YEAR:
1195 {
1196 char *chr=*chrString;
1197 if(ulSize>=sizeof(_id3Year)) {
1198 strncpy(chr, _id3Year, sizeof(_id3Year));
1199 chr[sizeof(_id3Year)-1]=0;
1200 }
1201 else {
1202 strncpy(chr, _id3Year, ulSize);
1203 chr[ulSize-1]=0;
1204 }
1205 if(chr[0]==0)
1206 return FALSE;
1207 else
1208 return TRUE;
1209 }
1210 case IDINFO_GENRE:
1211 {
1212 char *chr=*chrString;
1213 if(ulSize>=sizeof(_id3Genre)) {
1214 strncpy(chr, _id3Genre, sizeof(_id3Genre));
1215 chr[sizeof(_id3Genre)-1]=0;
1216 }
1217 else {
1218 strncpy(chr, _id3Genre, ulSize);
1219 chr[ulSize-1]=0;
1220 }
1221 if(chr[0]==0)
1222 return FALSE;
1223 else
1224 return TRUE;
1225 }
1226#endif
1227
1228 default:
1229 break;
1230 }
1231
1232 /* Return statement to be customized: */
1233 return 0;
1234}
1235
1236/************************************************************/
1237/* */
1238/* */
1239/* */
1240/************************************************************/
1241MRESULT EXPENTRY playObjectProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1242{
1243
1244 switch (msg)
1245 {
1246 case WM_APPTERMINATENOTIFY:
1247 {
1248 if(LONGFROMMP(mp1)==ACKEY_START)
1249 {
1250 unsigned char chrCommand[CCHMAXPATH*2];
1251 char chrDevice[20];
1252 char name[CCHMAXPATH];
1253 ULONG ulNameSize;
1254 char retMsg[20];
1255 APIRET rc;
1256 int iTime;
1257 OPENPARAMS * pParams;
1258 MMAudio * thisPtr;
1259 char *s;
1260
1261 pParams=PVOIDFROMMP(mp2);/* Get parameter block */
1262 if(!pParams)
1263 {
1264 WinPostMsg(hwnd,WM_QUIT,0,0);
1265 return MRFALSE;
1266 }
1267
1268 WinSetWindowULong(hwnd, QWL_USER, (ULONG)pParams);
1269
1270 thisPtr=pParams->wpObject;
1271 if(somIsObj(thisPtr)) {
1272 SOMClass* mmMIDIClass=somGetSomClass("MMMIDI");
1273 MMAudioData *somThis = MMAudioGetData(thisPtr);
1274
1275 ulNameSize=sizeof(name);
1276 _wpQueryRealName(thisPtr, name, &ulNameSize, TRUE);
1277
1278 if(_somIsA(thisPtr, mmMIDIClass)) {
1279 strncpy(chrDevice,"sequencer", sizeof(chrDevice) - 1);
1280 /* Start audio file */
1281 sprintf(chrCommand,"open \"%s\" type %s alias wave%p shareable wait", name, chrDevice, thisPtr);
1282 rc = mciSendString( chrCommand, retMsg, sizeof(retMsg), hwnd, 0);
1283 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1284 WinPostMsg(hwnd,WM_QUIT,0,0);
1285 return MRFALSE;
1286 }
1287
1288 /* Set time format */
1289 sprintf(chrCommand,"SET wave%p TIME FORMAT MILLISECONDS wait", thisPtr);
1290 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1291 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1292 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1293 return MRFALSE;
1294 }
1295
1296 sprintf(chrCommand,"STATUS wave%p LENGTH WAIT", thisPtr);
1297 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1298 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1299 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1300 return MRFALSE;
1301 }
1302
1303 iTime=atoi(retMsg);
1304
1305 // sprintf(chrCommand,"SETPOSITIONADVISE wave%p ON EVERY %d NOTIFY", thisPtr, 3000);
1306 // rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), hwnd, 0);
1307
1308 if(iTime>1100)
1309 iTime-=700;
1310 else
1311 iTime-=300;
1312
1313 if(iTime<=0)
1314 iTime=10;
1315
1316 sprintf(chrCommand,"SETCUEPOINT wave%p ON at %d WAIT", thisPtr, iTime);
1317 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), hwnd, 0);
1318 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1319 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1320 return MRFALSE;
1321 }
1322
1323
1324 /* Set volume */
1325 sprintf(chrCommand,"SET wave%p AUDIO VOLUME %d wait", thisPtr, globalClassVolume);
1326 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1327 /* Not able to set the volume isn't that bad so don't quit in case of an error. */
1328 #if 0
1329 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1330 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1331 return MRFALSE;
1332 }
1333 #endif
1334
1335 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, 1, 100);
1336
1337 sprintf(chrCommand,"play wave%p", thisPtr);
1338 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1339 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1340 WinSendMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1341 return MRFALSE;
1342 }
1343
1344 /* Set Time in icon title to 00:00 */
1345 strncpy(chrCommand, _wpQueryTitle(thisPtr), CCHMAXPATH);
1346 if(_ulPlaySecs) {
1347 sprintf(retMsg, "%02d:%02d", _ulPlaySecs/60, _ulPlaySecs%60);
1348 strncat(chrCommand,"\n00:00 / ",sizeof(chrCommand)-1-strlen(chrCommand));
1349 strncat(chrCommand, retMsg,sizeof(chrCommand)-1-strlen(chrCommand));
1350 }
1351 else
1352 strncat(chrCommand,"\n00:00", sizeof(chrCommand)-1-strlen(chrCommand));
1353
1354 _cwmmSetRecordTitles(thisPtr, chrCommand, FALSE);
1355 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, 1, 1000);
1356 __set_ulTrackStatus( thisPtr,TRACK_STATUS_PLAYING);
1357
1358 }
1359 else {
1360 strncpy(chrDevice,"WAVEAUDIO", sizeof(chrDevice) - 1);
1361 /* Start audio file */
1362 sprintf(chrCommand,"open \"%s\" type %s alias wave%p SHAREABLE wait",name, chrDevice, thisPtr);
1363 rc = mciSendString( chrCommand, retMsg, sizeof(retMsg), hwnd, 0);
1364 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1365 WinPostMsg(hwnd,WM_QUIT,0,0);
1366 return MRFALSE;
1367 }
1368
1369 /* Set time format */
1370 sprintf(chrCommand,"SET wave%p TIME FORMAT MILLISECONDS wait", thisPtr);
1371 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1372 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1373 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1374 return MRFALSE;
1375 }
1376
1377 sprintf(chrCommand,"STATUS wave%p LENGTH WAIT", thisPtr);
1378 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1379 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1380 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1381 return MRFALSE;
1382 }
1383
1384 iTime=atoi(retMsg);
1385
1386 // sprintf(chrCommand,"SETPOSITIONADVISE wave%p ON EVERY %d NOTIFY", thisPtr, 3000);
1387 // rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), hwnd, 0);
1388
1389 if(iTime>1100)
1390 iTime-=700;
1391 else
1392 iTime-=300;
1393
1394 if(iTime<=0)
1395 iTime=100;
1396
1397 sprintf(chrCommand,"SETCUEPOINT wave%p ON at %d WAIT", thisPtr, iTime);
1398 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), hwnd, 0);
1399 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1400 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1401 return MRFALSE;
1402 }
1403
1404 /* Set volume */
1405 sprintf(chrCommand,"SET wave%p AUDIO VOLUME %d wait", thisPtr, globalClassVolume);
1406 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1407 /* Not able to set the volume isn't that bad so don't quit in case of an error. */
1408 #if 0
1409 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1410 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1411 return MRFALSE;
1412 }
1413 #endif
1414
1415 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, 1, 100);
1416
1417 sprintf(chrCommand,"play wave%p ", thisPtr);
1418 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1419 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1420 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1421 return MRFALSE;
1422 }
1423
1424 /* Set Time in icon title to 00:00 */
1425 strncpy(chrCommand, _wpQueryTitle(thisPtr), CCHMAXPATH);
1426 s = strchr(chrCommand, '\n');
1427 if (s)
1428 *s = 0;
1429 if(_ulPlaySecs) {
1430 sprintf(retMsg, "%02d:%02d", _ulPlaySecs/60, _ulPlaySecs%60);
1431 strncat(chrCommand,"\n00:00 / ",sizeof(chrCommand)-1-strlen(chrCommand));
1432 strncat(chrCommand, retMsg,sizeof(chrCommand)-1-strlen(chrCommand));
1433 }
1434 else
1435 strncat(chrCommand,"\n00:00", sizeof(chrCommand)-1-strlen(chrCommand));
1436
1437 _cwmmSetRecordTitles(thisPtr, chrCommand, FALSE);
1438 WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, 1, 1000);
1439 __set_ulTrackStatus( thisPtr,TRACK_STATUS_PLAYING);
1440 }
1441 break;
1442 }/* somIsObj(thisPtr) */
1443 }
1444 else
1445 {
1446 MMAudio * thisPtr;
1447
1448 /* Don't use parameter block here (see AVKEY_PLAY handling). The param is
1449 indeed somSelf. */
1450 thisPtr=(MMAudio *)PVOIDFROMMP(mp2);/* Get object ptr */
1451 if(somIsObj(thisPtr)) {
1452 switch(LONGFROMMP(mp1))
1453 {
1454 case ACKEY_VOLUME:
1455 {
1456 HWND globalHwndObjectPlay;
1457 unsigned char chrCommand[CCHMAXPATH];
1458 char retMsg[20];
1459
1460 /* Set volume */
1461 sprintf(chrCommand,"SET wave%p AUDIO VOLUME %d ", thisPtr, globalClassVolume);
1462 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1463 /* Not able to set the volume isn't that bad so don't quit in case of an error. */
1464 break;
1465 }
1466 case ACKEY_STOP:
1467 {
1468 /* Stop playing */
1469 unsigned char chrCommand[CCHMAXPATH];
1470 char retMsg[20];
1471
1472 WinStopTimer(WinQueryAnchorBlock(hwnd),hwnd,1 );
1473
1474 sprintf(chrCommand,"stop wave%p wait", thisPtr);
1475 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1476
1477 sprintf(chrCommand,"close wave%p wait", thisPtr);
1478 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1479
1480 __set_ulTrackStatus(thisPtr, TRACK_STATUS_STOPPED);
1481 WinPostMsg(hwnd,WM_QUIT,0,0);
1482 break;
1483 }
1484 case ACKEY_PAUSE:
1485 {
1486 unsigned char chrCommand[CCHMAXPATH];
1487 char retMsg[20];
1488 APIRET rc;
1489
1490 sprintf(chrCommand,"STATUS wave%p MODE WAIT", thisPtr);
1491 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1492 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1493 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1494 return MRFALSE;
1495 }
1496
1497 if(!stricmp(retMsg, "playing"))
1498 {
1499 sprintf(chrCommand,"PAUSE wave%p wait", thisPtr);
1500 rc=mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1501 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1502 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1503 return MRFALSE;
1504 }
1505 __set_ulTrackStatus(thisPtr, TRACK_STATUS_PAUSED);
1506 }
1507 break;
1508 }
1509 case ACKEY_RESUME:
1510 {
1511 unsigned char chrCommand[CCHMAXPATH];
1512 char retMsg[20];
1513 APIRET rc;
1514
1515 sprintf(chrCommand,"STATUS wave%p MODE WAIT", thisPtr);
1516 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1517 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1518 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1519 return MRFALSE;
1520 }
1521
1522 if(!stricmp(retMsg, "paused"))
1523 {
1524 sprintf(chrCommand,"RESUME wave%p wait", thisPtr);
1525 rc=mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1526 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1527 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1528 return MRFALSE;
1529 }
1530 __set_ulTrackStatus(thisPtr, TRACK_STATUS_PLAYING);
1531 }
1532 break;
1533 }
1534 default:
1535 break;
1536 }
1537 }/* if(thisPtr) */
1538 return MRFALSE;
1539 }
1540 }
1541 //case MM_MCIPOSITIONCHANGE:
1542 case WM_TIMER:
1543 if(SHORT1FROMMP(mp1)==1) {
1544 MMAudio * thisPtr;
1545 OPENPARAMS * pParams;
1546
1547 pParams=(OPENPARAMS*)WinQueryWindowULong(hwnd, QWL_USER);
1548 thisPtr=pParams->wpObject;
1549
1550 if(somIsObj(thisPtr)) {
1551 char retMsg[50] = {0};
1552 unsigned char chrCommand[CCHMAXPATH+20] = {0};
1553 APIRET rc;
1554 ULONG ulCur;
1555 MMAudioData *somThis = MMAudioGetData(thisPtr);
1556 char *s;
1557
1558 /*@@CHANGE 0.2.8:
1559
1560 Added check for hwndCnr==NULL, audio objects stopped playing after a second if not started from a folder.
1561 */
1562 /* Check if folder closed. If yes stop playing */
1563 if(pParams->hwndCnr && !WinIsWindow(globalHab, pParams->hwndCnr)) {
1564 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1565 return MRFALSE;
1566 }
1567 /* Get current play position */
1568 sprintf(chrCommand,"STATUS wave%p POSITION WAIT", thisPtr);
1569 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1570 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1571 return MRFALSE;
1572 }
1573
1574 ulCur=atoi(retMsg);
1575 if(ulCur) {
1576 ulCur/=1000;
1577 if(!ulCur)
1578 ulCur=1;
1579 }
1580
1581 strncpy(chrCommand, _wpQueryTitle(thisPtr), CCHMAXPATH);
1582 s = strchr(chrCommand, '\n');
1583 if (s)
1584 *s = 0;
1585 strncat(chrCommand,"\n",sizeof(chrCommand)-1-strlen(chrCommand));
1586 if(_ulPlaySecs) {
1587 sprintf(retMsg, "%02d:%02d / %02d:%02d", ulCur/60, ulCur%60, _ulPlaySecs/60, _ulPlaySecs%60);
1588 strncat(chrCommand, retMsg,sizeof(chrCommand)-1-strlen(chrCommand));
1589 }
1590 else
1591 {
1592 sprintf(retMsg, "%02d:%02d", ulCur/60, ulCur%60);
1593 strncat(chrCommand, retMsg,sizeof(chrCommand)-1-strlen(chrCommand));
1594 }
1595 if(_cwmmQueryTrackStatus(thisPtr)==TRACK_STATUS_PAUSED) {
1596 if(!getMessage(retMsg, IDSTR_TRACKPAUSED, sizeof(retMsg), queryResModuleHandle(), HWND_DESKTOP))
1597 strcpy(retMsg," (Paused)");
1598 strncat(chrCommand, retMsg,sizeof(chrCommand)-1-strlen(chrCommand));
1599 }
1600 /* Set new time in icon title */
1601 _cwmmSetRecordTitles(thisPtr, chrCommand, FALSE);
1602 }
1603 return MRFALSE;
1604 }
1605 break;
1606 case MM_MCICUEPOINT:
1607 {
1608 /***********************************************/
1609 /* The track is about to end */
1610 /***********************************************/
1611 MMAudio * thisPtr;
1612 OPENPARAMS * pParams;
1613 pParams=(OPENPARAMS*)WinQueryWindowULong(hwnd, QWL_USER);
1614 thisPtr=pParams->wpObject;
1615
1616 if(somIsObj(thisPtr)) {
1617 unsigned char chrCommand[CCHMAXPATH];
1618 char retMsg[20];
1619
1620 sprintf(chrCommand,"STATUS wave%p MODE WAIT", thisPtr);
1621 do {
1622 APIRET rc;
1623 retMsg[0]=0;
1624 DosSleep(100);
1625 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
1626 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
1627 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1628
1629 return MRFALSE;
1630 }
1631 //HlpWriteToTrapLog("%s\n", retMsg);
1632 } while(!stricmp(retMsg, "playing"));
1633 /* The track ended. Call 'Stop' so the object title is updated and everything is cleaned up.
1634 During handling of the 'Stop' message the WM_QUIT message will be posted to end the thread. */
1635 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(thisPtr));
1636 }
1637 return MRFALSE;
1638 }
1639 default:
1640 break;
1641 }
1642 return WinDefWindowProc( hwnd, msg, mp1, mp2);
1643}
1644
1645/************************************************************/
1646/* */
1647/* This thread is used to handle the object in use emphasis.*/
1648/* Playing starts on the object window proc. */
1649/* */
1650/************************************************************/
1651void _Optlink playThreadFunc (void *arg)
1652{
1653 HAB hab;
1654 HMQ hmq;
1655 QMSG qmsg;
1656 OPENPARAMS * params;
1657 CWMMDataFile *thisPtr;
1658 BOOL bCntDecremented=FALSE; /* Flag telling if the play counter was decremented so another audio file may be started. */
1659
1660 params=(OPENPARAMS*)arg;
1661 if(!params) {
1662 iRunningAudioFiles--;
1663 if(iRunningAudioFiles<0)
1664 iRunningAudioFiles=0;/* Should never happen... */
1665 return;
1666 }
1667
1668 thisPtr=params->wpObject;
1669 if(!somIsObj(thisPtr)) {
1670 iRunningAudioFiles--;
1671 if(iRunningAudioFiles<0)
1672 iRunningAudioFiles=0;/* Should never happen... */
1673 _wpFreeMem(thisPtr, (PBYTE)params);
1674 return;
1675 }
1676
1677 /* Prevent starting of several audio files at the same time */
1678 //if(iRunningAudioFiles<MAX_AUDIOFILE_STARTS+1) {
1679 hab=WinInitialize(0);
1680 if(hab) {
1681 hmq=WinCreateMsgQueue(hab,0);
1682 if(hmq) {
1683 HWND hwnd;
1684 BOOL notFound;
1685
1686 if(somIsObj(thisPtr)) {
1687 params->useItem.type=USAGE_OPENVIEW;
1688 params->viewItem.handle=NULLHANDLE;
1689
1690 /* Create an invisible object window */
1691 hwnd=WinCreateWindow(HWND_OBJECT,WC_STATIC,"playObj", 0, 0, 0, 0, 0,
1692 NULLHANDLE, HWND_BOTTOM,12343,NULL,NULL);
1693 if(hwnd) {
1694 /* Window created. */
1695 /* Set in use emphasis for object */
1696 _wpAddToObjUseList(thisPtr, &params->useItem);
1697
1698 /* Subclass the object window with the audio object private window proc.
1699 Every audio pbject has to set this in order to manage start/stop/resume command.
1700 It's usually done in MMAudio::wpInitData(). */
1701 WinSubclassWindow(hwnd, _cwmmQueryObjWindowProc(thisPtr));
1702 //SysWriteToTrapLog("WinSubclassWindow() returned: %x\n_cwmmQueryObjWindowProc() returns: %x\nplayObjectProc: %x\n",
1703 //WinSubclassWindow(hwnd, _cwmmQueryObjWindowProc(thisPtr)), _cwmmQueryObjWindowProc(thisPtr),playObjectProc);
1704
1705 // DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
1706
1707 /* Tell the window proc to start the file */
1708 WinPostMsg(hwnd, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_START), MPFROMP(params));
1709
1710 /* Save object window pointer in instance data */
1711 __set_hwndObjectPlay(thisPtr, hwnd);
1712 /* Needed for volume setting */
1713 globalHwndObjectPlay=hwnd;
1714 globalObjectPlay=thisPtr;
1715
1716 while(WinGetMsg(hab,&qmsg,(HWND)NULL,0,0))
1717 WinDispatchMsg(hab,&qmsg);
1718 WinDestroyWindow(hwnd);
1719 _cwmmSetRecordTitles(thisPtr, NULLHANDLE, FALSE);
1720 }
1721 if(somIsObj(thisPtr)) {
1722 /* Remove in use emphasis */
1723 _wpDeleteFromObjUseList(thisPtr, &params->useItem);
1724
1725 __set_hwndObjectPlay(thisPtr, NULLHANDLE);
1726
1727 _wpSetDefaultView(thisPtr, __get_ulPreviousView(thisPtr));
1728 }/* somIsObj() */
1729
1730 iRunningAudioFiles--;
1731 if(iRunningAudioFiles<0)
1732 iRunningAudioFiles=0;/* Should never happen... */
1733 bCntDecremented=TRUE;
1734
1735 /* The track ended. Check if there're other tracks selected in
1736 the container. If yes, start the next track. */
1737 notFound=TRUE;
1738 for(;;)
1739 {
1740 PMINIRECORDCORE pMrc, mrcTemp;
1741 OPENPARAMS * pParams;
1742 WPObject * contentObject;
1743 SOMClass *cwAudioClass=somGetSomClass("MMAudio");
1744
1745 pParams=params;
1746
1747 /* Get MINIRECORDCORE */
1748 if(!(pMrc=_wpQueryCoreRecord(thisPtr)))
1749 break;
1750
1751 if(!WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP), pParams->hwndCnr))
1752 break; /* Container isn't valid. Probably the folder was closed. */
1753
1754 /* Remove selected state if any */
1755 WinSendMsg(pParams->hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pMrc), MPFROM2SHORT(FALSE, CRA_SELECTED));
1756
1757 /* Get next selected audio file */
1758 mrcTemp=(PMINIRECORDCORE)WinSendMsg(pParams->hwndCnr,CM_QUERYRECORDEMPHASIS, pMrc,
1759 MPFROMSHORT(CRA_SELECTED));
1760 if((int)mrcTemp==-1)
1761 /* Wrong parameter -> user deleted the shadow. */
1762 break;
1763
1764 /* No selected files after the currently playing one. So start at the beginnning of the
1765 container. */
1766 if(!mrcTemp)
1767 mrcTemp=(PMINIRECORDCORE)WinSendMsg(pParams->hwndCnr,CM_QUERYRECORDEMPHASIS, (MPARAM)CMA_FIRST,
1768 MPFROMSHORT(CRA_SELECTED));
1769
1770 while(notFound && mrcTemp && (int)mrcTemp!=-1){
1771 contentObject=(WPObject*)OBJECT_FROM_PREC(mrcTemp);//Get object
1772 if(somIsObj(contentObject)) {
1773 /* Get file system object or NULL */
1774 if((contentObject=somGetFileSystemObject(contentObject))==NULLHANDLE) {
1775 mrcTemp=(PMINIRECORDCORE)WinSendMsg(pParams->hwndCnr,CM_QUERYRECORDEMPHASIS, mrcTemp,
1776 MPFROMSHORT(CRA_SELECTED));
1777 continue;
1778 }
1779 }
1780 else
1781 break;/* Error */
1782
1783 if(_somIsA(contentObject, cwAudioClass)) {
1784 notFound=FALSE;
1785 }
1786 else
1787 {
1788 /* Try next object */
1789 mrcTemp=(PMINIRECORDCORE)WinSendMsg(pParams->hwndCnr,CM_QUERYRECORDEMPHASIS, mrcTemp,
1790 MPFROMSHORT(CRA_SELECTED));
1791 }
1792 }; /* while */
1793 if(notFound)
1794 break;
1795 /* Another audio file is selected. Start it. */
1796 _wpViewObject(contentObject, params->hwndCnr, ID_MENU_START, NULLHANDLE);
1797 break;
1798 }; /* for() */
1799 /* FIXME
1800 Get thread sync right.
1801
1802 Set global handle to NULL if no more files to play. Doing it this way we prevent a race condition
1803 with the newly started thread. Not really nice but simple. A mutex wouldn't help because we must
1804 prevent that this ending thread overwrites the handle which may be set by the newly started thread. */
1805 if(notFound) {
1806 globalHwndObjectPlay=NULLHANDLE;
1807 globalObjectPlay=NULLHANDLE;
1808 }
1809 }/* somIsObj() */
1810 WinDestroyMsgQueue(hmq);
1811 }
1812 WinTerminate(hab);
1813 }/* hab */
1814 // }/* iRunningAudioFiles */
1815
1816 if(!bCntDecremented) {
1817 iRunningAudioFiles--;
1818 if(iRunningAudioFiles<0)
1819 iRunningAudioFiles=0;/* Should never happen... */
1820 }
1821 /* Free the parameter block */
1822 _wpFreeMem(thisPtr, (PBYTE)params);
1823}
1824
1825/****************************************************************/
1826/* */
1827/* New method which starts playing of the file. Playing is done */
1828/* on a separate thread. */
1829/* */
1830/****************************************************************/
1831/*!*******************************************************/
1832/* */
1833/* @@DESC */
1834/* */
1835/* This instance method is called to allow the object */
1836/* to start or stop audio playing. */
1837/* */
1838/* */
1839/* @@USAGE */
1840/* */
1841/* This method can be called at any time in order to */
1842/* start or stop playing. */
1843/* :p. */
1844/* The audio file is played on a separate thread. In use */
1845/* emphasis is applied and the current playing time */
1846/* will be shown in the objects title. */
1847/* */
1848/* @@PARAM */
1849/* */
1850/* MMAudio *somSelf input */
1851/* */
1852/* Pointer to the object on which the method is being */
1853/* invoked. */
1854/* :p. */
1855/* Points to an object of class :hp2.MMAudio:ehp2.. */
1856/* */
1857/* @@PARAM */
1858/* */
1859/* HWND hwndCnr input */
1860/* */
1861/* Handle of the container which holds the object. */
1862/* */
1863/* @@PARAM */
1864/* */
1865/* BOOL bPlay input */
1866/* */
1867/* Start/stop flag. */
1868/* :p. */
1869/* If TRUE the object will start playing. */
1870/* :p. */
1871/* If FALSE a playing object stops playing. */
1872/* */
1873/* @@OVERRIDE */
1874/* */
1875/* This method is usually not overriden. */
1876/* */
1877/* @@REMARKS */
1878/* */
1879/* This method does not have a return value. */
1880/* The only way to check if the method succeeded is */
1881/* to use the method cwmmQueryTrackStatus(). */
1882/* :p. */
1883/* This is because control is given to a new thread */
1884/* and it's not clear at which time this new thread will */
1885/* start execution. */
1886/* */
1887/*!!******************************************************/
1888SOM_Scope void SOMLINK cwaudio_cwmmPlayTrack(MMAudio* somSelf,
1889 HWND hwndCnr, BOOL bPlay)
1890{
1891 ULONG ulError;
1892 OPENPARAMS *pThreadParams;
1893
1894 MMAudioMethodDebug("MMAudio","cwaudio_cwmmPlayTrack");
1895
1896 if(bPlay) { /* Start playing */
1897 /* Check if there's a valid object window for handling the play messages. */
1898 if(!WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP),__get_hwndObjectPlay(somSelf))) {
1899 /* Start playing only if there's not an object window yet. This is only
1900 a sanity check. If there's already an object window the track already is
1901 started.
1902 */
1903 pThreadParams=(OPENPARAMS*)_wpAllocMem(somSelf, sizeof(OPENPARAMS), &ulError);
1904 if(pThreadParams) {
1905 char chrTitle[CCHMAXPATH];
1906 char chrText[100];
1907
1908 strncpy(chrTitle, _wpQueryTitle(somSelf), sizeof(chrTitle));
1909 chrTitle[sizeof(chrTitle)-1]=0;
1910 if(!getMessage(chrText, IDSTR_STARTINGTRACK, sizeof(chrText), queryResModuleHandle(), HWND_DESKTOP)) {
1911 strcpy(chrText, "Starting Track...");
1912 }
1913 strncat(chrTitle,"\n", sizeof(chrTitle)-1-strlen(chrTitle));
1914 strncat(chrTitle, chrText, sizeof(chrTitle)-1-strlen(chrTitle));
1915
1916 memset((void*)pThreadParams ,0, sizeof(OPENPARAMS));
1917 pThreadParams->wpObject=somSelf;
1918 pThreadParams->hwndCnr=hwndCnr;
1919 pThreadParams->viewItem.view=ID_MENU_START;
1920 if(_beginthread(playThreadFunc,NULL,8192*160,(void*)pThreadParams)) //Fehlerbehandlung fehlt
1921 _cwmmSetRecordTitles(somSelf, chrTitle, FALSE);
1922 }
1923 }
1924 }
1925 else /* Stop playing. */
1926 if(WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP),__get_hwndObjectPlay(somSelf)))
1927 WinPostMsg(__get_hwndObjectPlay(somSelf), WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_STOP), MPFROMP(somSelf));
1928}
1929
1930
1931
1932/*
1933 This method is called to pause a playing track from the context menu.
1934*/
1935/*
1936 * LONG cwmmSetTrackVolume(in ULONG ulVolume);
1937 * LONG cwmmQueryTrackVolume();
1938 */
1939
1940/*
1941 * LONG cwmmSetTrackVolume(in ULONG ulVolume);
1942 * LONG cwmmQueryTrackVolume();
1943 * Local filesize info to check if someone altered the file. Attribute because MMMP3 needs this info.
1944 */
1945/*!*******************************************************/
1946/* */
1947/* @@DESC */
1948/* */
1949/* This instance method is called to allow the object */
1950/* to pause or resume audio playing. */
1951/* */
1952/* */
1953/* @@USAGE */
1954/* */
1955/* This method can be called at any time in order to */
1956/* control playing. */
1957/* */
1958/* @@PARAM */
1959/* */
1960/* MMAudio *somSelf input */
1961/* */
1962/* Pointer to the object on which the method is being */
1963/* invoked. */
1964/* :p. */
1965/* Points to an object of class :hp2.MMAudio:ehp2.. */
1966/* */
1967/* @@PARAM */
1968/* */
1969/* HWND hwndCnr input */
1970/* */
1971/* Handle of the container which holds the object. */
1972/* */
1973/* @@PARAM */
1974/* */
1975/* ULONG ulAction input */
1976/* */
1977/* Pause/resume. */
1978/* :parml compact tsize=25 break=none. */
1979/* :pt.ACKEY_PAUSE:pd.The object will pause playing. */
1980/* :pt.ACKEY_RESUME:pd.A currently pausing object */
1981/* resumes playing. */
1982/* :eparml. */
1983/* @@OVERRIDE */
1984/* */
1985/* This method is usually not overriden. */
1986/* */
1987/* @@REMARKS */
1988/* */
1989/* This method does not have a return value. */
1990/* Use the method cwmmQueryTrackStatus() to check the */
1991/* current state of the audio object. */
1992/* */
1993/* */
1994/* */
1995/*!!******************************************************/
1996SOM_Scope void SOMLINK cwaudio_cwmmPauseTrack(MMAudio *somSelf,
1997 HWND hwndCnr,
1998 ULONG ulAction)
1999{
2000 /* CWMMDataFileData *somThis = CWMMDataFileGetData(somSelf);*/
2001 MMAudioMethodDebug("MMAudio","cwaudio_cwmmPauseTrack");
2002
2003 if(_cwmmQueryTrackStatus(somSelf)==TRACK_STATUS_STOPPED)
2004 return;
2005
2006 switch(ulAction)
2007 {
2008 case ACKEY_PAUSE:
2009
2010 /* Already paused? Shouldn't happen but I've seen it. */
2011 if(_cwmmQueryTrackStatus(somSelf)==TRACK_STATUS_PAUSED)
2012 return;
2013
2014 /* Post a message to the object window handling the commands. */
2015 if(WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP),__get_hwndObjectPlay(somSelf)))
2016 WinPostMsg(__get_hwndObjectPlay(somSelf), WM_APPTERMINATENOTIFY, MPFROMLONG(ulAction), MPFROMP(somSelf));
2017
2018 break;
2019 case ACKEY_RESUME:
2020
2021 if(_cwmmQueryTrackStatus(somSelf)==TRACK_STATUS_PLAYING)
2022 return;
2023
2024 if(WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP), __get_hwndObjectPlay(somSelf)))
2025 WinPostMsg(__get_hwndObjectPlay(somSelf), WM_APPTERMINATENOTIFY, MPFROMLONG(ulAction), MPFROMP(somSelf));
2026 break;
2027 default:
2028 break;
2029 }
2030}
2031
2032#if 0
2033SOM_Scope long SOMLINK cwaudio_cwmmSetTrackVolume(MMAudio *somSelf,
2034 ULONG ulVolume)
2035{
2036 MMAudioData *somThis = MMAudioGetData(somSelf);
2037 MMAudioMethodDebug("MMAudio","cwaudio_cwmmSetTrackVolume");
2038
2039 /* Return statement to be customized: */
2040 return -1;
2041}
2042
2043SOM_Scope long SOMLINK cwaudio_cwmmQueryTrackVolume(MMAudio *somSelf)
2044{
2045 MMAudioData *somThis = MMAudioGetData(somSelf);
2046 MMAudioMethodDebug("MMAudio","cwaudio_cwmmQueryTrackVolume");
2047
2048 /* Return statement to be customized: */
2049 return -1;
2050}
2051#endif
2052
2053/****************************************************************/
2054/*
2055 Two new settings pages are added to every audio object:
2056
2057 -Audio information showing playtime samplerate and so on.
2058 -Track information for editing artist name, album name and so
2059 on.
2060
2061 */
2062/****************************************************************/
2063SOM_Scope BOOL SOMLINK cwaudio_wpAddSettingsPages(MMAudio *somSelf,
2064 HWND hwndNotebook)
2065{
2066 BOOL rc;
2067
2068 /* MMAudioData *somThis = MMAudioGetData(somSelf);*/
2069 MMAudioMethodDebug("MMAudio","cwaudio_wpAddSettingsPages");
2070
2071
2072 rc= (MMAudio_parent_CWMMDataFile_wpAddSettingsPages(somSelf, hwndNotebook));
2073
2074 /* Only insert trackname page if object isn't on CD. CDs don't support EAs so this page
2075 would be useless. */
2076 if(!cwObjectIsOnCD(somSelf))
2077 return rc | _cwmmAddAudioInformationPage(somSelf, hwndNotebook)|
2078 _cwmmAddTrackNamePage(somSelf, hwndNotebook);
2079 else
2080 return rc | _cwmmAddAudioInformationPage(somSelf, hwndNotebook);
2081
2082}
2083
2084/*
2085 * The prototype for cwaudio_wpQueryDetailsData was replaced by the following prototype:
2086 */
2087SOM_Scope ULONG SOMLINK cwaudio_wpQueryDetailsData(MMAudio *somSelf,
2088 PVOID* ppDetailsData,
2089 PULONG pcp)
2090{
2091 BOOL rcParent;
2092 PAUDIODETAILS pAudioDetails;
2093 MMAudioData *somThis = MMAudioGetData(somSelf);
2094 MMAudioMethodDebug("MMAudio","cwaudio_wpQueryDetailsData");
2095
2096 /* Call parent */
2097 rcParent= (MMAudio_parent_CWMMDataFile_wpQueryDetailsData(somSelf,
2098 ppDetailsData,
2099 pcp));
2100
2101 /* The WPS asks for data to be displayed */
2102 if(ppDetailsData)
2103 {
2104 /* Fill the structure with the info to be displayed */
2105 pAudioDetails=(PAUDIODETAILS)*ppDetailsData;
2106 pAudioDetails->pszPlayTime=_chrPlayTime;
2107 pAudioDetails->pszBitRate=_chrBitRate; /* New with 0.2.7 */
2108 pAudioDetails->pszSampleRate=_chrSampleRate;
2109 pAudioDetails->pszChannels=_chrChannels;
2110 pAudioDetails->pszBPS=_chrBPS;
2111
2112 pAudioDetails->pszName=_pszName;
2113 pAudioDetails->pszArtist=_pszArtist;
2114 pAudioDetails->pszAlbum=_pszAlbum;
2115 pAudioDetails->pszYear=_pszYear;
2116 pAudioDetails->pszComment=_pszComment;
2117 pAudioDetails->pszGenre=_pszGenre;
2118
2119#if 0
2120 pAudioDetails->pszName=_id3Name;
2121 pAudioDetails->pszArtist=_id3Artist;
2122 pAudioDetails->pszAlbum=_id3Album;
2123 pAudioDetails->pszYear=_id3Year;
2124 pAudioDetails->pszComment=_id3Comment;
2125 pAudioDetails->pszGenre=_id3Genre;
2126#endif
2127 *ppDetailsData=((PBYTE) (*ppDetailsData))+sizeof(*pAudioDetails);
2128 }
2129 else
2130 {
2131 /* Buffer size is queried */
2132 if(pcp)
2133 *pcp+=sizeof(*pAudioDetails);
2134 }
2135 return rcParent;
2136}
2137
2138
2139/*
2140 * The prototype for cwaudio_wpRestoreState was replaced by the following prototype:
2141 */
2142SOM_Scope BOOL SOMLINK cwaudio_wpRestoreState(MMAudio *somSelf,
2143 ULONG ulReserved)
2144{
2145 BOOL bRc;
2146 char fName[CCHMAXPATH];
2147 BOOL bReRead=FALSE;
2148 ULONG ulError;
2149 BOOL bIsMidi;
2150 PBYTE pByte;
2151
2152 MMAudioData *somThis = MMAudioGetData(somSelf);
2153 MMAudioMethodDebug("MMAudio","cwaudio_wpRestoreState");
2154
2155 bRc=(MMAudio_parent_CWMMDataFile_wpRestoreState(somSelf, ulReserved));
2156
2157 _bNeedSaving=FALSE;
2158
2159 /* Query the audio info */
2160 if(!_wpRestoreLong(somSelf, "CWAudio", KEY_FILESIZE, &_ulFileSize))
2161 bReRead=TRUE;
2162 if(!_wpRestoreLong(somSelf, "CWAudio", KEY_TIME, &_ulPlaySecs))
2163 bReRead=TRUE;
2164 if(!_wpRestoreLong(somSelf, "CWAudio", KEY_CHANNELS, &_ulChannels))
2165 bReRead=TRUE;
2166 if(!_wpRestoreLong(somSelf, "CWAudio", KEY_SAMPLERATE, &_ulSampleRate))
2167 bReRead=TRUE;
2168 if(!_wpRestoreLong(somSelf, "CWAudio", KEY_BPS, &_ulBPS))
2169 bReRead=TRUE;
2170 if(!_wpRestoreLong(somSelf, "CWAudio", KEY_TIME_MS, &_ulPlayMsecs))
2171 bReRead=TRUE;
2172 if(!_wpRestoreLong(somSelf, "CWAudio", KEY_NUM_AUDIO_BYTES, &_ulNumAudioBytes))
2173 bReRead=TRUE;
2174
2175 /* New with 0.2.7 */
2176 if(EARestoreString(somSelf, "MMBITRATE", _chrBitRate, sizeof(_chrBitRate))) {
2177 _ulBitRate=atol(_chrBitRate);
2178 }
2179 else {
2180 //SysWriteToTrapLog("No EA for %s\n", _wpQueryTitle(somSelf));
2181 bReRead=TRUE;
2182 }
2183 /* Get audiotrack info from EA */
2184 if( (pByte=_wpAllocMem(somSelf, MAX_EA_SIZE, &ulError))!=NULLHANDLE)
2185 {
2186 _pszName=_readTrackInfoIntoMem(somSelf, "MMTRACKNAME" , pByte, MAX_EA_SIZE);
2187 _pszArtist=_readTrackInfoIntoMem(somSelf, "MMARTIST" , pByte, MAX_EA_SIZE);
2188 _pszAlbum=_readTrackInfoIntoMem(somSelf, "MMALBUM" , pByte, MAX_EA_SIZE);
2189 _pszYear=_readTrackInfoIntoMem(somSelf, "MMYEAR" , pByte, MAX_EA_SIZE);
2190 _pszComment=_readTrackInfoIntoMem(somSelf, "MMCOMMENT" , pByte, MAX_EA_SIZE);
2191 _pszGenre=_readTrackInfoIntoMem(somSelf, "MMGENRE" , pByte, MAX_EA_SIZE);
2192 _wpFreeMem(somSelf, pByte);
2193 }
2194
2195#if 0
2196 cwGetStringFromEA(somSelf, "MMTRACKNAME" , _id3Name, sizeof(_id3Name));
2197 cwGetStringFromEA(somSelf, "MMARTIST" , _id3Artist, sizeof(_id3Artist));
2198 cwGetStringFromEA(somSelf, "MMALBUM" , _id3Album, sizeof(_id3Album));
2199 cwGetStringFromEA(somSelf, "MMYEAR" , _id3Year, sizeof(_id3Year));
2200 cwGetStringFromEA(somSelf, "MMCOMMENT" , _id3Comment, sizeof(_id3Comment));
2201 cwGetStringFromEA(somSelf, "MMGENRE" , _id3Genre, sizeof(_id3Genre));
2202
2203 sprintf(chrBuffer,"%d",_ulSampleRate);
2204 cwSaveStringToEA(somSelf, "MMSAMPLERATE", chrBuffer);
2205 sprintf(chrBuffer,"%d",_ulChannels);
2206 cwSaveStringToEA(somSelf, "MMCHANNELS", chrBuffer);
2207 sprintf(chrBuffer,"%d",_ulBPS);
2208 cwSaveStringToEA(somSelf, "MMBPS", chrBuffer);
2209 sprintf(chrBuffer,"%d",_ulPlaySecs);
2210 cwSaveStringToEA(somSelf, "MMPLAYTIME", chrBuffer);
2211 sprintf(chrBuffer,"%d",_ulPlayMsecs);
2212 cwSaveStringToEA(somSelf, "MMPLAYTIMEMS", chrBuffer);
2213#endif
2214
2215 if(_ulFileSize!=_wpQueryFileSize(somSelf))
2216 bReRead=TRUE; /* The filesize changed, somebody altered the audio file so reread the info */
2217
2218 if(!_ulFileSize)
2219 bReRead=FALSE;
2220 /* If filesize=0 do nothing because the file was just created and there's no contents yet */
2221
2222 //if(cwObjectIsOnCD(somSelf) && bReRead) {
2223 if(cwObjectIsOnInvalidDrive(somSelf)&& bReRead) {
2224 /* Only get audio info when file isn't on CD. This speeds up opening of folders on CDs filled with
2225 MP3s. Doesn't hurt because folders of CDs open in normal details view as default so the audio info
2226 isn't necessary. When opening the settings notebook the info is reread anyway. */
2227 bReRead=FALSE;
2228 }
2229 bIsMidi=_somIsA(somSelf, somGetSomClass("MMMIDI"));
2230 if(bReRead){
2231 /* Some info changed or isn't present. Reread the audio information */
2232
2233 /* Send the object pointer to the audio worker thread to read the audio info in the background.
2234 The audio worker thread was started during initialization of CWMMDataFile.
2235 */
2236 if((bIsMidi && !globalHaveTimidity) || !bIsMidi)
2237 WinPostMsg(__get_hwndAudioWorker(_CWMMDataFile) , WM_APPTERMINATENOTIFY, somSelf, 0);
2238
2239 /* Set default values into instance vars */
2240 if(bIsMidi)
2241 {
2242 /* MIDI files don't have this info. */
2243 strncpy(_chrSampleRate, "---", sizeof(_chrSampleRate));
2244 strncpy(_chrBPS, "---", sizeof(_chrBPS));
2245 }
2246 else
2247 {
2248 strncpy(_chrSampleRate, "??", sizeof(_chrSampleRate));
2249 strncpy(_chrBPS, "??", sizeof(_chrBPS));
2250 }
2251 strncpy(_chrBitRate, "---", sizeof(_chrBitRate));
2252 strncpy(_chrChannels, "??", sizeof(_chrChannels));
2253 strncpy(_chrPlayTime, "??:??", sizeof(_chrPlayTime));
2254
2255 _ulFileSize=0;
2256 _ulPlaySecs=0;
2257 _ulChannels=0;
2258 _ulSampleRate=0;
2259 _ulBitRate=0;
2260 _ulBPS=0;
2261 _ulPlayMsecs=0;
2262 _ulNumAudioBytes=0;
2263 }/* bReRead */
2264 else {
2265 /* No new reading necessary. Fill in the instance vars with the restored
2266 data. */
2267 sprintf(fName,"%d",_ulChannels);
2268 strncpy(_chrChannels, fName, sizeof(_chrChannels));
2269
2270 if(bIsMidi)
2271 strncpy(_chrSampleRate, "---", sizeof(_chrSampleRate));
2272 else {
2273 sprintf(fName,"%d", _ulSampleRate);
2274 strncpy(_chrSampleRate, fName, sizeof(_chrSampleRate));
2275 }
2276
2277 if(bIsMidi)
2278 strncpy(_chrBPS, "---", sizeof(_chrBPS));
2279 else {
2280 sprintf(fName,"%d",_ulBPS);
2281 strncpy(_chrBPS, fName, sizeof(_chrBPS));
2282 }
2283 /* Bitrate of MP3 files */
2284 if(!_ulBitRate)
2285 strncpy(_chrBitRate, "---", sizeof(_chrBitRate));
2286 else {
2287 sprintf(fName,"%d",_ulBitRate);
2288 strncpy(_chrBitRate, fName, sizeof(_chrBitRate));
2289 }
2290
2291 sprintf(fName,"%02d:%02d",_ulPlaySecs/60, _ulPlaySecs%60);
2292 strncpy(_chrPlayTime, fName, sizeof(_chrPlayTime));
2293 }
2294 _chrChannels[sizeof(_chrChannels)-1]=0;
2295 _chrSampleRate[sizeof(_chrSampleRate)-1]=0;
2296 _chrBPS[sizeof(_chrBPS)-1]=0;
2297 _chrPlayTime[sizeof(_chrPlayTime)-1]=0;
2298
2299 return bRc;
2300}
2301
2302#if 0
2303static void _printObjectInfo(WPObject * wpObject)
2304{
2305 char chrFileName[CCHMAXPATH];
2306 ULONG ulSize;
2307 PSZ pszID;
2308
2309 ulSize=sizeof(chrFileName);
2310 _wpQueryRealName(wpObject, chrFileName,&ulSize,TRUE);
2311 SysWriteToTrapLog("Filename: %s \n", chrFileName);
2312 SysWriteToTrapLog("Object is initialized: %d (TRUE/FALSE)\n", _wpIsObjectInitialized(wpObject));
2313 SysWriteToTrapLog("Object style: %d 0x%x\n", _wpQueryStyle(wpObject), _wpQueryStyle(wpObject));
2314 if((pszID=_wpQueryObjectID(wpObject))!=NULLHANDLE)
2315 SysWriteToTrapLog("Object ID: %s\n\n", pszID);
2316 else
2317 SysWriteToTrapLog("Object ID: None\n\n");
2318
2319}
2320#endif
2321
2322/*
2323 * The prototype for cwaudio_wpSaveState was replaced by the following prototype:
2324 */
2325SOM_Scope BOOL SOMLINK cwaudio_wpSaveState(MMAudio *somSelf)
2326{
2327 char chrBuffer[10];
2328
2329 MMAudioData *somThis = MMAudioGetData(somSelf);
2330 MMAudioMethodDebug("MMAudio","cwaudio_wpSaveState");
2331
2332
2333 if(_ulFileSize) {
2334 _wpSaveLong(somSelf, "CWAudio", KEY_TIME,_ulPlaySecs);
2335 _wpSaveLong(somSelf, "CWAudio", KEY_SAMPLERATE,_ulSampleRate);
2336 _wpSaveLong(somSelf, "CWAudio", KEY_CHANNELS,_ulChannels);
2337 _wpSaveLong(somSelf, "CWAudio", KEY_BPS,_ulBPS);
2338 _wpSaveLong(somSelf, "CWAudio", KEY_FILESIZE,_ulFileSize);
2339 _wpSaveLong(somSelf, "CWAudio", KEY_TIME_MS,_ulPlayMsecs);
2340 _wpSaveLong(somSelf, "CWAudio", KEY_NUM_AUDIO_BYTES, _ulNumAudioBytes);
2341 }
2342
2343#if 0
2344 _printObjectInfo(somSelf);
2345 cwSaveStringToEA(somSelf, "MMTRACKNAME", _pszName);
2346 if(_wpQueryStyle(somSelf)!=0x10000) {
2347 SysWriteToTrapLog("2 Template? %d \n", _wpQueryStyle(somSelf));
2348#endif
2349
2350 /* Save audio info in EA for other programs */
2351 cwSaveStringToEA(somSelf, "MMTRACKNAME", _pszName);
2352 cwSaveStringToEA(somSelf, "MMARTIST", _pszArtist);
2353 cwSaveStringToEA(somSelf, "MMALBUM", _pszAlbum);
2354 cwSaveStringToEA(somSelf, "MMCOMMENT", _pszComment);
2355 cwSaveStringToEA(somSelf, "MMYEAR", _pszYear);
2356 cwSaveStringToEA(somSelf, "MMGENRE", _pszGenre);
2357
2358
2359#if 0
2360 cwSaveStringToEA(somSelf, "MMTRACKNAME", _id3Name);
2361 cwSaveStringToEA(somSelf, "MMARTIST", _id3Artist);
2362 cwSaveStringToEA(somSelf, "MMALBUM", _id3Album);
2363 cwSaveStringToEA(somSelf, "MMCOMMENT", _id3Comment);
2364 cwSaveStringToEA(somSelf, "MMYEAR", _id3Year);
2365 cwSaveStringToEA(somSelf, "MMGENRE", _id3Genre);
2366#endif
2367
2368 sprintf(chrBuffer,"%d",_ulSampleRate);
2369 cwSaveStringToEA(somSelf, "MMSAMPLERATE", chrBuffer);
2370 sprintf(chrBuffer,"%d",_ulChannels);
2371 cwSaveStringToEA(somSelf, "MMCHANNELS", chrBuffer);
2372 sprintf(chrBuffer,"%d",_ulBPS);
2373 cwSaveStringToEA(somSelf, "MMBPS", chrBuffer);
2374 sprintf(chrBuffer,"%d",_ulPlaySecs);
2375 cwSaveStringToEA(somSelf, "MMPLAYTIME", chrBuffer);
2376 sprintf(chrBuffer,"%d",_ulPlayMsecs);
2377 cwSaveStringToEA(somSelf, "MMPLAYTIMEMS", chrBuffer);
2378 sprintf(chrBuffer,"%d",_ulNumAudioBytes);
2379 cwSaveStringToEA(somSelf, "MMNUMAUDIOBYTES", chrBuffer);
2380
2381 /* New with 0.2.7 */
2382 sprintf(chrBuffer,"%d",_ulBitRate);
2383 EASaveString(somSelf, "MMBITRATE", chrBuffer);
2384#if 0
2385 }
2386#endif
2387
2388#if 0
2389 cwGetStringFromEA(somSelf, "MMTRACKNAME" , chrBuf, sizeof(chrBuf));
2390 HlpWriteToTrapLog("Value: %s\n", chrBuf);
2391 cwGetStringFromEA(somSelf, "MMARTIST" , chrBuffer, sizeof(chrBuffer));
2392 cwGetStringFromEA(somSelf, "MMALBUM" , chrBuffer, sizeof(chrBuffer));
2393#endif
2394
2395#if 0
2396 /* Set .TYPE EA so the editor and the player are happy. */
2397 strncpy(chrBuf, _wpQueryType(somSelf), sizeof(chrBuf));
2398 chrBuf[sizeof(chrBuf)-1]=0;
2399
2400 if(!strstr(chrBuf, TYPE_DIGITALAUDIO)) {
2401 ulLength=strlen(chrBuf);
2402 if(ulLength) {
2403 if(ulLength+2+sizeof(TYPE_DIGITALAUDIO) < sizeof(chrBuf)) {
2404 strcat(chrBuf, "\n");
2405 strcat(chrBuf, TYPE_DIGITALAUDIO);
2406 }
2407 }
2408 else
2409 strcpy(chrBuf, TYPE_DIGITALAUDIO);
2410 /* Set .TYPE EA so the editor and the player are happy. */
2411 _wpSetType(somSelf, chrBuf , NULL);
2412 }
2413#endif
2414 //_wpSetType(somSelf, "Digital Audio" , NULL);
2415 return (MMAudio_parent_CWMMDataFile_wpSaveState(somSelf));
2416}
2417
2418/*
2419 FIXME:
2420
2421 This function isn't thread safe because of one global memory area. It is supposed to be
2422 called from the wpPopupMenu() method. This method can only be called once at
2423 a time, so that's not a problem. It may become a problem if this function is also
2424 called from somewhere else. The global mem pointer is used by the image class and the
2425 audio class.
2426
2427 This function inserts only write enabled IO procedures into the menu.
2428*/
2429BOOL insertAudioIOProcMenuItems( HWND hwndMenu )
2430{
2431 CHAR szBuffer[ sizeof( FOURCC ) + CCHMAXPATH + 4 ];
2432 MMFORMATINFO mmFormatInfo;
2433 PMMFORMATINFO pmmFormatInfoArray;
2434 ULONG ulReturnCode;
2435 LONG lFormatsRead;
2436 LONG index;
2437 LONG lBytesRead;
2438 HWND hwndSubMenu;
2439 MENUITEM mi;
2440 LONG lNumIOProcs;
2441
2442 if(g_pmmFormatInfoArray)
2443 free(g_pmmFormatInfoArray);
2444 g_pmmFormatInfoArray=NULLHANDLE;
2445
2446 memset( &mmFormatInfo,
2447 '\0',
2448 sizeof(MMFORMATINFO) );
2449
2450 mmFormatInfo.ulMediaType |= MMIO_MEDIATYPE_AUDIO;
2451 mmFormatInfo.ulFlags|=MMIO_CANWRITETRANSLATED;/* FIXME: CANWRITEUNTRANSLATED???*/
2452 ulReturnCode = mmioQueryFormatCount ( &mmFormatInfo,
2453 &lNumIOProcs,
2454 0,
2455 0 );
2456
2457 if( ulReturnCode != MMIO_SUCCESS )
2458 {
2459 /* Error - mmioQueryFormatCount failed. */
2460 return FALSE;
2461 }
2462
2463 /*
2464 * Allocate enough memory for n number of FormatInfo blocks
2465 */
2466 g_pmmFormatInfoArray = malloc (lNumIOProcs * sizeof( MMFORMATINFO ) );
2467 if( g_pmmFormatInfoArray == NULL )
2468 {
2469 /* Could not allocate enough memory for mmFormatInfo array. */
2470 return FALSE;
2471 }
2472
2473 /*
2474 * call mmioGetFormats to get info on the formats supported.
2475 */
2476 ulReturnCode = mmioGetFormats( &mmFormatInfo,
2477 lNumIOProcs,
2478 g_pmmFormatInfoArray,
2479 &lFormatsRead,
2480 0,
2481 0 );
2482 if( ulReturnCode != MMIO_SUCCESS )
2483 {
2484 /*
2485 * mmioGetFormats failed.
2486 */
2487 free(g_pmmFormatInfoArray);
2488 g_pmmFormatInfoArray=NULLHANDLE;
2489 return FALSE;
2490 }
2491
2492 if( lFormatsRead != lNumIOProcs )
2493 {
2494 /*
2495 * Error in MMIO - number of formats read in by
2496 * mmioGetFormats is not equal to number of formats
2497 * found by mmioQueryFormatCount.
2498 */
2499 free(g_pmmFormatInfoArray);
2500 g_pmmFormatInfoArray=NULLHANDLE;
2501 return FALSE;
2502 }
2503
2504 // Create Empty Submenu //
2505 hwndSubMenu=WinCreateWindow(hwndMenu,WC_MENU,"",0,
2506 0,0,0,0,
2507 hwndMenu,//Owner. If set, this window
2508 //is destroyed if owner is destroyed
2509 HWND_TOP,
2510 ID_MENU_CONVERT,//menuid
2511 NULL,NULL);
2512
2513 mi.iPosition=MIT_END;
2514 mi.afStyle=MIS_TEXT;//|MIS_SUBMENU;
2515 mi.id=ID_MENU_CONVERT;
2516 mi.afAttribute=NULLHANDLE;
2517 mi.hwndSubMenu=NULLHANDLE;//hwndSubMenu;
2518 mi.hItem=NULLHANDLE;
2519 mi.hwndSubMenu=hwndSubMenu;
2520
2521 if(!getMessage(szBuffer, IDSTR_MENU_CONVERT, sizeof(szBuffer), queryResModuleHandle(), HWND_DESKTOP))
2522 sprintf(szBuffer,"~Convert to");
2523 WinSendMsg(hwndMenu,MM_INSERTITEM,(MPARAM)&mi,
2524 (MPARAM)szBuffer);
2525
2526 pmmFormatInfoArray=g_pmmFormatInfoArray;
2527 for ( index = 0; index <lNumIOProcs; index++ )
2528 {
2529 ulReturnCode = mmioGetFormatName(pmmFormatInfoArray, szBuffer, &lBytesRead, 0L, 0L);
2530 if(ulReturnCode)
2531 {
2532 //SysWriteToTrapLog("IO-Proc 2: %s %u\n\n", szBuffer, ulReturnCode);
2533 continue;
2534 }
2535
2536 /* Insert NULL string terminator */
2537 *( szBuffer + lBytesRead ) = (CHAR)NULL;
2538
2539 /* Only write enabled IO procs are used in the convert menu.
2540 */
2541 if(pmmFormatInfoArray->ulFlags & MMIO_CANWRITETRANSLATED)
2542 {
2543 // HlpWriteToTrapLog("IO-Proc 2: %s\n\n", szBuffer);
2544 /* Add menu item */
2545 /* Fill the MENUITEM structure */
2546 mi.iPosition=MIT_END;
2547 mi.afStyle=MIS_TEXT|MIS_SUBMENU;
2548 mi.id=ID_ITEM_FIRSTCONVERT+index;/* Create menu id */
2549 mi.afAttribute=NULLHANDLE;
2550 mi.hwndSubMenu=NULLHANDLE;//hwndSubMenu;
2551 mi.hItem=NULLHANDLE;
2552 WinSendMsg(hwndSubMenu, MM_INSERTITEM,(MPARAM)&mi,
2553 (MPARAM)szBuffer);
2554 }
2555 /*
2556 * advance to next entry in mmFormatInfo array
2557 */
2558 pmmFormatInfoArray++;
2559 }
2560 return TRUE;
2561}
2562
2563
2564/*
2565 * The prototype for cwaudio_wpModifyPopupMenu was replaced by the following prototype:
2566 */
2567SOM_Scope BOOL SOMLINK cwaudio_wpModifyPopupMenu(MMAudio *somSelf,
2568 HWND hwndMenu,
2569 HWND hwndCnr,
2570 ULONG iPosition)
2571{
2572 BOOL rc;
2573
2574 MMAudioMethodDebug("MMAudio","cwaudio_wpModifyPopupMenu");
2575
2576 /* New Volume item */
2577 _wpInsertPopupMenuItems(somSelf, hwndMenu, 1, queryResModuleHandle(), ID_MENU_VOLUME, 1);
2578 /* Convert menu item */
2579
2580 /* Insert all known audio I/O procs */
2581 TRY_LOUD(AUDIO_INSERTPOPUPMENU) {
2582 insertAudioIOProcMenuItems( hwndMenu );
2583 }/* TRY_LOUD */
2584 CATCH(AUDIO_INSERTPOPUPMENU)
2585 {
2586 SysWriteToTrapLog("\nTrap occured in %s, file %s, near line %d.\n",
2587 __FUNCTION__, __FILE__, __LINE__);
2588 } END_CATCH;
2589
2590 if(WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP),__get_hwndObjectPlay(somSelf))) {
2591 if(_cwmmQueryTrackStatus(somSelf)==TRACK_STATUS_PAUSED)
2592 _wpInsertPopupMenuItems(somSelf, hwndMenu, 1, queryResModuleHandle(), ID_MENU_RESUME, 1);
2593 else
2594 _wpInsertPopupMenuItems(somSelf, hwndMenu, 1, queryResModuleHandle(), ID_MENU_PAUSE, 1);
2595 _wpInsertPopupMenuItems(somSelf, hwndMenu, 1, queryResModuleHandle(), ID_MENU_STOP, 1);
2596 }
2597 else
2598 {
2599 _wpInsertPopupMenuItems(somSelf, hwndMenu, 1, queryResModuleHandle(), ID_MENU_EDITOR, 1);
2600 _wpInsertPopupMenuItems(somSelf, hwndMenu, 1, queryResModuleHandle(), ID_MENU_PLAYER, 1);
2601 _wpInsertPopupMenuItems(somSelf, hwndMenu, 1, queryResModuleHandle(), ID_MENU_START, 1);
2602 }
2603 rc= (MMAudio_parent_CWMMDataFile_wpModifyPopupMenu(somSelf,
2604 hwndMenu,
2605 hwndCnr,
2606 iPosition));
2607 return rc;
2608}
2609
2610
2611/*
2612 * The prototype for cwaudio_wpMenuItemSelected was replaced by the following prototype:
2613 */
2614SOM_Scope BOOL SOMLINK cwaudio_wpMenuItemSelected(MMAudio *somSelf,
2615 HWND hwndFrame,
2616 ULONG ulMenuId)
2617{
2618 /* MMAudioData *somThis = MMAudioGetData(somSelf);*/
2619 MMAudioMethodDebug("MMAudio","cwaudio_wpMenuItemSelected");
2620
2621
2622 if(ulMenuId>=ID_ITEM_FIRSTCONVERT && ulMenuId<=ID_ITEM_FIRSTCONVERT+lNumIOProcs-1)
2623 {
2624 char chrEditor[CCHMAXPATH]={0};
2625 char chrParams[2*CCHMAXPATH]="\"";
2626 char *chrPtr=chrParams;
2627 ULONG ulSize;
2628 ULONG ulRc;
2629
2630 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "audioconverter", "", chrEditor,
2631 sizeof(chrEditor));
2632 chrPtr++;
2633 ulSize=sizeof(chrParams);
2634 _wpQueryRealName(somSelf, chrPtr, &ulSize, TRUE);
2635 strcat(chrPtr,"\" \"");
2636 chrPtr=strrchr(chrPtr, 0);
2637 if(mmioGetFormatName(&g_pmmFormatInfoArray[ulMenuId-ID_ITEM_FIRSTCONVERT], chrPtr,(LONG*) &ulSize, 0L, 0L))
2638 SysWriteToTrapLog("cwaudio_wpMenuItemSelected: %s\n\n", chrPtr);
2639 else
2640 *( chrPtr + ulSize ) = (CHAR)NULL;
2641 strcat(chrPtr,"\"");
2642
2643 if((ulRc=launchPMProg("", chrEditor, chrParams, somSelf, ulMenuId-ID_ITEM_FIRSTCONVERT))==NULLHANDLE) {
2644 /* Error */
2645 return TRUE;
2646 }
2647 return TRUE;
2648 }
2649
2650 switch(ulMenuId)
2651 {
2652 case ID_MENU_VOLUME:
2653 case ID_MENU_START:
2654 case ID_MENU_STOP:
2655 case ID_MENU_PAUSE:
2656 case ID_MENU_RESUME:
2657 case ID_MENU_PLAYER:
2658 case ID_MENU_EDITOR:
2659 case ID_ITEM_CONVERT:
2660 _wpViewObject(somSelf, WinWindowFromID(hwndFrame, FID_CLIENT), ulMenuId,0);
2661 return TRUE;
2662 default:
2663 break;
2664 }
2665 return (MMAudio_parent_CWMMDataFile_wpMenuItemSelected(somSelf,
2666 hwndFrame,
2667 ulMenuId));
2668}
2669
2670/*
2671 * The prototype for cwaudio_wpObjectReady was replaced by the following prototype:
2672 */
2673SOM_Scope void SOMLINK cwaudio_wpObjectReady(MMAudio *somSelf,
2674 ULONG ulCode, WPObject* refObject)
2675{
2676 MMAudioData *somThis = MMAudioGetData(somSelf);
2677 MMAudioMethodDebug("MMAudio","cwaudio_wpObjectReady");
2678
2679 MMAudio_parent_CWMMDataFile_wpObjectReady(somSelf, ulCode, refObject);
2680
2681 /* Set the type of this object to keep the MM player happy. */
2682 mmclsSetObjectType(somSelf);
2683
2684 if(_bNeedSaving)
2685 _wpSaveDeferred(somSelf);
2686}
2687
2688
2689/*
2690 * The prototype for cwaudio_wpSetup was replaced by the following prototype:
2691 */
2692SOM_Scope BOOL SOMLINK cwaudio_wpSetup(MMAudio *somSelf, PSZ pszSetupString)
2693{
2694 char buffer[MAX_EA_SIZE];
2695 ULONG bufferSize;
2696
2697 MMAudioData *somThis = MMAudioGetData(somSelf);
2698 MMAudioMethodDebug("MMAudio","cwaudio_wpSetup");
2699
2700 /* Setting volume while playing */
2701 bufferSize=sizeof(buffer);
2702 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOVOLUME, buffer, &bufferSize))
2703 {
2704 LONG l;
2705
2706 l=atol(buffer);
2707 if(l>100)
2708 l=100;
2709 if(l<0)
2710 l=0;
2711
2712 globalClassVolume=l;
2713 /* Now tell the running file if any */
2714 WinSendMsg(globalHwndObjectPlay, WM_APPTERMINATENOTIFY, MPFROMLONG(ACKEY_VOLUME), MPFROMP(globalObjectPlay));
2715 }
2716
2717 /* These are the old setup strings. They will be removed in the future */
2718 bufferSize=sizeof(buffer);
2719 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_AUDIOTRACKNAME, buffer, &bufferSize))
2720 {
2721 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_NAME);
2722 }
2723
2724 bufferSize=sizeof(buffer);
2725 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_AUDIOARTIST, buffer, &bufferSize))
2726 {
2727 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_ARTIST);
2728 }
2729
2730 bufferSize=sizeof(buffer);
2731 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_AUDIOALBUM, buffer, &bufferSize))
2732 {
2733 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_ALBUM);
2734 }
2735
2736 bufferSize=sizeof(buffer);
2737 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_AUDIOCOMMENT, buffer, &bufferSize))
2738 {
2739 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_COMMENT);
2740 }
2741
2742 bufferSize=sizeof(buffer);
2743 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_AUDIOGENRE, buffer, &bufferSize))
2744 {
2745 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_GENRE);
2746 }
2747
2748 bufferSize=sizeof(buffer);
2749 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_AUDIOYEAR, buffer, &bufferSize))
2750 {
2751 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_YEAR);
2752 }
2753
2754 bufferSize=sizeof(buffer);
2755 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_AUDIOPLAYTIME, buffer, &bufferSize))
2756 {
2757 int iPlaytime=atoi(buffer);
2758 if(iPlaytime<0)
2759 iPlaytime=0;
2760 _cwmmSetTrackInfo(somSelf, buffer, iPlaytime, IDINFO_PLAYTIME);
2761 }
2762
2763 /* Refresh */
2764 bufferSize=sizeof(buffer);
2765 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_REFRESH, buffer,&bufferSize))
2766 {
2767 _ulFileSize=1; /* Set filesize to 1 this will force a reread */
2768 /* Make sure MMIOMP3 doesn't take the time from the EA */
2769 cwSaveStringToEA(somSelf, "MMPLAYTIME", "");
2770 cwSaveStringToEA(somSelf, "MMPLAYTIMEMS", "");
2771
2772 /* The filesize changed, somebody altered the audio file so reread the info */
2773 // if(!cwObjectIsOnCD(somSelf)) {
2774 if(!cwObjectIsOnInvalidDrive(somSelf)) {
2775 /* Only get audio info when file isn't on CD. This speeds up opening of folders on CDs filled with
2776 MP3s. Doesn't hurt because folders of CDs open in normal details view as default so the audio info
2777 isn't necessary. When opening the settings notebook the info is reread anyway. */
2778
2779 /* Send the object pointer to the audio worker thread to read the audio info in the background. */
2780 WinPostMsg(__get_hwndAudioWorker(_CWMMDataFile) , WM_APPTERMINATENOTIFY, somSelf, 0);
2781 }
2782 _wpCnrRefreshDetails(somSelf);
2783 }
2784
2785 bufferSize=sizeof(buffer);
2786 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_COPYTAGTO, buffer, &bufferSize))
2787 {
2788 /* The caller requested to copy the tags from this audio file to another */
2789 PBYTE pByte;
2790 ULONG ul;
2791
2792 /* Length of instance var string can't be longer than MAX_EA_SIZE. See cwmmSetTrackInfo() */
2793 if((pByte=_wpAllocMem(somSelf, MAX_EA_SIZE+100, &ul))!=NULLHANDLE)
2794 {
2795 sprintf(pByte,"%s=%s;",SETUP_AUDIOTRACKNAME, _pszName);
2796 HlpSendCommandToObject( buffer, pByte);
2797
2798 sprintf(pByte,"%s=%s",SETUP_AUDIOARTIST, _pszArtist);
2799 HlpSendCommandToObject( buffer, pByte);
2800
2801 sprintf(pByte,"%s=%s",SETUP_AUDIOALBUM, _pszAlbum);
2802 HlpSendCommandToObject( buffer, pByte);
2803
2804 sprintf(pByte,"%s=%s",SETUP_AUDIOCOMMENT, _pszComment);
2805 HlpSendCommandToObject( buffer, pByte);
2806
2807 sprintf(pByte,"%s=%s",SETUP_AUDIOYEAR, _pszYear);
2808 HlpSendCommandToObject( buffer, pByte);
2809
2810 sprintf(pByte,"%s=%s",SETUP_AUDIOGENRE, _pszGenre);
2811 HlpSendCommandToObject( buffer, pByte);
2812 }
2813 }
2814
2815#if 0
2816 /* Old code using a static array. To be removed in V.0.2.8 */
2817 bufferSize=sizeof(buffer);
2818 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_COPYTAGTO, buffer, &bufferSize))
2819 {
2820 /* The caller requested to copy the tags from this audio file to another */
2821 char chrCommand[200];
2822
2823 sprintf(chrCommand,"%s=%s;",SETUP_AUDIOTRACKNAME, _id3Name);
2824 HlpSendCommandToObject( buffer, chrCommand);
2825
2826 sprintf(chrCommand,"%s=%s",SETUP_AUDIOARTIST, _id3Artist);
2827 HlpSendCommandToObject( buffer, chrCommand);
2828
2829 sprintf(chrCommand,"%s=%s",SETUP_AUDIOALBUM, _id3Album);
2830 HlpSendCommandToObject( buffer, chrCommand);
2831
2832 sprintf(chrCommand,"%s=%s",SETUP_AUDIOCOMMENT, _id3Comment);
2833 HlpSendCommandToObject( buffer, chrCommand);
2834
2835 sprintf(chrCommand,"%s=%s",SETUP_AUDIOYEAR, _id3Year);
2836 HlpSendCommandToObject( buffer, chrCommand);
2837
2838 sprintf(chrCommand,"%s=%s",SETUP_AUDIOGENRE, _id3Genre);
2839 HlpSendCommandToObject( buffer, chrCommand);
2840 }
2841#endif
2842
2843 /* The new MM* setup strings. These have a better naming */
2844 bufferSize=sizeof(buffer);
2845 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOTRACKNAME, buffer, &bufferSize))
2846 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_NAME);
2847
2848 bufferSize=sizeof(buffer);
2849 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOARTIST, buffer, &bufferSize))
2850 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_ARTIST);
2851
2852 bufferSize=sizeof(buffer);
2853 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOALBUM, buffer, &bufferSize))
2854 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_ALBUM);
2855
2856 bufferSize=sizeof(buffer);
2857 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOCOMMENT, buffer, &bufferSize))
2858 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_COMMENT);
2859
2860 bufferSize=sizeof(buffer);
2861 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOGENRE, buffer, &bufferSize))
2862 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_GENRE);
2863
2864 bufferSize=sizeof(buffer);
2865 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOYEAR, buffer, &bufferSize))
2866 _cwmmSetTrackInfo(somSelf, buffer, 0, IDINFO_YEAR);
2867
2868 bufferSize=sizeof(buffer);
2869 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMAUDIOPLAYTIME, buffer, &bufferSize))
2870 {
2871 int iPlaytime=atoi(buffer);
2872 if(iPlaytime<0)
2873 iPlaytime=0;
2874 _cwmmSetTrackInfo(somSelf, buffer, iPlaytime, IDINFO_PLAYTIME);
2875 }
2876
2877 /* Refresh */
2878 bufferSize=sizeof(buffer);
2879 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMREFRESH, buffer,&bufferSize))
2880 {
2881 _ulFileSize=1; /* Set filesize to 1 this will force a reread */
2882 /* Make sure MMIOMP3 doesn't take the time from the EA */
2883 cwSaveStringToEA(somSelf, "MMPLAYTIME", "");
2884 cwSaveStringToEA(somSelf, "MMPLAYTIMEMS", "");
2885
2886 /* The filesize changed, somebody altered the audio file so reread the info */
2887 // if(!cwObjectIsOnCD(somSelf)) {
2888 if(!cwObjectIsOnInvalidDrive(somSelf)) {
2889 /* Only get audio info when file isn't on CD. This speeds up opening of folders on CDs filled with
2890 MP3s. Doesn't hurt because folders of CDs open in normal details view as default so the audio info
2891 isn't necessary. When opening the settings notebook the info is reread anyway. */
2892
2893 /* Send the object pointer to the audio worker thread to read the audio info in the background. */
2894 WinPostMsg(__get_hwndAudioWorker(_CWMMDataFile) , WM_APPTERMINATENOTIFY, somSelf, 0);
2895 }
2896 _wpCnrRefreshDetails(somSelf);
2897 }
2898
2899 bufferSize=sizeof(buffer);
2900 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMCOPYTAGTO, buffer, &bufferSize))
2901 {
2902 /* The caller requested to copy the tags from this audio file to another */
2903 PBYTE pByte;
2904 ULONG ul;
2905
2906 /* Length of instance var string can't be longer than MAX_EA_SIZE. See cwmmSetTrackInfo() */
2907 if((pByte=_wpAllocMem(somSelf, MAX_EA_SIZE+100, &ul))!=NULLHANDLE)
2908 {
2909 if(_pszName) { /* Prevent inserting of (null) into the EA. (null) will be inserted by sprintf() */
2910 sprintf(pByte,"%s=%s;",SETUP_MMAUDIOTRACKNAME, _pszName);
2911 HlpSendCommandToObject( buffer, pByte);
2912 }
2913 if(_pszArtist) { /* Prevent inserting of (null) into the EA. (null) will be inserted by sprintf() */
2914 sprintf(pByte,"%s=%s",SETUP_MMAUDIOARTIST, _pszArtist);
2915 HlpSendCommandToObject( buffer, pByte);
2916 }
2917 if(_pszAlbum) { /* Prevent inserting of (null) into the EA. (null) will be inserted by sprintf() */
2918 sprintf(pByte,"%s=%s",SETUP_MMAUDIOALBUM, _pszAlbum);
2919 HlpSendCommandToObject( buffer, pByte);
2920 }
2921 if(_pszComment) { /* Prevent inserting of (null) into the EA. (null) will be inserted by sprintf() */
2922 sprintf(pByte,"%s=%s",SETUP_MMAUDIOCOMMENT, _pszComment);
2923 HlpSendCommandToObject( buffer, pByte);
2924 }
2925 if(_pszYear) { /* Prevent inserting of (null) into the EA. (null) will be inserted by sprintf() */
2926 sprintf(pByte,"%s=%s",SETUP_MMAUDIOYEAR, _pszYear);
2927 HlpSendCommandToObject( buffer, pByte);
2928 }
2929 if(_pszGenre) { /* Prevent inserting of (null) into the EA. (null) will be inserted by sprintf() */
2930 sprintf(pByte,"%s=%s",SETUP_MMAUDIOGENRE, _pszGenre);
2931 HlpSendCommandToObject( buffer, pByte);
2932 }
2933 }
2934 }
2935
2936#if 0
2937 /* Old code using a static array. To be removed in V0.2.8 */
2938 bufferSize=sizeof(buffer);
2939 if(_wpScanSetupString(somSelf, pszSetupString, SETUP_MMCOPYTAGTO, buffer, &bufferSize))
2940 {
2941 /* The caller requested to copy the tags from this audio file to another */
2942 char chrCommand[200];
2943
2944 sprintf(chrCommand,"%s=%s;",SETUP_MMAUDIOTRACKNAME, _id3Name);
2945 HlpSendCommandToObject( buffer, chrCommand);
2946
2947 sprintf(chrCommand,"%s=%s",SETUP_MMAUDIOARTIST, _id3Artist);
2948 HlpSendCommandToObject( buffer, chrCommand);
2949
2950 sprintf(chrCommand,"%s=%s",SETUP_MMAUDIOALBUM, _id3Album);
2951 HlpSendCommandToObject( buffer, chrCommand);
2952
2953 sprintf(chrCommand,"%s=%s",SETUP_MMAUDIOCOMMENT, _id3Comment);
2954 HlpSendCommandToObject( buffer, chrCommand);
2955
2956 sprintf(chrCommand,"%s=%s",SETUP_MMAUDIOYEAR, _id3Year);
2957 HlpSendCommandToObject( buffer, chrCommand);
2958
2959 sprintf(chrCommand,"%s=%s",SETUP_MMAUDIOGENRE, _id3Genre);
2960 HlpSendCommandToObject( buffer, chrCommand);
2961 }
2962#endif
2963
2964 return (MMAudio_parent_CWMMDataFile_wpSetup(somSelf, pszSetupString));
2965}
2966
2967
2968/*
2969 * wpSetTitle : override;
2970 * wpQueryRealName : override;
2971 * wpQueryTitle : override;
2972 * wpRefresh : override;
2973 */
2974
2975SOM_Scope HWND SOMLINK cwaudio_wpOpen(MMAudio *somSelf, HWND hwndCnr,
2976 ULONG ulView, ULONG param)
2977{
2978 ULONG ulRc;
2979
2980 /* CWAudioData *somThis = CWAudioGetData(somSelf);*/
2981 /* CWMMDataFileData *somThis = CWMMDataFileGetData(somSelf); */
2982 MMAudioMethodDebug("MMAudio","cwaudio_wpOpen");
2983
2984 switch(ulView)
2985 {
2986 case ID_MENU_START:
2987 {
2988 if(iRunningAudioFiles<MAX_AUDIOFILE_STARTS) {
2989
2990 /* Another audio file running */
2991 iRunningAudioFiles++;
2992
2993 __set_ulPreviousView(somSelf, _wpQueryDefaultView(somSelf));/* Save the view set by the user */
2994 _cwmmPlayTrack(somSelf, hwndCnr, TRUE); /* Start playing*/
2995 _wpSetDefaultView(somSelf, ID_MENU_STOP); /* Set new view so doubleclick stops the playing. */
2996 }
2997 return NULLHANDLE;
2998 }
2999 case ID_MENU_STOP:
3000 {
3001 _cwmmPlayTrack(somSelf, hwndCnr, FALSE); /* Stop playing */
3002 _wpSetDefaultView(somSelf, __get_ulPreviousView(somSelf)); /* Restore the user view */
3003 return NULLHANDLE;
3004 }
3005 case ID_MENU_PAUSE:
3006 {
3007 _cwmmPauseTrack(somSelf, hwndCnr, ACKEY_PAUSE);
3008 return NULLHANDLE;
3009 }
3010 case ID_MENU_RESUME:
3011 {
3012 _cwmmPauseTrack(somSelf, hwndCnr, ACKEY_RESUME);
3013 return NULLHANDLE;
3014 }
3015 case ID_MENU_PLAYER:
3016 /*case 0xbbe5: Player */
3017 {
3018 char chrPlayer[CCHMAXPATH]={0};
3019 char chrParams[CCHMAXPATH+2]="\"";
3020 char chrTitle[50];
3021 char *chrPtr=chrParams;
3022 ULONG ulSize;
3023
3024 /* Build path for the audio player app */
3025 sprintf(chrPlayer, "%s\\bin\\%s", chrInstallDir, "mmplayer.exe");
3026
3027 /* The user may override the audio player using a setting in the ini. Default is using the
3028 provided one.
3029 */
3030 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "audioplayer", chrPlayer, chrPlayer,sizeof(chrPlayer));
3031 chrPtr++;
3032 ulSize=sizeof(chrParams)-2;
3033 _wpQueryRealName(somSelf, chrPtr, &ulSize, TRUE); /* Add filename */
3034 strcat(chrPtr,"\"");
3035
3036 /* Get the Title for the window list */
3037 if(!getMessage(chrTitle, IDSTR_AUDPLAYERTITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3038 strcpy(chrTitle, "Player");
3039
3040 if((ulRc=launchPMProg(chrTitle, chrPlayer, chrParams, somSelf, ulView))==NULLHANDLE) {
3041 break;
3042 }
3043 return NULLHANDLE;
3044 }
3045 case ID_MENU_VOLUME:
3046 {
3047 char chrVolume[CCHMAXPATH]={0};
3048 char chrTitle[100]={0};
3049 char chrParam[CCHMAXPATH]="\"";
3050 ULONG ulRc;
3051
3052 sprintf(chrVolume, "%s\\bin\\classvol.exe", queryInstallDir());
3053
3054 ulRc=sizeof(chrParam);
3055 _wpQueryRealName(somSelf,chrParam+1, &ulRc, TRUE);
3056 strcat(chrParam,"\"");
3057 /* Get the Title for the window list */
3058 if(!getMessage(chrTitle, IDSTR_VOLUMETITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3059 strcpy(chrTitle, "Volume");
3060
3061 if((ulRc=launchPMProg(chrTitle, chrVolume, chrParam, somSelf, ID_MENU_VOLUME))==0)
3062 return NULLHANDLE;
3063
3064#if 0
3065 HOBJECT hObject;
3066 if((hObject=WinQueryObject("<MMPM2_MMVOLUME>"))!=NULLHANDLE)
3067 WinOpenObject(hObject, OPEN_DEFAULT, TRUE);
3068#endif
3069 return NULLHANDLE;
3070 }
3071 case ID_MENU_EDITOR:
3072 /* case 0xbc0d: Editor */
3073 {
3074 char chrPlayer[CCHMAXPATH]={0};
3075 char chrParams[CCHMAXPATH+10]="-e \"";
3076 char chrTitle[50];
3077 char *chrPtr=chrParams;
3078 ULONG ulSize;
3079
3080 /*
3081 Check if the user specified another audio editor.
3082 */
3083 if(!PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "audioeditor", NULLHANDLE, chrPlayer,sizeof(chrPlayer)))
3084 /* No user setting. Use default ab.exe copied by the installation program to another location. IF this setting is missing
3085 try the app from the path. */
3086 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "ab", "ab.exe", chrPlayer,sizeof(chrPlayer));
3087
3088 chrPtr+=4;
3089 ulSize=sizeof(chrParams)-2;
3090 _wpQueryRealName(somSelf, chrPtr, &ulSize, TRUE);
3091 strcat(chrPtr,"\"");
3092
3093 if(!getMessage(chrTitle, IDSTR_AUDEDITORTITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3094 strcpy(chrTitle, "Editor");
3095
3096 if((ulRc=launchPMProg( chrTitle, chrPlayer, chrParams, somSelf, ulView))==NULLHANDLE) {
3097 break;
3098 }
3099
3100 return NULLHANDLE;
3101 }
3102#if 0
3103 /*
3104 FIXME:
3105 Moved this to wpMenuItemSelected(). Should be moved back later.
3106 */
3107 case 0xb4dd: /* Convert */
3108 {
3109 char chrPlayer[CCHMAXPATH]={0};
3110 char chrParams[CCHMAXPATH+2]="\"";
3111 char *chrPtr=chrParams;
3112 ULONG ulSize;
3113
3114 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "audioconverter", "", chrPlayer,sizeof(chrPlayer));
3115 chrPtr++;
3116 ulSize=sizeof(chrParams)-2;
3117 _wpQueryRealName(somSelf, chrPtr, &ulSize, TRUE);
3118 strcat(chrPtr,"\"");
3119 if((ulRc=launchPMProg("Spieler", chrPlayer, chrParams, somSelf, ulView))==NULLHANDLE) {
3120 break;
3121 }
3122 return NULLHANDLE;
3123 }
3124#endif
3125 default:
3126 break;
3127 }
3128 return (MMAudio_parent_CWMMDataFile_wpOpen(somSelf, hwndCnr, ulView, param));
3129}
3130
3131
3132SOM_Scope void SOMLINK cwaudio_wpInitData(MMAudio *somSelf)
3133{
3134 MMAudioData *somThis = MMAudioGetData(somSelf);
3135 MMAudioMethodDebug("MMAudio","cwaudio_wpInitData");
3136
3137 MMAudio_parent_CWMMDataFile_wpInitData(somSelf);
3138 /* Flag to mark we haven't yet the audio size. The size will be read from the
3139 EAs (to circumvent the IO proc file scanning) or by checking the file using
3140 IO procs when the file was altered. */
3141 _ulFileSize=1;
3142
3143 /* This proc handles the start/stop/resume commands for audio objects.
3144 Playing takes place on a separate thread with an object window and this proc used
3145 for communicating. */
3146 _cwmmSetObjWindowProc(somSelf, &playObjectProc);
3147}
3148
3149/*
3150 This function checks all the installed audio IO procs if one of them can handle the
3151 audio file with the given extension. Only write enabled IO procs are accepted because
3152 we use this function to determine if we should create a template for the audio class.
3153 */
3154static BOOL checkForWriteEnabledAudioIOProc(char * chrExt)
3155{
3156 CHAR szBuffer[ sizeof( FOURCC ) + CCHMAXPATH + 4 ];
3157 MMFORMATINFO mmFormatInfo;
3158 PMMFORMATINFO pmmFormatInfoArray;
3159 void * memPtr;
3160 ULONG ulReturnCode;
3161 LONG lFormatsRead;
3162 LONG index;
3163 LONG lBytesRead;
3164 LONG lNumIOProcs;
3165
3166 memset( &mmFormatInfo,
3167 '\0',
3168 sizeof(MMFORMATINFO) );
3169
3170 mmFormatInfo.ulMediaType |= MMIO_MEDIATYPE_AUDIO;
3171 mmFormatInfo.ulFlags|=MMIO_CANWRITETRANSLATED;
3172 ulReturnCode = mmioQueryFormatCount ( &mmFormatInfo,
3173 &lNumIOProcs,
3174 0,
3175 0 );
3176
3177 if( ulReturnCode != MMIO_SUCCESS )
3178 {
3179 /*
3180 * Error - mmioQueryFormatCount failed.
3181 */
3182 return FALSE;
3183 }
3184
3185 /*
3186 * Allocate enough memory for n number of FormatInfo blocks
3187 */
3188 pmmFormatInfoArray = malloc (lNumIOProcs * sizeof( MMFORMATINFO ) );
3189 memPtr=pmmFormatInfoArray;
3190 if( pmmFormatInfoArray == NULL )
3191 {
3192 /*
3193 * Could not allocate enough memory for mmFormatInfo array.
3194 */
3195 return FALSE;
3196 }
3197
3198 /*
3199 * call mmioGetFormats to get info on the formats supported.
3200 */
3201 ulReturnCode = mmioGetFormats( &mmFormatInfo,
3202 lNumIOProcs,
3203 pmmFormatInfoArray,
3204 &lFormatsRead,
3205 0,
3206 0 );
3207 if( ulReturnCode != MMIO_SUCCESS )
3208 {
3209 /*
3210 * mmioGetFormats failed.
3211 */
3212 free(pmmFormatInfoArray);
3213 return FALSE;
3214 }
3215
3216 if( lFormatsRead != lNumIOProcs )
3217 {
3218 /*
3219 * Error in MMIO - number of formats read in by
3220 * mmioGetFormats is not equal to number of formats
3221 * found by mmioQueryFormatCount.
3222 */
3223 free(pmmFormatInfoArray);
3224 return FALSE;
3225 }
3226
3227 for ( index = 0; index <lNumIOProcs; index++ )
3228 {
3229 if(mmioGetFormatName(pmmFormatInfoArray, szBuffer, &lBytesRead, 0L, 0L))
3230 {
3231 //SysWriteToTrapLog("checkForWriteEnabledAudioIOProc: %s\n\n", szBuffer);
3232 continue;
3233 }
3234
3235 /* Insert NULL string terminator */
3236 *( szBuffer + lBytesRead ) = (CHAR)NULL;
3237
3238 if(pmmFormatInfoArray->ulFlags & MMIO_CANWRITETRANSLATED)
3239 {
3240 //if(pmmFormatInfoArray->fccIOProc==mmioStringToFOURCC(chr, MMIO_TOUPPER))
3241 //HlpWriteToTrapLog("%s --- %x %x %s\n",szBuffer, pmmFormatInfoArray->fccIOProc, mmioStringToFOURCC(chrType, MMIO_TOUPPER),
3242 // pmmFormatInfoArray->szDefaultFormatExt);
3243 if(strstr(chrExt, pmmFormatInfoArray->szDefaultFormatExt)) {
3244 // HlpWriteToTrapLog("******* Ext given: %s IO-Proc: %s\n", chrExt, pmmFormatInfoArray->szDefaultFormatExt);
3245 free(memPtr);
3246 return TRUE;
3247 }
3248 }
3249 /*
3250 * advance to next entry in mmFormatInfo array
3251 */
3252 pmmFormatInfoArray++;
3253 }
3254 free(memPtr);
3255 return FALSE;
3256}
3257
3258/*
3259 * wpCreateShadowObject : override;
3260 */
3261
3262SOM_Scope void SOMLINK cwaudio_wpUnInitData(MMAudio *somSelf)
3263{
3264 MMAudioData *somThis = MMAudioGetData(somSelf);
3265 MMAudioMethodDebug("MMAudio","cwaudio_wpUnInitData");
3266
3267 if(_pszName)
3268 _wpFreeMem(somSelf, _pszName);
3269
3270 if(_pszArtist)
3271 _wpFreeMem(somSelf, _pszArtist);
3272
3273 if(_pszAlbum)
3274 _wpFreeMem(somSelf, _pszAlbum);
3275
3276 if(_pszComment)
3277 _wpFreeMem(somSelf, _pszComment);
3278
3279 if(_pszYear)
3280 _wpFreeMem(somSelf, _pszYear);
3281
3282 if(_pszGenre)
3283 _wpFreeMem(somSelf, _pszGenre);
3284
3285 MMAudio_parent_CWMMDataFile_wpUnInitData(somSelf);
3286}
3287
3288
3289/*
3290 Only templates for write enabled audio IO procs are created in this method.
3291 */
3292SOM_Scope BOOL SOMLINK cwaudioM_wpclsCreateDefaultTemplates(M_MMAudio *somSelf,
3293 WPObject* Folder)
3294{
3295 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsCreateDefaultTemplates");
3296
3297 //HlpWriteToTrapLog("Classtitle: %s, Type: %s\n",_wpclsQueryTitle(somSelf), _wpclsQueryInstanceType(somSelf));
3298 if(checkForWriteEnabledAudioIOProc( _wpclsQueryInstanceFilter(somSelf))) {
3299 /* A write enabled IO proc was found, create the template. */
3300 mmclsCreateTheDefaultTemplate(somSelf, Folder);
3301 return TRUE; /* Tell the WPS template created*/
3302 }
3303
3304 return TRUE; /* We created the template or don't want to have one */
3305}
3306
3307
3308SOM_Scope PSZ SOMLINK cwaudioM_wpclsQueryInstanceType(M_MMAudio *somSelf)
3309{
3310 /* M_MMAudioData *somThis = M_MMAudioGetData(somSelf); */
3311 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryInstanceType");
3312
3313 return TYPE_DIGITALAUDIO;
3314}
3315
3316SOM_Scope PSZ SOMLINK cwaudioM_wpclsQueryInstanceFilter(M_MMAudio *somSelf)
3317{
3318 /* M_MMAudioData *somThis = M_MMAudioGetData(somSelf); */
3319 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryInstanceFilter");
3320
3321 /* The list of additional extensions is built in wpclsInitData().
3322
3323 FIXME
3324 This is a static list read in only once during startup.
3325 Should probably be changed later on.
3326 */
3327 return chrMMAudioExt;
3328 /* return (M_MMAudio_parent_M_CWMMDataFile_wpclsQueryInstanceFilter(somSelf)); */
3329}
3330
3331/*
3332 * The prototype for cwaudioM_wpclsQueryDetailsInfo was replaced by the following prototype:
3333 */
3334SOM_Scope ULONG SOMLINK cwaudioM_wpclsQueryDetailsInfo(M_MMAudio *somSelf,
3335 PCLASSFIELDINFO* ppClassFieldInfo,
3336 PULONG pSize)
3337{
3338 ULONG cParentColumns;
3339 PCLASSFIELDINFO pCfi;
3340 int i;
3341
3342 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3343 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryDetailsInfo");
3344
3345 cParentColumns= (M_MMAudio_parent_M_CWMMDataFile_wpclsQueryDetailsInfo(somSelf,
3346 ppClassFieldInfo,
3347 pSize));
3348 if(pSize)
3349 *pSize+=sizeof(AUDIODETAILS);
3350
3351 if(ppClassFieldInfo)
3352 {
3353 if(*ppClassFieldInfo)
3354 {
3355 pCfi=*ppClassFieldInfo;
3356 for(i=0; i<cParentColumns;i++)
3357 pCfi=(pCfi->pNextFieldInfo ? pCfi->pNextFieldInfo: pCfi);
3358
3359 pCfi->pNextFieldInfo=cfiFieldInfo;
3360 }
3361 else
3362 *ppClassFieldInfo=cfiFieldInfo;
3363 }
3364 return (cParentColumns+NUM_AUDIO_FIELDS);
3365}
3366
3367
3368/*
3369 * The prototype for cwaudioM_wpclsQueryTitle was replaced by the following prototype:
3370 */
3371SOM_Scope PSZ SOMLINK cwaudioM_wpclsQueryTitle(M_MMAudio *somSelf)
3372{
3373 static char chrTitle[30]={0};
3374
3375 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryTitle");
3376
3377 if(chrTitle[0]==0)
3378 if(!getMessage(chrTitle, IDSTR_CWAUDIOTITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3379 strcpy(chrTitle, CLSTITLE_DIGITALAUDIO);
3380
3381 return chrTitle;
3382}
3383
3384/*
3385 Initialize the MMAudio class.
3386 */
3387SOM_Scope void SOMLINK cwaudioM_wpclsInitData(M_MMAudio *somSelf)
3388{
3389 PCLASSFIELDINFO pCfi;
3390 USHORT i;
3391 static BOOL bGotAudioExt=FALSE;
3392
3393 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3394 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsInitData");
3395
3396 /*
3397 Get extensions of additional audio procs. These extensions may be specified by
3398 newly installed IO procs in MMPM2.INI or by using the Multimedia setup. For
3399 example the MMIOMP3 procedure for reading MP3 files adds the MP3 extension this
3400 way to the system. Extensions already handled by a specialized class will be
3401 filtered in the called REXX script e.g. MP3 so only unknown extensions end up here.
3402
3403 Strangely enough wpclsQueryInstanceFilter() is called during wpclsInitData() so
3404 we query the extensions here before calling the parent.
3405
3406 FIXME:
3407 The check is only done once during initialization. This is a little annoyance for
3408 the user because new extension specified in the settings will only be picked up
3409 on next WPS start.
3410 */
3411 if(!bGotAudioExt)
3412 {
3413 char chrTimidity[4];
3414 getStringFromRexxScript("audioext.rx", chrMMAudioExt, sizeof(chrMMAudioExt));
3415 bGotAudioExt=TRUE;
3416 getStringFromRexxScript("chktimid.rx", chrTimidity, sizeof(chrTimidity));
3417 // SysWriteToTrapLog("%s %d\n", chrTimidity, atol(chrTimidity));
3418 globalHaveTimidity=atol(chrTimidity);
3419 }
3420
3421 M_MMAudio_parent_M_CWMMDataFile_wpclsInitData(somSelf);
3422
3423 /* Get strings for details view titled from the ressource DLL */
3424 if(getMessage(chrPlayTime, IDSTR_PLAYTIME, sizeof(chrPlayTime), queryResModuleHandle(), HWND_DESKTOP))
3425 pszAudioColTitles[0]=chrPlayTime;
3426 /* New with 0.2.7 */
3427 if(getMessage(chrSampleRate, IDSTR_BITRATE, sizeof(chrBitRate), queryResModuleHandle(), HWND_DESKTOP))
3428 pszAudioColTitles[1]=chrBitRate;
3429
3430 if(getMessage(chrSampleRate, IDSTR_SAMPLERATE, sizeof(chrSampleRate), queryResModuleHandle(), HWND_DESKTOP))
3431 pszAudioColTitles[2]=chrSampleRate;
3432 if(getMessage(chrChannels, IDSTR_CHANNELS, sizeof(chrChannels), queryResModuleHandle(), HWND_DESKTOP))
3433 pszAudioColTitles[3]=chrChannels;
3434 if(getMessage(chrBPS, IDSTR_BPS, sizeof(chrBPS), queryResModuleHandle(), HWND_DESKTOP))
3435 pszAudioColTitles[4]=chrBPS;
3436
3437 if(getMessage(chrName, IDSTR_TITLE, sizeof(chrName), queryResModuleHandle(), HWND_DESKTOP))
3438 pszAudioColTitles[5]=chrName;
3439 if(getMessage(chrArtist, IDSTR_ARTIST, sizeof(chrArtist), queryResModuleHandle(), HWND_DESKTOP))
3440 pszAudioColTitles[6]=chrArtist;
3441 if(getMessage(chrAlbum, IDSTR_ALBUM, sizeof(chrAlbum), queryResModuleHandle(), HWND_DESKTOP))
3442 pszAudioColTitles[7]=chrAlbum;
3443 if(getMessage(chrYear, IDSTR_YEAR, sizeof(chrYear), queryResModuleHandle(), HWND_DESKTOP))
3444 pszAudioColTitles[8]=chrYear;
3445 if(getMessage(chrComment, IDSTR_COMMENT, sizeof(chrComment), queryResModuleHandle(), HWND_DESKTOP))
3446 pszAudioColTitles[9]=chrComment;
3447 if(getMessage(chrGenre, IDSTR_GENRE, sizeof(chrGenre), queryResModuleHandle(), HWND_DESKTOP))
3448 pszAudioColTitles[10]=chrGenre;
3449
3450
3451 /* Setup the static data for the details view */
3452 for(i=0,pCfi=cfiFieldInfo;i<NUM_AUDIO_FIELDS;i++,pCfi++)
3453 {
3454 memset((PCH)pCfi,0,sizeof(CLASSFIELDINFO));
3455
3456 pCfi->cb=sizeof(CLASSFIELDINFO);
3457 pCfi->flData=CFA_LEFT|CFA_SEPARATOR|CFA_FIREADONLY;
3458 pCfi->flTitle=CFA_CENTER|CFA_SEPARATOR|CFA_HORZSEPARATOR|CFA_STRING|CFA_FITITLEREADONLY;
3459 pCfi->pNextFieldInfo=pCfi+1;
3460 pCfi->pTitleData=(PVOID)pszAudioColTitles[i];
3461 pCfi->flCompare=COMPARE_SUPPORTED|SORTBY_SUPPORTED;
3462
3463 switch(i)
3464 {
3465 case 0: /* play time */
3466 pCfi->flData|=CFA_STRING;
3467 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszPlayTime));
3468 pCfi->ulLenFieldData=sizeof(PSZ);
3469 pCfi->DefaultComparison=CMP_EQUAL;
3470 break;
3471 case 1: /* Bitrate */ /* New with 0.2.7 */
3472 pCfi->flData|=CFA_STRING;
3473 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszBitRate));
3474 pCfi->ulLenFieldData=sizeof(PSZ);
3475 pCfi->DefaultComparison=CMP_EQUAL;
3476 break;
3477 case 2: /* Sample rate */
3478 pCfi->flData|=CFA_STRING;
3479 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszSampleRate));
3480 pCfi->ulLenFieldData=sizeof(PSZ);
3481 pCfi->DefaultComparison=CMP_EQUAL;
3482 break;
3483 case 3: /* Channels */
3484 pCfi->flData|=CFA_STRING;
3485 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszChannels));
3486 pCfi->ulLenFieldData=sizeof(PSZ);
3487 pCfi->DefaultComparison=CMP_EQUAL;
3488 break;
3489 case 4: /* BPS */
3490 pCfi->flData|=CFA_STRING;
3491 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszBPS));
3492 pCfi->ulLenFieldData=sizeof(PSZ);
3493 pCfi->DefaultComparison=CMP_EQUAL;
3494 break;
3495
3496 case 5:
3497 pCfi->flData|=CFA_STRING;
3498 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszName));
3499 pCfi->ulLenFieldData=sizeof(PSZ);
3500 pCfi->DefaultComparison=CMP_EQUAL;
3501 break;
3502 case 6:
3503 pCfi->flData|=CFA_STRING;
3504 pCfi->flData|=CFA_STRING;
3505 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszArtist));
3506 pCfi->ulLenFieldData=sizeof(PSZ);
3507 pCfi->DefaultComparison=CMP_EQUAL;
3508 break;
3509 case 7:
3510 pCfi->flData|=CFA_STRING;
3511 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszAlbum));
3512 pCfi->ulLenFieldData=sizeof(PSZ);
3513 pCfi->DefaultComparison=CMP_EQUAL;
3514 break;
3515 case 8:
3516 pCfi->flData|=CFA_STRING;
3517 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszYear));
3518 pCfi->ulLenFieldData=sizeof(PSZ);
3519 pCfi->DefaultComparison=CMP_EQUAL;
3520 break;
3521 case 9:
3522 pCfi->flData|=CFA_STRING;
3523 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszComment));
3524 pCfi->ulLenFieldData=sizeof(PSZ);
3525 pCfi->DefaultComparison=CMP_EQUAL;
3526 break;
3527 case 10:
3528 pCfi->flData|=CFA_STRING;
3529 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszGenre));
3530 pCfi->ulLenFieldData=sizeof(PSZ);
3531 pCfi->DefaultComparison=CMP_EQUAL;
3532 break;
3533
3534 }/* switch(i) */
3535 }/* for() */
3536 cfiFieldInfo[NUM_AUDIO_FIELDS].pNextFieldInfo=NULL;
3537
3538 /* Get name of help library from resource */
3539 if(!getMessage(chrHelpLibrary, IDSTR_HELPLIBRARY, sizeof(chrHelpLibrary),
3540 queryResModuleHandle(), HWND_DESKTOP))
3541 strcpy(chrHelpLibrary,"MMPARTS.HLP"); /* Fall back to default Warp hel library */
3542}
3543
3544
3545
3546
3547SOM_Scope void SOMLINK cwaudioM_wpclsUnInitData(M_MMAudio *somSelf)
3548{
3549 /* M_MMAudioData *somThis = M_MMAudioGetData(somSelf); */
3550 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsUnInitData");
3551
3552 M_MMAudio_parent_M_CWMMDataFile_wpclsUnInitData(somSelf);
3553}
3554
3555/*
3556 * The prototype for cwaudioM_wpclsQueryDefaultView was replaced by the following prototype:
3557 */
3558SOM_Scope ULONG SOMLINK cwaudioM_wpclsQueryDefaultView(M_MMAudio *somSelf)
3559{
3560 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3561 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryDefaultView");
3562
3563 /* Default view for audio objects is 'Start' so on doubleclick the playing starts
3564 immediately. */
3565
3566 return ID_MENU_START;
3567}
3568
3569/*
3570 * The prototype for cwaudioM_wpclsQueryIconData was replaced by the following prototype:
3571 */
3572SOM_Scope ULONG SOMLINK cwaudioM_wpclsQueryIconData(M_MMAudio *somSelf,
3573 PICONINFO pIconInfo)
3574{
3575 HMODULE hmod;
3576 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3577 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryIconData");
3578 /*
3579 We have our own icon.
3580 */
3581 hmod=queryModuleHandle();
3582 if(!hmod)
3583 return M_MMAudio_parent_M_CWMMDataFile_wpclsQueryIconData(somSelf, pIconInfo);
3584
3585 if (pIconInfo) {
3586 pIconInfo->fFormat = ICON_RESOURCE;
3587 pIconInfo->hmod = queryModuleHandle();
3588 pIconInfo->resid = ID_ICONCWAUDIOFILE;
3589 } /* endif */
3590
3591 return ( sizeof(ICONINFO) );
3592}
3593
3594
3595
3596MRESULT EXPENTRY audioWorkerProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
3597{
3598
3599 switch (msg)
3600 {
3601 case WM_APPTERMINATENOTIFY:
3602 {
3603 ULONG ulSize;
3604 char fName[CCHMAXPATH];
3605 char text[CCHMAXPATH];
3606 BOOL bContinue=FALSE;
3607 MMAudio *somSelf=(MMAudio*)mp1;
3608 WPObject *pLinkObj=NULLHANDLE;
3609 MMAudioData *somThis= MMAudioGetData(somSelf);
3610 ULONG ulLoop;
3611
3612 TRY_LOUD(AUDIO_WORKER) {
3613 for(;;) {
3614 ULONG rc;
3615 MMIOINFO mmio;
3616 HMMIO hmmio;
3617 MMAUDIOHEADER mmAudioHeader={0};
3618 LONG lBytesRead=0;
3619 char* pChar;
3620 ULONG ulFSize;
3621 BOOL bIsMidi=FALSE;
3622 WPFolder *wpFolder;
3623
3624 mmclsSetObjectType(somSelf);
3625
3626 if(!somIsObj(somSelf))
3627 break;
3628
3629 /* Don't check stream objects */
3630 if(somObjectIsA(somSelf, "MMAudioStream"))
3631 break;
3632 /* Don't check CD-Track objects */
3633 if(somObjectIsA(somSelf, "MMCDTrack"))
3634 break;
3635
3636 /* Check if object is inserted into a container. If not the folder was
3637 closed. */
3638 // if(!somObjectIsInsertedInContainer(somSelf))
3639 // break;
3640
3641 ulFSize=_wpQueryFileSize(somSelf);
3642 if(_ulFileSize==ulFSize)
3643 break; /* We already scanned this file */
3644
3645 /*
3646 @@CHANGE 0.2.8
3647
3648 Check if parent folder is closed. If yes, don't start file scanning.
3649
3650 @@CHANGE 0.2.9
3651
3652 Check if we have a shadow in an open folder.
3653
3654 */
3655
3656 wpFolder=_wpQueryFolder(somSelf);
3657 if(somIsObj(wpFolder)) {
3658 if(!_wpFindViewItem(wpFolder , VIEW_ANY, NULLHANDLE)) {
3659 PUSEITEM pUseItem;
3660 BOOL fOpenView=FALSE;
3661 /* Ok, our object isn't in an open folder, but we may have a shadow somewhere in an
3662 open folder. */
3663 for(pUseItem=_wpFindUseItem(somSelf, USAGE_LINK, NULL);pUseItem;
3664 pUseItem=_wpFindUseItem(somSelf, USAGE_LINK, pUseItem))
3665 {
3666 PLINKITEM pLI=(PLINKITEM)++pUseItem;
3667 pLinkObj=pLI->LinkObj; /* The awake shadow */
3668
3669 if(somIsObj(pLinkObj)) {
3670 wpFolder=_wpQueryFolder(pLinkObj);
3671 if(somIsObj(wpFolder)) {
3672 if(_wpFindViewItem(wpFolder , VIEW_ANY, NULLHANDLE)) {
3673 fOpenView=TRUE;
3674 break;
3675 }
3676 }/* somIsObj(wpFolder) */
3677 }
3678 }/* for() */
3679 if(!fOpenView)
3680 break;
3681 }
3682 }
3683
3684 /* Get file name */
3685 ulSize=sizeof(fName);
3686 if(!_wpQueryRealName(somSelf, fName, &ulSize, TRUE))
3687 break; /* Error */
3688
3689 /* Show status window */
3690 if((pChar=strrchr(fName, '\\'))!=NULLHANDLE) {
3691 HPS hps;
3692 ULONG ulWinTextLen;
3693 POINTL aptlPoints[TXTBOX_COUNT];
3694 SWP swp;
3695 ULONG ulCy;
3696 WPOINT pwpBorder;
3697
3698 HWND hwndClient=WinWindowFromID(__get_hwndStatus(_CWMMDataFile), FID_CLIENT);
3699
3700 sprintf(text,"%c:\\...%s",fName[0], pChar);
3701
3702 WinSetWindowText(hwndClient, text);
3703 ulWinTextLen=(ULONG)strlen(text); // Query text length
3704
3705 /* Calculate text size in pixel */
3706 hps=WinBeginPaint(hwndClient,(HPS)NULL,(PRECTL)NULL);
3707 GpiQueryTextBox(hps,ulWinTextLen,text,TXTBOX_COUNT,aptlPoints);
3708 WinEndPaint(hps);
3709
3710 if(WinSendMsg(__get_hwndStatus(_CWMMDataFile) ,WM_QUERYBORDERSIZE, MPFROMP(&pwpBorder), 0L))
3711 ulCy=pwpBorder.x*2;
3712 else
3713 ulCy=SV_CYBORDER*2; /* Safe default */
3714
3715 if(WinQueryWindowPos(WinWindowFromID(__get_hwndStatus(_CWMMDataFile), FID_TITLEBAR),&swp))
3716 {
3717 if(!swp.cy)
3718 if(!WinQueryWindowPos(WinWindowFromID(HWND_DESKTOP, FID_TITLEBAR), &swp))
3719 swp.cy=15;
3720 ulCy+=swp.cy;
3721 }
3722 else
3723 ulCy+=15;
3724
3725 WinSetWindowPos(__get_hwndStatus(_CWMMDataFile), HWND_TOP, 0,0,
3726 aptlPoints[TXTBOX_BOTTOMRIGHT].x-aptlPoints[TXTBOX_BOTTOMLEFT].x+18,
3727 aptlPoints[TXTBOX_TOPRIGHT].y-aptlPoints[TXTBOX_BOTTOMRIGHT].y+ulCy+4,
3728 SWP_SIZE|SWP_SHOW|SWP_ZORDER|SWP_DEACTIVATE);
3729 WinPostMsg(__get_hwndStatus(_CWMMDataFile), WM_APPTERMINATENOTIFY, 0,MPFROMLONG(1L));
3730 }
3731
3732 //#if 0
3733 /* This part obsolete?? */
3734 /* Get file name */
3735 ulSize=sizeof(fName);
3736 if(!_wpQueryRealName(somSelf, fName, &ulSize, TRUE))
3737 break;
3738 //#endif
3739
3740 if(!_somIsA(somSelf, somGetSomClass("MMMIDI")))
3741 {
3742 /* Check audio files */
3743 MP3OPTIONS mp3Opt={0}; /* Struct holding MP3 additional info */
3744 VORBISOPTIONS vorbisOpt={0};
3745
3746 PMP3OPTIONS returnedMP3Opts;
3747 PVORBISOPTIONS returnedVorbisOpts;
3748
3749 memset(&mmio,0, sizeof(mmio));
3750 mmio.ulFlags=MMIO_READ;
3751 mmio.ulTranslate=MMIO_TRANSLATEHEADER;
3752
3753 hmmio = mmioOpen(fName, &mmio, MMIO_READ);
3754 if(!hmmio)
3755 break;
3756
3757 /* The Quicktime IO-procs don't like any data in mmio.pExtraInfoStruct when calling
3758 mmioOpen(). But we need that if we want to have the bitrate of MP3 and Ogg. So the
3759 file is closed here and opened again with the FourCC set to MP3 or OGGS. So the Quicktime
3760 IO-procs will not be called.*/
3761 if(somObjectIsA(somSelf, "MMOGG"))
3762 {
3763 if(mmioFOURCC('O', 'G', 'G', 'S')==mmio.fccIOProc) {
3764 mmioClose(hmmio, 0);
3765
3766 memset(&mmio,0, sizeof(mmio));
3767 mmio.ulFlags=MMIO_READ;
3768 mmio.ulTranslate=MMIO_TRANSLATEHEADER;
3769 mmio.fccIOProc=mmioFOURCC('O', 'G', 'G', 'S');
3770 vorbisOpt.cookie = VORBIS_COOKIE;
3771 mmio.pExtraInfoStruct = &vorbisOpt;
3772 /*Now reopen */
3773 hmmio = mmioOpen(fName, &mmio, MMIO_READ);
3774 if(!hmmio)
3775 break;
3776 }
3777 }
3778 else if(somObjectIsA(somSelf, "MMMP3"))
3779 {
3780 if(mmioFOURCC('M', 'P', '3', ' ')==mmio.fccIOProc) {
3781 mmioClose(hmmio, 0);
3782
3783 memset(&mmio,0, sizeof(mmio));
3784 mmio.ulFlags=MMIO_READ;
3785 mmio.ulTranslate=MMIO_TRANSLATEHEADER;
3786 mmio.fccIOProc=mmioFOURCC('M', 'P', '3', ' ');
3787 /* For bitrate query of MP3 */
3788 mp3Opt.cookie = MP3_COOKIE;
3789 mmio.pExtraInfoStruct = &mp3Opt;
3790 /*Now reopen */
3791 hmmio = mmioOpen(fName, &mmio, MMIO_READ);
3792 if(!hmmio)
3793 break;
3794
3795 //SysWriteToTrapLog("%s reopened. mp3Opt.bitrate: %d\n", fName, mp3Opt.bitrate);
3796 }
3797 }
3798
3799 memset(&mmAudioHeader,0,sizeof(MMAUDIOHEADER));
3800 rc = mmioGetHeader(hmmio, &mmAudioHeader,sizeof(MMAUDIOHEADER),
3801 &lBytesRead, 0, 0);
3802
3803 if(rc!=MMIO_SUCCESS) {
3804 mmioClose(hmmio, 0);
3805 break;
3806 }
3807
3808 mmioClose(hmmio, 0);
3809
3810 /* Check if the object is still living. */
3811 if(!somIsObj(somSelf))
3812 break;
3813
3814 _ulBitRate=0;
3815 if(somObjectIsA(somSelf, "MMOGG")) {
3816 returnedVorbisOpts = (PVORBISOPTIONS)mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation;
3817 if(0 != returnedVorbisOpts && VORBIS_COOKIE == returnedVorbisOpts->cookie && 0 != returnedVorbisOpts->nominal_bitrate)
3818 _ulBitRate=returnedVorbisOpts->nominal_bitrate;
3819 }
3820 else if(somObjectIsA(somSelf, "MMMP3")) {
3821 returnedMP3Opts = (PMP3OPTIONS)mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation;
3822 if(0 != returnedMP3Opts && MP3_COOKIE == returnedMP3Opts->cookie && 0 != returnedMP3Opts->bitrate)
3823 _ulBitRate=returnedMP3Opts->bitrate;
3824 }
3825
3826 _ulChannels=mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels;
3827 _ulSampleRate=mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
3828 _ulBPS=mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample;
3829 _ulNumAudioBytes=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
3830 /* sprintf(fName,"%02d:%02d",mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes/
3831 mmAudioHeader.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec/60,
3832 mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes/
3833 mmAudioHeader.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec%60);*/
3834 if(mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS/1000) {
3835 _ulPlaySecs=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS/1000;
3836 _ulPlayMsecs=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS;
3837 }
3838 else {
3839 _ulPlaySecs=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes/
3840 mmAudioHeader.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec;
3841 _ulPlayMsecs=_ulPlaySecs*1000;
3842 }
3843 }/* _somIsA()*/
3844 else
3845 {
3846 /* The file is a midi file. Get audio information using MCI commands. */
3847 unsigned char chrCommand[CCHMAXPATH];
3848 char retMsg[20];
3849 APIRET rc;
3850 ULONG ulTime;
3851
3852 bIsMidi=TRUE;
3853
3854 /* Prevent Timidity crash */
3855 if(globalHaveTimidity)
3856 break;
3857
3858 /* open the file */
3859 sprintf(chrCommand,"open \"%s\" type SEQUENCER alias wave%p SHAREABLE wait",fName, somSelf);
3860 rc = mciSendString( chrCommand, retMsg, sizeof(retMsg), NULLHANDLE, 0);
3861 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
3862 break;
3863 }
3864
3865 /* Set time format */
3866 sprintf(chrCommand,"SET wave%p TIME FORMAT MILLISECONDS wait", somSelf);
3867 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3868 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
3869 /* close the file */
3870 sprintf(chrCommand,"close wave%p wait", somSelf);
3871 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3872 break;
3873 }
3874
3875 /* Get midi info */
3876 sprintf(chrCommand,"STATUS wave%p LENGTH WAIT", somSelf);
3877 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3878 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
3879 /* close the file */
3880 sprintf(chrCommand,"close wave%p wait", somSelf);
3881 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3882 break;
3883 }
3884 ulTime=atoi(retMsg);
3885 // HlpWriteToTrapLog("Midi-Time in ms: %d %s\n", ulTime, fName);
3886
3887 if(ulTime/1000) {
3888 _ulPlaySecs=ulTime/1000;
3889 _ulPlayMsecs=ulTime;
3890 }
3891 else {
3892 _ulPlaySecs=1;
3893 _ulPlayMsecs=_ulPlaySecs*1000;
3894 }
3895
3896 // HlpWriteToTrapLog("Midi-Time ulPlaySecs: %d\n", _ulPlaySecs);
3897 sprintf(chrCommand,"STATUS wave%p NUMBER OF TRACKS WAIT", somSelf);
3898 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3899 if((rc & 0x0000ffff)==MCIERR_SUCCESS) {
3900 _ulChannels=atoi(retMsg);
3901 // HlpWriteToTrapLog("Midi-Tracks: %d %s %s\n", _ulChannels, fName, retMsg);
3902 }
3903
3904 /* close the file */
3905 sprintf(chrCommand,"close wave%p wait", somSelf);
3906 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3907 }/* else is MMMIDI */
3908
3909 _ulFileSize=_wpQueryFileSize(somSelf);
3910 _bNeedSaving=TRUE;/* When the object is initialized the new instance data will be saved in wpObjectReady(). */
3911
3912 sprintf(fName,"%d",_ulChannels);
3913 strncpy(_chrChannels, fName, sizeof(_chrChannels));
3914 _chrChannels[sizeof(_chrChannels)-1]=0;
3915
3916 if(bIsMidi)
3917 strncpy(_chrSampleRate, "---", sizeof(_chrSampleRate));
3918 else {
3919 sprintf(fName,"%d", _ulSampleRate);
3920 strncpy(_chrSampleRate, fName, sizeof(_chrSampleRate));
3921 }
3922 _chrSampleRate[sizeof(_chrSampleRate)-1]=0;
3923
3924 if(!_ulBitRate)
3925 strncpy(_chrBitRate, "---", sizeof(_chrBitRate));
3926 else {
3927 sprintf(fName,"%d",_ulBitRate);
3928 strncpy(_chrBitRate, fName, sizeof(_chrBitRate));
3929 }
3930 _chrBitRate[sizeof(_chrBitRate)-1]=0;
3931
3932 if(bIsMidi)
3933 strncpy(_chrBPS, "---", sizeof(_chrBPS));
3934 else {
3935 sprintf(fName,"%d",_ulBPS);
3936 strncpy(_chrBPS, fName, sizeof(_chrBPS));
3937 }
3938 _chrBPS[sizeof(_chrBPS)-1]=0;
3939
3940 sprintf(fName,"%02d:%02d",_ulPlaySecs/60, _ulPlaySecs%60);
3941 strncpy(_chrPlayTime, fName, sizeof(_chrPlayTime));
3942 _chrPlayTime[sizeof(_chrPlayTime)-1]=0;
3943
3944 bContinue=TRUE;
3945 break;
3946 }/* for */
3947 }
3948 CATCH(AUDIO_WORKER)
3949 {
3950 SysWriteToTrapLog("\nTrap occured in %s, file %s, around line %d.\n",
3951 __FUNCTION__, __FILE__, __LINE__);
3952 SysWriteToTrapLog("Audio file: %s\n\n",
3953 fName);
3954 } END_CATCH;
3955
3956 /* Hide status window */
3957 WinPostMsg(__get_hwndStatus(_CWMMDataFile), WM_APPTERMINATENOTIFY, 0, 0L);
3958
3959 if(!bContinue)
3960 return (MRESULT)FALSE;
3961
3962 /* This Message was posted from wpRestore(). It's not allowed to call
3963 wpSaveDeferred() from there. The object must be initilized! This is important when
3964 creating objects from templates. So we wait for the object to be initialized.
3965 If it isn't initialized within 2s we quit. */
3966 ulLoop=0;
3967 while(!_wpIsObjectInitialized(somSelf) && ulLoop<40) {
3968 DosSleep(50);
3969 ulLoop++;
3970 }
3971 if(ulLoop<20)
3972 _wpSaveDeferred(somSelf);
3973 /* Now we have the audio info */
3974 _wpCnrRefreshDetails(somSelf);
3975 /*
3976 @@CHANGE 0.2.9
3977
3978 Also refresh shadows in containers. For now we only support one shadow but that doesn't is a problem
3979 because after the first shadow the linked object has queried the audio data and every other shadow
3980 that will be awaked can use that info without ending here. Only problem may be the user opens a lot
3981 of folders with shadows and we are not fast enough but I don't care at the momen ;-).
3982 */
3983 if(pLinkObj!=NULLHANDLE && somIsObj(pLinkObj)) /* The check on NULLHANDLE is very fast while somIsObj() needs
3984 quite some time. So we check for a valid object only if we
3985 can be quite sure we have an object (pointer!=NULLHANDLE). */
3986 _wpCnrRefreshDetails(pLinkObj);
3987 return (MRESULT) FALSE;
3988 }
3989 default:
3990 break;
3991 }
3992
3993 return WinDefWindowProc( hwnd, msg, mp1, mp2);
3994}
3995
Note: See TracBrowser for help on using the repository browser.