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

Last change on this file was 190, checked in by gyoung, 15 months ago

Add midiplayer ini key since ab.exe fails to play midi fles

File size: 155.2 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
117//BOOL 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 if(!_somIsA(somSelf, somGetSomClass("MMMIDI")))
3031 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "audioplayer", chrPlayer, chrPlayer,sizeof(chrPlayer));
3032 else
3033 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "midiplayer", chrPlayer, chrPlayer,sizeof(chrPlayer));
3034 chrPtr++;
3035 ulSize=sizeof(chrParams)-2;
3036 _wpQueryRealName(somSelf, chrPtr, &ulSize, TRUE); /* Add filename */
3037 strcat(chrPtr,"\"");
3038
3039 /* Get the Title for the window list */
3040 if(!getMessage(chrTitle, IDSTR_AUDPLAYERTITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3041 strcpy(chrTitle, "Player");
3042
3043 if((ulRc=launchPMProg(chrTitle, chrPlayer, chrParams, somSelf, ulView))==NULLHANDLE) {
3044 break;
3045 }
3046 return NULLHANDLE;
3047 }
3048 case ID_MENU_VOLUME:
3049 {
3050 char chrVolume[CCHMAXPATH]={0};
3051 char chrTitle[100]={0};
3052 char chrParam[CCHMAXPATH]="\"";
3053 ULONG ulRc;
3054
3055 sprintf(chrVolume, "%s\\bin\\classvol.exe", queryInstallDir());
3056
3057 ulRc=sizeof(chrParam);
3058 _wpQueryRealName(somSelf,chrParam+1, &ulRc, TRUE);
3059 strcat(chrParam,"\"");
3060 /* Get the Title for the window list */
3061 if(!getMessage(chrTitle, IDSTR_VOLUMETITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3062 strcpy(chrTitle, "Volume");
3063
3064 if((ulRc=launchPMProg(chrTitle, chrVolume, chrParam, somSelf, ID_MENU_VOLUME))==0)
3065 return NULLHANDLE;
3066
3067#if 0
3068 HOBJECT hObject;
3069 if((hObject=WinQueryObject("<MMPM2_MMVOLUME>"))!=NULLHANDLE)
3070 WinOpenObject(hObject, OPEN_DEFAULT, TRUE);
3071#endif
3072 return NULLHANDLE;
3073 }
3074 case ID_MENU_EDITOR:
3075 /* case 0xbc0d: Editor */
3076 {
3077 char chrPlayer[CCHMAXPATH]={0};
3078 char chrParams[CCHMAXPATH+10]="-e \"";
3079 char chrTitle[50];
3080 char *chrPtr=chrParams;
3081 ULONG ulSize;
3082
3083 /*
3084 Check if the user specified another audio editor.
3085 */
3086 if(!PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "audioeditor", NULLHANDLE, chrPlayer,sizeof(chrPlayer)))
3087 /* No user setting. Use default ab.exe copied by the installation program to another location. IF this setting is missing
3088 try the app from the path. */
3089 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "ab", "ab.exe", chrPlayer,sizeof(chrPlayer));
3090
3091 chrPtr+=4;
3092 ulSize=sizeof(chrParams)-2;
3093 _wpQueryRealName(somSelf, chrPtr, &ulSize, TRUE);
3094 strcat(chrPtr,"\"");
3095
3096 if(!getMessage(chrTitle, IDSTR_AUDEDITORTITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3097 strcpy(chrTitle, "Editor");
3098
3099 if((ulRc=launchPMProg( chrTitle, chrPlayer, chrParams, somSelf, ulView))==NULLHANDLE) {
3100 break;
3101 }
3102
3103 return NULLHANDLE;
3104 }
3105#if 0
3106 /*
3107 FIXME:
3108 Moved this to wpMenuItemSelected(). Should be moved back later.
3109 */
3110 case 0xb4dd: /* Convert */
3111 {
3112 char chrPlayer[CCHMAXPATH]={0};
3113 char chrParams[CCHMAXPATH+2]="\"";
3114 char *chrPtr=chrParams;
3115 ULONG ulSize;
3116
3117 PrfQueryProfileString(HINI_USERPROFILE, "CWMM", "audioconverter", "", chrPlayer,sizeof(chrPlayer));
3118 chrPtr++;
3119 ulSize=sizeof(chrParams)-2;
3120 _wpQueryRealName(somSelf, chrPtr, &ulSize, TRUE);
3121 strcat(chrPtr,"\"");
3122 if((ulRc=launchPMProg("Spieler", chrPlayer, chrParams, somSelf, ulView))==NULLHANDLE) {
3123 break;
3124 }
3125 return NULLHANDLE;
3126 }
3127#endif
3128 default:
3129 break;
3130 }
3131 return (MMAudio_parent_CWMMDataFile_wpOpen(somSelf, hwndCnr, ulView, param));
3132}
3133
3134
3135SOM_Scope void SOMLINK cwaudio_wpInitData(MMAudio *somSelf)
3136{
3137 MMAudioData *somThis = MMAudioGetData(somSelf);
3138 MMAudioMethodDebug("MMAudio","cwaudio_wpInitData");
3139
3140 MMAudio_parent_CWMMDataFile_wpInitData(somSelf);
3141 /* Flag to mark we haven't yet the audio size. The size will be read from the
3142 EAs (to circumvent the IO proc file scanning) or by checking the file using
3143 IO procs when the file was altered. */
3144 _ulFileSize=1;
3145
3146 /* This proc handles the start/stop/resume commands for audio objects.
3147 Playing takes place on a separate thread with an object window and this proc used
3148 for communicating. */
3149 _cwmmSetObjWindowProc(somSelf, &playObjectProc);
3150}
3151
3152/*
3153 This function checks all the installed audio IO procs if one of them can handle the
3154 audio file with the given extension. Only write enabled IO procs are accepted because
3155 we use this function to determine if we should create a template for the audio class.
3156 */
3157static BOOL checkForWriteEnabledAudioIOProc(char * chrExt)
3158{
3159 CHAR szBuffer[ sizeof( FOURCC ) + CCHMAXPATH + 4 ];
3160 MMFORMATINFO mmFormatInfo;
3161 PMMFORMATINFO pmmFormatInfoArray;
3162 void * memPtr;
3163 ULONG ulReturnCode;
3164 LONG lFormatsRead;
3165 LONG index;
3166 LONG lBytesRead;
3167 LONG lNumIOProcs;
3168
3169 memset( &mmFormatInfo,
3170 '\0',
3171 sizeof(MMFORMATINFO) );
3172
3173 mmFormatInfo.ulMediaType |= MMIO_MEDIATYPE_AUDIO;
3174 mmFormatInfo.ulFlags|=MMIO_CANWRITETRANSLATED;
3175 ulReturnCode = mmioQueryFormatCount ( &mmFormatInfo,
3176 &lNumIOProcs,
3177 0,
3178 0 );
3179
3180 if( ulReturnCode != MMIO_SUCCESS )
3181 {
3182 /*
3183 * Error - mmioQueryFormatCount failed.
3184 */
3185 return FALSE;
3186 }
3187
3188 /*
3189 * Allocate enough memory for n number of FormatInfo blocks
3190 */
3191 pmmFormatInfoArray = malloc (lNumIOProcs * sizeof( MMFORMATINFO ) );
3192 memPtr=pmmFormatInfoArray;
3193 if( pmmFormatInfoArray == NULL )
3194 {
3195 /*
3196 * Could not allocate enough memory for mmFormatInfo array.
3197 */
3198 return FALSE;
3199 }
3200
3201 /*
3202 * call mmioGetFormats to get info on the formats supported.
3203 */
3204 ulReturnCode = mmioGetFormats( &mmFormatInfo,
3205 lNumIOProcs,
3206 pmmFormatInfoArray,
3207 &lFormatsRead,
3208 0,
3209 0 );
3210 if( ulReturnCode != MMIO_SUCCESS )
3211 {
3212 /*
3213 * mmioGetFormats failed.
3214 */
3215 free(pmmFormatInfoArray);
3216 return FALSE;
3217 }
3218
3219 if( lFormatsRead != lNumIOProcs )
3220 {
3221 /*
3222 * Error in MMIO - number of formats read in by
3223 * mmioGetFormats is not equal to number of formats
3224 * found by mmioQueryFormatCount.
3225 */
3226 free(pmmFormatInfoArray);
3227 return FALSE;
3228 }
3229
3230 for ( index = 0; index <lNumIOProcs; index++ )
3231 {
3232 if(mmioGetFormatName(pmmFormatInfoArray, szBuffer, &lBytesRead, 0L, 0L))
3233 {
3234 //SysWriteToTrapLog("checkForWriteEnabledAudioIOProc: %s\n\n", szBuffer);
3235 continue;
3236 }
3237
3238 /* Insert NULL string terminator */
3239 *( szBuffer + lBytesRead ) = (CHAR)NULL;
3240
3241 if(pmmFormatInfoArray->ulFlags & MMIO_CANWRITETRANSLATED)
3242 {
3243 //if(pmmFormatInfoArray->fccIOProc==mmioStringToFOURCC(chr, MMIO_TOUPPER))
3244 //HlpWriteToTrapLog("%s --- %x %x %s\n",szBuffer, pmmFormatInfoArray->fccIOProc, mmioStringToFOURCC(chrType, MMIO_TOUPPER),
3245 // pmmFormatInfoArray->szDefaultFormatExt);
3246 if(strstr(chrExt, pmmFormatInfoArray->szDefaultFormatExt)) {
3247 // HlpWriteToTrapLog("******* Ext given: %s IO-Proc: %s\n", chrExt, pmmFormatInfoArray->szDefaultFormatExt);
3248 free(memPtr);
3249 return TRUE;
3250 }
3251 }
3252 /*
3253 * advance to next entry in mmFormatInfo array
3254 */
3255 pmmFormatInfoArray++;
3256 }
3257 free(memPtr);
3258 return FALSE;
3259}
3260
3261/*
3262 * wpCreateShadowObject : override;
3263 */
3264
3265SOM_Scope void SOMLINK cwaudio_wpUnInitData(MMAudio *somSelf)
3266{
3267 MMAudioData *somThis = MMAudioGetData(somSelf);
3268 MMAudioMethodDebug("MMAudio","cwaudio_wpUnInitData");
3269
3270 if(_pszName)
3271 _wpFreeMem(somSelf, _pszName);
3272
3273 if(_pszArtist)
3274 _wpFreeMem(somSelf, _pszArtist);
3275
3276 if(_pszAlbum)
3277 _wpFreeMem(somSelf, _pszAlbum);
3278
3279 if(_pszComment)
3280 _wpFreeMem(somSelf, _pszComment);
3281
3282 if(_pszYear)
3283 _wpFreeMem(somSelf, _pszYear);
3284
3285 if(_pszGenre)
3286 _wpFreeMem(somSelf, _pszGenre);
3287
3288 MMAudio_parent_CWMMDataFile_wpUnInitData(somSelf);
3289}
3290
3291
3292/*
3293 Only templates for write enabled audio IO procs are created in this method.
3294 */
3295SOM_Scope BOOL SOMLINK cwaudioM_wpclsCreateDefaultTemplates(M_MMAudio *somSelf,
3296 WPObject* Folder)
3297{
3298 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsCreateDefaultTemplates");
3299
3300 //HlpWriteToTrapLog("Classtitle: %s, Type: %s\n",_wpclsQueryTitle(somSelf), _wpclsQueryInstanceType(somSelf));
3301 if(checkForWriteEnabledAudioIOProc( _wpclsQueryInstanceFilter(somSelf))) {
3302 /* A write enabled IO proc was found, create the template. */
3303 mmclsCreateTheDefaultTemplate(somSelf, Folder);
3304 return TRUE; /* Tell the WPS template created*/
3305 }
3306
3307 return TRUE; /* We created the template or don't want to have one */
3308}
3309
3310
3311SOM_Scope PSZ SOMLINK cwaudioM_wpclsQueryInstanceType(M_MMAudio *somSelf)
3312{
3313 /* M_MMAudioData *somThis = M_MMAudioGetData(somSelf); */
3314 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryInstanceType");
3315
3316 return TYPE_DIGITALAUDIO;
3317}
3318
3319SOM_Scope PSZ SOMLINK cwaudioM_wpclsQueryInstanceFilter(M_MMAudio *somSelf)
3320{
3321 /* M_MMAudioData *somThis = M_MMAudioGetData(somSelf); */
3322 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryInstanceFilter");
3323
3324 /* The list of additional extensions is built in wpclsInitData().
3325
3326 FIXME
3327 This is a static list read in only once during startup.
3328 Should probably be changed later on.
3329 */
3330 return chrMMAudioExt;
3331 /* return (M_MMAudio_parent_M_CWMMDataFile_wpclsQueryInstanceFilter(somSelf)); */
3332}
3333
3334/*
3335 * The prototype for cwaudioM_wpclsQueryDetailsInfo was replaced by the following prototype:
3336 */
3337SOM_Scope ULONG SOMLINK cwaudioM_wpclsQueryDetailsInfo(M_MMAudio *somSelf,
3338 PCLASSFIELDINFO* ppClassFieldInfo,
3339 PULONG pSize)
3340{
3341 ULONG cParentColumns;
3342 PCLASSFIELDINFO pCfi;
3343 int i;
3344
3345 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3346 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryDetailsInfo");
3347
3348 cParentColumns= (M_MMAudio_parent_M_CWMMDataFile_wpclsQueryDetailsInfo(somSelf,
3349 ppClassFieldInfo,
3350 pSize));
3351 if(pSize)
3352 *pSize+=sizeof(AUDIODETAILS);
3353
3354 if(ppClassFieldInfo)
3355 {
3356 if(*ppClassFieldInfo)
3357 {
3358 pCfi=*ppClassFieldInfo;
3359 for(i=0; i<cParentColumns;i++)
3360 pCfi=(pCfi->pNextFieldInfo ? pCfi->pNextFieldInfo: pCfi);
3361
3362 pCfi->pNextFieldInfo=cfiFieldInfo;
3363 }
3364 else
3365 *ppClassFieldInfo=cfiFieldInfo;
3366 }
3367 return (cParentColumns+NUM_AUDIO_FIELDS);
3368}
3369
3370
3371/*
3372 * The prototype for cwaudioM_wpclsQueryTitle was replaced by the following prototype:
3373 */
3374SOM_Scope PSZ SOMLINK cwaudioM_wpclsQueryTitle(M_MMAudio *somSelf)
3375{
3376 static char chrTitle[30]={0};
3377
3378 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryTitle");
3379
3380 if(chrTitle[0]==0)
3381 if(!getMessage(chrTitle, IDSTR_CWAUDIOTITLE, sizeof(chrTitle), queryResModuleHandle(), HWND_DESKTOP))
3382 strcpy(chrTitle, CLSTITLE_DIGITALAUDIO);
3383
3384 return chrTitle;
3385}
3386
3387/*
3388 Initialize the MMAudio class.
3389 */
3390SOM_Scope void SOMLINK cwaudioM_wpclsInitData(M_MMAudio *somSelf)
3391{
3392 PCLASSFIELDINFO pCfi;
3393 USHORT i;
3394 static BOOL bGotAudioExt=FALSE;
3395
3396 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3397 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsInitData");
3398
3399 /*
3400 Get extensions of additional audio procs. These extensions may be specified by
3401 newly installed IO procs in MMPM2.INI or by using the Multimedia setup. For
3402 example the MMIOMP3 procedure for reading MP3 files adds the MP3 extension this
3403 way to the system. Extensions already handled by a specialized class will be
3404 filtered in the called REXX script e.g. MP3 so only unknown extensions end up here.
3405
3406 Strangely enough wpclsQueryInstanceFilter() is called during wpclsInitData() so
3407 we query the extensions here before calling the parent.
3408
3409 FIXME:
3410 The check is only done once during initialization. This is a little annoyance for
3411 the user because new extension specified in the settings will only be picked up
3412 on next WPS start.
3413 */
3414 if(!bGotAudioExt)
3415 {
3416 char chrTimidity[4];
3417 getStringFromRexxScript("audioext.rx", chrMMAudioExt, sizeof(chrMMAudioExt));
3418 bGotAudioExt=TRUE;
3419 /*getStringFromRexxScript("chktimid.rx", chrTimidity, sizeof(chrTimidity));
3420 // SysWriteToTrapLog("%s %d\n", chrTimidity, atol(chrTimidity));
3421 globalHaveTimidity=atol(chrTimidity);*/
3422 }
3423
3424 M_MMAudio_parent_M_CWMMDataFile_wpclsInitData(somSelf);
3425
3426 /* Get strings for details view titled from the ressource DLL */
3427 if(getMessage(chrPlayTime, IDSTR_PLAYTIME, sizeof(chrPlayTime), queryResModuleHandle(), HWND_DESKTOP))
3428 pszAudioColTitles[0]=chrPlayTime;
3429 /* New with 0.2.7 */
3430 if(getMessage(chrSampleRate, IDSTR_BITRATE, sizeof(chrBitRate), queryResModuleHandle(), HWND_DESKTOP))
3431 pszAudioColTitles[1]=chrBitRate;
3432
3433 if(getMessage(chrSampleRate, IDSTR_SAMPLERATE, sizeof(chrSampleRate), queryResModuleHandle(), HWND_DESKTOP))
3434 pszAudioColTitles[2]=chrSampleRate;
3435 if(getMessage(chrChannels, IDSTR_CHANNELS, sizeof(chrChannels), queryResModuleHandle(), HWND_DESKTOP))
3436 pszAudioColTitles[3]=chrChannels;
3437 if(getMessage(chrBPS, IDSTR_BPS, sizeof(chrBPS), queryResModuleHandle(), HWND_DESKTOP))
3438 pszAudioColTitles[4]=chrBPS;
3439
3440 if(getMessage(chrName, IDSTR_TITLE, sizeof(chrName), queryResModuleHandle(), HWND_DESKTOP))
3441 pszAudioColTitles[5]=chrName;
3442 if(getMessage(chrArtist, IDSTR_ARTIST, sizeof(chrArtist), queryResModuleHandle(), HWND_DESKTOP))
3443 pszAudioColTitles[6]=chrArtist;
3444 if(getMessage(chrAlbum, IDSTR_ALBUM, sizeof(chrAlbum), queryResModuleHandle(), HWND_DESKTOP))
3445 pszAudioColTitles[7]=chrAlbum;
3446 if(getMessage(chrYear, IDSTR_YEAR, sizeof(chrYear), queryResModuleHandle(), HWND_DESKTOP))
3447 pszAudioColTitles[8]=chrYear;
3448 if(getMessage(chrComment, IDSTR_COMMENT, sizeof(chrComment), queryResModuleHandle(), HWND_DESKTOP))
3449 pszAudioColTitles[9]=chrComment;
3450 if(getMessage(chrGenre, IDSTR_GENRE, sizeof(chrGenre), queryResModuleHandle(), HWND_DESKTOP))
3451 pszAudioColTitles[10]=chrGenre;
3452
3453
3454 /* Setup the static data for the details view */
3455 for(i=0,pCfi=cfiFieldInfo;i<NUM_AUDIO_FIELDS;i++,pCfi++)
3456 {
3457 memset((PCH)pCfi,0,sizeof(CLASSFIELDINFO));
3458
3459 pCfi->cb=sizeof(CLASSFIELDINFO);
3460 pCfi->flData=CFA_LEFT|CFA_SEPARATOR|CFA_FIREADONLY;
3461 pCfi->flTitle=CFA_CENTER|CFA_SEPARATOR|CFA_HORZSEPARATOR|CFA_STRING|CFA_FITITLEREADONLY;
3462 pCfi->pNextFieldInfo=pCfi+1;
3463 pCfi->pTitleData=(PVOID)pszAudioColTitles[i];
3464 pCfi->flCompare=COMPARE_SUPPORTED|SORTBY_SUPPORTED;
3465
3466 switch(i)
3467 {
3468 case 0: /* play time */
3469 pCfi->flData|=CFA_STRING;
3470 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszPlayTime));
3471 pCfi->ulLenFieldData=sizeof(PSZ);
3472 pCfi->DefaultComparison=CMP_EQUAL;
3473 break;
3474 case 1: /* Bitrate */ /* New with 0.2.7 */
3475 pCfi->flData|=CFA_STRING;
3476 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszBitRate));
3477 pCfi->ulLenFieldData=sizeof(PSZ);
3478 pCfi->DefaultComparison=CMP_EQUAL;
3479 break;
3480 case 2: /* Sample rate */
3481 pCfi->flData|=CFA_STRING;
3482 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszSampleRate));
3483 pCfi->ulLenFieldData=sizeof(PSZ);
3484 pCfi->DefaultComparison=CMP_EQUAL;
3485 break;
3486 case 3: /* Channels */
3487 pCfi->flData|=CFA_STRING;
3488 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszChannels));
3489 pCfi->ulLenFieldData=sizeof(PSZ);
3490 pCfi->DefaultComparison=CMP_EQUAL;
3491 break;
3492 case 4: /* BPS */
3493 pCfi->flData|=CFA_STRING;
3494 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszBPS));
3495 pCfi->ulLenFieldData=sizeof(PSZ);
3496 pCfi->DefaultComparison=CMP_EQUAL;
3497 break;
3498
3499 case 5:
3500 pCfi->flData|=CFA_STRING;
3501 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszName));
3502 pCfi->ulLenFieldData=sizeof(PSZ);
3503 pCfi->DefaultComparison=CMP_EQUAL;
3504 break;
3505 case 6:
3506 pCfi->flData|=CFA_STRING;
3507 pCfi->flData|=CFA_STRING;
3508 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszArtist));
3509 pCfi->ulLenFieldData=sizeof(PSZ);
3510 pCfi->DefaultComparison=CMP_EQUAL;
3511 break;
3512 case 7:
3513 pCfi->flData|=CFA_STRING;
3514 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszAlbum));
3515 pCfi->ulLenFieldData=sizeof(PSZ);
3516 pCfi->DefaultComparison=CMP_EQUAL;
3517 break;
3518 case 8:
3519 pCfi->flData|=CFA_STRING;
3520 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszYear));
3521 pCfi->ulLenFieldData=sizeof(PSZ);
3522 pCfi->DefaultComparison=CMP_EQUAL;
3523 break;
3524 case 9:
3525 pCfi->flData|=CFA_STRING;
3526 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszComment));
3527 pCfi->ulLenFieldData=sizeof(PSZ);
3528 pCfi->DefaultComparison=CMP_EQUAL;
3529 break;
3530 case 10:
3531 pCfi->flData|=CFA_STRING;
3532 pCfi->offFieldData=(ULONG)(FIELDOFFSETUL(AUDIODETAILS,pszGenre));
3533 pCfi->ulLenFieldData=sizeof(PSZ);
3534 pCfi->DefaultComparison=CMP_EQUAL;
3535 break;
3536
3537 }/* switch(i) */
3538 }/* for() */
3539 cfiFieldInfo[NUM_AUDIO_FIELDS].pNextFieldInfo=NULL;
3540
3541 /* Get name of help library from resource */
3542 if(!getMessage(chrHelpLibrary, IDSTR_HELPLIBRARY, sizeof(chrHelpLibrary),
3543 queryResModuleHandle(), HWND_DESKTOP))
3544 strcpy(chrHelpLibrary,"MMPARTS.HLP"); /* Fall back to default Warp hel library */
3545}
3546
3547
3548
3549
3550SOM_Scope void SOMLINK cwaudioM_wpclsUnInitData(M_MMAudio *somSelf)
3551{
3552 /* M_MMAudioData *somThis = M_MMAudioGetData(somSelf); */
3553 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsUnInitData");
3554
3555 M_MMAudio_parent_M_CWMMDataFile_wpclsUnInitData(somSelf);
3556}
3557
3558/*
3559 * The prototype for cwaudioM_wpclsQueryDefaultView was replaced by the following prototype:
3560 */
3561SOM_Scope ULONG SOMLINK cwaudioM_wpclsQueryDefaultView(M_MMAudio *somSelf)
3562{
3563 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3564 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryDefaultView");
3565
3566 /* Default view for audio objects is 'Start' so on doubleclick the playing starts
3567 immediately. */
3568
3569 return ID_MENU_START;
3570}
3571
3572/*
3573 * The prototype for cwaudioM_wpclsQueryIconData was replaced by the following prototype:
3574 */
3575SOM_Scope ULONG SOMLINK cwaudioM_wpclsQueryIconData(M_MMAudio *somSelf,
3576 PICONINFO pIconInfo)
3577{
3578 HMODULE hmod;
3579 /* M_CWAudioData *somThis = M_CWAudioGetData(somSelf); */
3580 M_MMAudioMethodDebug("M_MMAudio","cwaudioM_wpclsQueryIconData");
3581 /*
3582 We have our own icon.
3583 */
3584 hmod=queryModuleHandle();
3585 if(!hmod)
3586 return M_MMAudio_parent_M_CWMMDataFile_wpclsQueryIconData(somSelf, pIconInfo);
3587
3588 if (pIconInfo) {
3589 pIconInfo->fFormat = ICON_RESOURCE;
3590 pIconInfo->hmod = queryModuleHandle();
3591 pIconInfo->resid = ID_ICONCWAUDIOFILE;
3592 } /* endif */
3593
3594 return ( sizeof(ICONINFO) );
3595}
3596
3597
3598
3599MRESULT EXPENTRY audioWorkerProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
3600{
3601
3602 switch (msg)
3603 {
3604 case WM_APPTERMINATENOTIFY:
3605 {
3606 ULONG ulSize;
3607 char fName[CCHMAXPATH];
3608 char text[CCHMAXPATH];
3609 BOOL bContinue=FALSE;
3610 MMAudio *somSelf=(MMAudio*)mp1;
3611 WPObject *pLinkObj=NULLHANDLE;
3612 MMAudioData *somThis= MMAudioGetData(somSelf);
3613 ULONG ulLoop;
3614
3615 TRY_LOUD(AUDIO_WORKER) {
3616 for(;;) {
3617 ULONG rc;
3618 MMIOINFO mmio;
3619 HMMIO hmmio;
3620 MMAUDIOHEADER mmAudioHeader={0};
3621 LONG lBytesRead=0;
3622 char* pChar;
3623 ULONG ulFSize;
3624 BOOL bIsMidi=FALSE;
3625 WPFolder *wpFolder;
3626
3627 mmclsSetObjectType(somSelf);
3628
3629 if(!somIsObj(somSelf))
3630 break;
3631
3632 /* Don't check stream objects */
3633 if(somObjectIsA(somSelf, "MMAudioStream"))
3634 break;
3635 /* Don't check CD-Track objects */
3636 if(somObjectIsA(somSelf, "MMCDTrack"))
3637 break;
3638
3639 /* Check if object is inserted into a container. If not the folder was
3640 closed. */
3641 // if(!somObjectIsInsertedInContainer(somSelf))
3642 // break;
3643
3644 ulFSize=_wpQueryFileSize(somSelf);
3645 if(_ulFileSize==ulFSize)
3646 break; /* We already scanned this file */
3647
3648 /*
3649 @@CHANGE 0.2.8
3650
3651 Check if parent folder is closed. If yes, don't start file scanning.
3652
3653 @@CHANGE 0.2.9
3654
3655 Check if we have a shadow in an open folder.
3656
3657 */
3658
3659 wpFolder=_wpQueryFolder(somSelf);
3660 if(somIsObj(wpFolder)) {
3661 if(!_wpFindViewItem(wpFolder , VIEW_ANY, NULLHANDLE)) {
3662 PUSEITEM pUseItem;
3663 BOOL fOpenView=FALSE;
3664 /* Ok, our object isn't in an open folder, but we may have a shadow somewhere in an
3665 open folder. */
3666 for(pUseItem=_wpFindUseItem(somSelf, USAGE_LINK, NULL);pUseItem;
3667 pUseItem=_wpFindUseItem(somSelf, USAGE_LINK, pUseItem))
3668 {
3669 PLINKITEM pLI=(PLINKITEM)++pUseItem;
3670 pLinkObj=pLI->LinkObj; /* The awake shadow */
3671
3672 if(somIsObj(pLinkObj)) {
3673 wpFolder=_wpQueryFolder(pLinkObj);
3674 if(somIsObj(wpFolder)) {
3675 if(_wpFindViewItem(wpFolder , VIEW_ANY, NULLHANDLE)) {
3676 fOpenView=TRUE;
3677 break;
3678 }
3679 }/* somIsObj(wpFolder) */
3680 }
3681 }/* for() */
3682 if(!fOpenView)
3683 break;
3684 }
3685 }
3686
3687 /* Get file name */
3688 ulSize=sizeof(fName);
3689 if(!_wpQueryRealName(somSelf, fName, &ulSize, TRUE))
3690 break; /* Error */
3691
3692 /* Show status window */
3693 if((pChar=strrchr(fName, '\\'))!=NULLHANDLE) {
3694 HPS hps;
3695 ULONG ulWinTextLen;
3696 POINTL aptlPoints[TXTBOX_COUNT];
3697 SWP swp;
3698 ULONG ulCy;
3699 WPOINT pwpBorder;
3700
3701 HWND hwndClient=WinWindowFromID(__get_hwndStatus(_CWMMDataFile), FID_CLIENT);
3702
3703 sprintf(text,"%c:\\...%s",fName[0], pChar);
3704
3705 WinSetWindowText(hwndClient, text);
3706 ulWinTextLen=(ULONG)strlen(text); // Query text length
3707
3708 /* Calculate text size in pixel */
3709 hps=WinBeginPaint(hwndClient,(HPS)NULL,(PRECTL)NULL);
3710 GpiQueryTextBox(hps,ulWinTextLen,text,TXTBOX_COUNT,aptlPoints);
3711 WinEndPaint(hps);
3712
3713 if(WinSendMsg(__get_hwndStatus(_CWMMDataFile) ,WM_QUERYBORDERSIZE, MPFROMP(&pwpBorder), 0L))
3714 ulCy=pwpBorder.x*2;
3715 else
3716 ulCy=SV_CYBORDER*2; /* Safe default */
3717
3718 if(WinQueryWindowPos(WinWindowFromID(__get_hwndStatus(_CWMMDataFile), FID_TITLEBAR),&swp))
3719 {
3720 if(!swp.cy)
3721 if(!WinQueryWindowPos(WinWindowFromID(HWND_DESKTOP, FID_TITLEBAR), &swp))
3722 swp.cy=15;
3723 ulCy+=swp.cy;
3724 }
3725 else
3726 ulCy+=15;
3727
3728 WinSetWindowPos(__get_hwndStatus(_CWMMDataFile), HWND_TOP, 0,0,
3729 aptlPoints[TXTBOX_BOTTOMRIGHT].x-aptlPoints[TXTBOX_BOTTOMLEFT].x+18,
3730 aptlPoints[TXTBOX_TOPRIGHT].y-aptlPoints[TXTBOX_BOTTOMRIGHT].y+ulCy+4,
3731 SWP_SIZE|SWP_SHOW|SWP_ZORDER|SWP_DEACTIVATE);
3732 WinPostMsg(__get_hwndStatus(_CWMMDataFile), WM_APPTERMINATENOTIFY, 0,MPFROMLONG(1L));
3733 }
3734
3735 //#if 0
3736 /* This part obsolete?? */
3737 /* Get file name */
3738 ulSize=sizeof(fName);
3739 if(!_wpQueryRealName(somSelf, fName, &ulSize, TRUE))
3740 break;
3741 //#endif
3742
3743 if(!_somIsA(somSelf, somGetSomClass("MMMIDI")))
3744 {
3745 /* Check audio files */
3746 MP3OPTIONS mp3Opt={0}; /* Struct holding MP3 additional info */
3747 VORBISOPTIONS vorbisOpt={0};
3748
3749 PMP3OPTIONS returnedMP3Opts;
3750 PVORBISOPTIONS returnedVorbisOpts;
3751
3752 memset(&mmio,0, sizeof(mmio));
3753 mmio.ulFlags=MMIO_READ;
3754 mmio.ulTranslate=MMIO_TRANSLATEHEADER;
3755
3756 hmmio = mmioOpen(fName, &mmio, MMIO_READ);
3757 if(!hmmio)
3758 break;
3759
3760 /* The Quicktime IO-procs don't like any data in mmio.pExtraInfoStruct when calling
3761 mmioOpen(). But we need that if we want to have the bitrate of MP3 and Ogg. So the
3762 file is closed here and opened again with the FourCC set to MP3 or OGGS. So the Quicktime
3763 IO-procs will not be called.*/
3764 if(somObjectIsA(somSelf, "MMOGG"))
3765 {
3766 if(mmioFOURCC('O', 'G', 'G', 'S')==mmio.fccIOProc) {
3767 mmioClose(hmmio, 0);
3768
3769 memset(&mmio,0, sizeof(mmio));
3770 mmio.ulFlags=MMIO_READ;
3771 mmio.ulTranslate=MMIO_TRANSLATEHEADER;
3772 mmio.fccIOProc=mmioFOURCC('O', 'G', 'G', 'S');
3773 vorbisOpt.cookie = VORBIS_COOKIE;
3774 mmio.pExtraInfoStruct = &vorbisOpt;
3775 /*Now reopen */
3776 hmmio = mmioOpen(fName, &mmio, MMIO_READ);
3777 if(!hmmio)
3778 break;
3779 }
3780 }
3781 else if(somObjectIsA(somSelf, "MMMP3"))
3782 {
3783 if(mmioFOURCC('M', 'P', '3', ' ')==mmio.fccIOProc) {
3784 mmioClose(hmmio, 0);
3785
3786 memset(&mmio,0, sizeof(mmio));
3787 mmio.ulFlags=MMIO_READ;
3788 mmio.ulTranslate=MMIO_TRANSLATEHEADER;
3789 mmio.fccIOProc=mmioFOURCC('M', 'P', '3', ' ');
3790 /* For bitrate query of MP3 */
3791 mp3Opt.cookie = MP3_COOKIE;
3792 mmio.pExtraInfoStruct = &mp3Opt;
3793 /*Now reopen */
3794 hmmio = mmioOpen(fName, &mmio, MMIO_READ);
3795 if(!hmmio)
3796 break;
3797
3798 //SysWriteToTrapLog("%s reopened. mp3Opt.bitrate: %d\n", fName, mp3Opt.bitrate);
3799 }
3800 }
3801
3802 memset(&mmAudioHeader,0,sizeof(MMAUDIOHEADER));
3803 rc = mmioGetHeader(hmmio, &mmAudioHeader,sizeof(MMAUDIOHEADER),
3804 &lBytesRead, 0, 0);
3805
3806 if(rc!=MMIO_SUCCESS) {
3807 mmioClose(hmmio, 0);
3808 break;
3809 }
3810
3811 mmioClose(hmmio, 0);
3812
3813 /* Check if the object is still living. */
3814 if(!somIsObj(somSelf))
3815 break;
3816
3817 _ulBitRate=0;
3818 if(somObjectIsA(somSelf, "MMOGG")) {
3819 returnedVorbisOpts = (PVORBISOPTIONS)mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation;
3820 if(0 != returnedVorbisOpts && VORBIS_COOKIE == returnedVorbisOpts->cookie && 0 != returnedVorbisOpts->nominal_bitrate)
3821 _ulBitRate=returnedVorbisOpts->nominal_bitrate;
3822 }
3823 else if(somObjectIsA(somSelf, "MMMP3")) {
3824 returnedMP3Opts = (PMP3OPTIONS)mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation;
3825 if(0 != returnedMP3Opts && MP3_COOKIE == returnedMP3Opts->cookie && 0 != returnedMP3Opts->bitrate)
3826 _ulBitRate=returnedMP3Opts->bitrate;
3827 }
3828
3829 _ulChannels=mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels;
3830 _ulSampleRate=mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
3831 _ulBPS=mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample;
3832 _ulNumAudioBytes=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
3833 /* sprintf(fName,"%02d:%02d",mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes/
3834 mmAudioHeader.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec/60,
3835 mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes/
3836 mmAudioHeader.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec%60);*/
3837 if(mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS/1000) {
3838 _ulPlaySecs=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS/1000;
3839 _ulPlayMsecs=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS;
3840 }
3841 else {
3842 _ulPlaySecs=mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes/
3843 mmAudioHeader.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec;
3844 _ulPlayMsecs=_ulPlaySecs*1000;
3845 }
3846 }/* _somIsA()*/
3847 else
3848 {
3849 /* The file is a midi file. Get audio information using MCI commands. */
3850 unsigned char chrCommand[CCHMAXPATH];
3851 char retMsg[20];
3852 APIRET rc;
3853 ULONG ulTime;
3854
3855 bIsMidi=TRUE;
3856
3857 /* Prevent Timidity crash */
3858 /*if(globalHaveTimidity)
3859 break;*/
3860
3861 /* open the file */
3862 sprintf(chrCommand,"open \"%s\" type SEQUENCER alias wave%p SHAREABLE wait",fName, somSelf);
3863 rc = mciSendString( chrCommand, retMsg, sizeof(retMsg), NULLHANDLE, 0);
3864 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
3865 break;
3866 }
3867
3868 /* Set time format */
3869 sprintf(chrCommand,"SET wave%p TIME FORMAT MILLISECONDS wait", somSelf);
3870 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3871 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
3872 /* close the file */
3873 sprintf(chrCommand,"close wave%p wait", somSelf);
3874 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3875 break;
3876 }
3877
3878 /* Get midi info */
3879 sprintf(chrCommand,"STATUS wave%p LENGTH WAIT", somSelf);
3880 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3881 if((rc & 0x0000ffff)!=MCIERR_SUCCESS) {
3882 /* close the file */
3883 sprintf(chrCommand,"close wave%p wait", somSelf);
3884 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3885 break;
3886 }
3887 ulTime=atoi(retMsg);
3888 // HlpWriteToTrapLog("Midi-Time in ms: %d %s\n", ulTime, fName);
3889
3890 if(ulTime/1000) {
3891 _ulPlaySecs=ulTime/1000;
3892 _ulPlayMsecs=ulTime;
3893 }
3894 else {
3895 _ulPlaySecs=1;
3896 _ulPlayMsecs=_ulPlaySecs*1000;
3897 }
3898
3899 // HlpWriteToTrapLog("Midi-Time ulPlaySecs: %d\n", _ulPlaySecs);
3900 sprintf(chrCommand,"STATUS wave%p NUMBER OF TRACKS WAIT", somSelf);
3901 rc = mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3902 if((rc & 0x0000ffff)==MCIERR_SUCCESS) {
3903 _ulChannels=atoi(retMsg);
3904 // HlpWriteToTrapLog("Midi-Tracks: %d %s %s\n", _ulChannels, fName, retMsg);
3905 }
3906
3907 /* close the file */
3908 sprintf(chrCommand,"close wave%p wait", somSelf);
3909 mciSendString(chrCommand, retMsg, sizeof(retMsg), 0, 0);
3910 }/* else is MMMIDI */
3911
3912 _ulFileSize=_wpQueryFileSize(somSelf);
3913 _bNeedSaving=TRUE;/* When the object is initialized the new instance data will be saved in wpObjectReady(). */
3914
3915 sprintf(fName,"%d",_ulChannels);
3916 strncpy(_chrChannels, fName, sizeof(_chrChannels));
3917 _chrChannels[sizeof(_chrChannels)-1]=0;
3918
3919 if(bIsMidi)
3920 strncpy(_chrSampleRate, "---", sizeof(_chrSampleRate));
3921 else {
3922 sprintf(fName,"%d", _ulSampleRate);
3923 strncpy(_chrSampleRate, fName, sizeof(_chrSampleRate));
3924 }
3925 _chrSampleRate[sizeof(_chrSampleRate)-1]=0;
3926
3927 if(!_ulBitRate)
3928 strncpy(_chrBitRate, "---", sizeof(_chrBitRate));
3929 else {
3930 sprintf(fName,"%d",_ulBitRate);
3931 strncpy(_chrBitRate, fName, sizeof(_chrBitRate));
3932 }
3933 _chrBitRate[sizeof(_chrBitRate)-1]=0;
3934
3935 if(bIsMidi)
3936 strncpy(_chrBPS, "---", sizeof(_chrBPS));
3937 else {
3938 sprintf(fName,"%d",_ulBPS);
3939 strncpy(_chrBPS, fName, sizeof(_chrBPS));
3940 }
3941 _chrBPS[sizeof(_chrBPS)-1]=0;
3942
3943 sprintf(fName,"%02d:%02d",_ulPlaySecs/60, _ulPlaySecs%60);
3944 strncpy(_chrPlayTime, fName, sizeof(_chrPlayTime));
3945 _chrPlayTime[sizeof(_chrPlayTime)-1]=0;
3946
3947 bContinue=TRUE;
3948 break;
3949 }/* for */
3950 }
3951 CATCH(AUDIO_WORKER)
3952 {
3953 SysWriteToTrapLog("\nTrap occured in %s, file %s, around line %d.\n",
3954 __FUNCTION__, __FILE__, __LINE__);
3955 SysWriteToTrapLog("Audio file: %s\n\n",
3956 fName);
3957 } END_CATCH;
3958
3959 /* Hide status window */
3960 WinPostMsg(__get_hwndStatus(_CWMMDataFile), WM_APPTERMINATENOTIFY, 0, 0L);
3961
3962 if(!bContinue)
3963 return (MRESULT)FALSE;
3964
3965 /* This Message was posted from wpRestore(). It's not allowed to call
3966 wpSaveDeferred() from there. The object must be initilized! This is important when
3967 creating objects from templates. So we wait for the object to be initialized.
3968 If it isn't initialized within 2s we quit. */
3969 ulLoop=0;
3970 while(!_wpIsObjectInitialized(somSelf) && ulLoop<40) {
3971 DosSleep(50);
3972 ulLoop++;
3973 }
3974 if(ulLoop<20)
3975 _wpSaveDeferred(somSelf);
3976 /* Now we have the audio info */
3977 _wpCnrRefreshDetails(somSelf);
3978 /*
3979 @@CHANGE 0.2.9
3980
3981 Also refresh shadows in containers. For now we only support one shadow but that doesn't is a problem
3982 because after the first shadow the linked object has queried the audio data and every other shadow
3983 that will be awaked can use that info without ending here. Only problem may be the user opens a lot
3984 of folders with shadows and we are not fast enough but I don't care at the momen ;-).
3985 */
3986 if(pLinkObj!=NULLHANDLE && somIsObj(pLinkObj)) /* The check on NULLHANDLE is very fast while somIsObj() needs
3987 quite some time. So we check for a valid object only if we
3988 can be quite sure we have an object (pointer!=NULLHANDLE). */
3989 _wpCnrRefreshDetails(pLinkObj);
3990 return (MRESULT) FALSE;
3991 }
3992 default:
3993 break;
3994 }
3995
3996 return WinDefWindowProc( hwnd, msg, mp1, mp2);
3997}
3998
Note: See TracBrowser for help on using the repository browser.