123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- #include "WindacPlay.h"
- #include "api__in_cdda.h"
- int WindacPlay::threadProc2()
- {
- while (1)
- {
- if (need_seek != -1)
- {
- current_sector = start_sector;
- current_sector += ((need_seek * 75) / 1000);
- bytes_in_sbuf = 0;
- line.outMod->Flush(need_seek);
- decode_pos_ms = need_seek;
- need_seek = -1;
- }
- if (!killswitch && bytes_in_sbuf <= 0 && current_sector.GetHSG() < end_sector.GetHSG())
- {
- if (!scsi->Get_DriveStatus().CDPresent)
- {
- //infos->error("No CD present!");
- PostMessage(line.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
- return 0;
- }
- unsigned char *s = sbuf;
- while ((bytes_in_sbuf < buf_size*2352) && (current_sector.GetHSG() < end_sector.GetHSG()) && !killswitch)
- {
- int n = min((int)16, (int)(end_sector.GetHSG() - current_sector.GetHSG()));
- memset(s, 0, n*2352);
- scsi->ReadCDDA(current_sector, n, s);
- while (!scsi->WaitCDDA() && !killswitch) Sleep(66);
- bytes_in_sbuf += n * 2352;
- s += n * 2352;
- current_sector += n;
- }
- }
- if (!bytes_in_sbuf && !killswitch)
- {
- //wait for output to be finished
- line.outMod->Write(NULL, 0);
- while (!killswitch && line.outMod->IsPlaying()) Sleep(10);
- if (!killswitch)
- PostMessage(line.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
- return 0;
- }
- if (killswitch) return 0;
- char sample_buffer[576*4*2] = {0};
- int bytes = sizeof(sample_buffer) / 2; // enough room for dsp bullcrap
- bytes = min((int)bytes_in_sbuf, (int)bytes);
- memcpy(sample_buffer, sbuf, bytes);
- if (bytes_in_sbuf > bytes) memcpy(sbuf, sbuf + bytes, bytes_in_sbuf - bytes);
- bytes_in_sbuf -= bytes;
- int obytes = bytes;
- line.VSAAddPCMData(sample_buffer, g_nch, 16, line.outMod->GetWrittenTime() /*decode_pos_ms*/);
- line.SAAddPCMData(sample_buffer, g_nch, 16, line.outMod->GetWrittenTime() /*decode_pos_ms*/);
- if (line.dsp_isactive())
- bytes = line.dsp_dosamples((short *)sample_buffer, bytes / g_nch / 2, 16, g_nch, 44100) * (g_nch * 2);
- while (line.outMod->CanWrite() < bytes && !killswitch) Sleep(66);
- if (killswitch) return 0;
- line.outMod->Write(sample_buffer, bytes);
- decode_pos_ms += ((obytes / g_nch / 2) * 1000) / 44100;
- }
- return 0;
- }
- void WindacPlay::stop()
- {
- if (hThread)
- {
- killswitch = 1;
- WaitForSingleObject(hThread, INFINITE);
- }
- if (needsToClose)
- {
- needsToClose = false;
- }
- line.outMod->Close();
- }
- int WindacPlay::open(wchar_t drive, int track) //called by winampGetExtendedRead
- {
- g_drive = drive;
- if (!inited && !LoadASPI())
- {
- g_drive = 0;
- return 1;
- }
- inited = 1;
- int drivenum = 0;
- getTrackInfos(&drivenum, (char)drive);
- m_pMapDrive = new CMapDrive(TRUE);
- int nbdrives = m_pMapDrive->GetMaxDrives();
- if (!nbdrives) return 0;
- int host = -1, id = -1, lun = -1;
- if (getSCSIIDFromDrive((char)drive, &host, &id, &lun))
- {
- int found = 0;
- for (int i = 0;i < nbdrives;i++)
- {
- drive_info = m_pMapDrive->GetInfo(i);
- if (drive_info.HostAdapterNumber == host && drive_info.ID == id && drive_info.LUN == lun)
- {
- found = 1;
- break;
- }
- }
- if (!found)
- {
- s_last_error = "Drive not found";
- return 1;
- }
- }
- else
- {
- // can't figure out the SCSI ID, oh well, try the gay method
- TDriveInfo *tdi = &m_pMapDrive->GetInfo(drivenum);
- if (!tdi)
- {
- s_last_error = "Drive not found";
- return 1;
- }
- drive_info = *tdi;
- }
- scsi = new CSCSICD((char)drive, drive_info);
- TDriveStatus status = scsi->Get_DriveStatus();
- if (!status.CDPresent)
- {
- s_last_error = "CD not present";
- //infos->warning("No CD present!");
- g_drive=0;
- return 1;
- }
- TTrackList track_info = {0};
- track_info.TrackNummer = track;
- scsi->ReadTrackInfo(track_info);
- if (track_info.Flags.DataTrack)
- {
- s_last_error = "Cannot play track";
- //infos->warning("Can't play data tracks");
- g_drive=0;
- return 1;
- }
- start_sector = track_info.StartSektor;
- current_sector = start_sector;
- end_sector = start_sector;
- slength = track_info.Laenge;
- end_sector += slength;
- g_playlength = (slength / 75) * 1000;
- g_nch = track_info.Flags.AudioChannels;
- g_srate = 44100;
- g_bps = 16;
- scsi->PrepareCDDA();
- if (!sbuf)
- sbuf = (unsigned char *)malloc(2352 * buf_size);
- bytes_in_sbuf = 0;
- last_eject_scan = 0;
- return 0;
- }
- int WindacPlay::play(wchar_t drive, int track) //called by winamp2's normal(old) play() interface
- {
- if (open(drive, track)) return 1;
- // do this here as it helps to prevent an audio glitch on first playback and volume is set low
- setvolume(a_v, a_p);
- int maxlat = line.outMod->Open(44100, g_nch, 16, -1, -1);
- if (maxlat < 0)
- {
- g_drive=0;
- return 1;
- }
- line.SetInfo(1411, 44, g_nch, 1);
- line.SAVSAInit(maxlat, 44100);
- line.VSASetInfo(g_nch, 44100);
- line.is_seekable = 1;
- killswitch = 0;
- DWORD thread_id;
- hThread = CreateThread(NULL, NULL, &threadProc, (LPVOID)this, NULL, &thread_id);
- SetThreadPriority(hThread, AGAVE_API_CONFIG->GetInt(playbackConfigGroupGUID, L"priority", THREAD_PRIORITY_HIGHEST));
- //open the device thru MCI (for getfileinfo to work properly)
- g_playtrack = track;
- needsToClose = true;
- return 0;
- }
- int WindacPlay::read(char *dest, int len, int *killswitch) //called by winampGetExtendedRead_getData
- {
- int l = 0;
- while (l < len && !*killswitch)
- {
- if (!*killswitch && bytes_in_sbuf <= 0 && current_sector.GetHSG() < end_sector.GetHSG())
- {
- //scan for ejected CD only every 2 seconds
- if (last_eject_scan + 5000 < GetTickCount())
- {
- int cnt = 5;
- while (!scsi->Get_DriveStatus().CDPresent && cnt--)
- {
- Sleep(100);
- }
- if (cnt < 0 && !scsi->Get_DriveStatus().CDPresent)
- {
- //infos->error("No CD present!");
- return -1;
- }
- last_eject_scan = GetTickCount();
- }
- unsigned char *s = sbuf;
- while ((bytes_in_sbuf < buf_size*2352) && (current_sector.GetHSG() < end_sector.GetHSG()))
- {
- int n = min((int)16, (int)(end_sector.GetHSG() - current_sector.GetHSG()));
- memset(s, 0, n*2352);
- scsi->ReadCDDA(current_sector, n, s);
- while (!scsi->WaitCDDA() && !*killswitch) Sleep(66);
- if (*killswitch) break;
- bytes_in_sbuf += n * 2352;
- s += n * 2352;
- current_sector += n;
- }
- }
- if (!bytes_in_sbuf) break;
- int bytes = min(bytes_in_sbuf, len - l);
- memcpy(dest + l, sbuf, bytes);
- if (bytes_in_sbuf > bytes) memcpy(sbuf, sbuf + bytes, bytes_in_sbuf - bytes);
- bytes_in_sbuf -= bytes;
- l += bytes;
- }
- return l;
- }
- void WindacPlay::getTrackInfos(int *drivenum, char driveletter)
- {
- //finds first cdrom drive letter
- char firstcd = 'D';
- {
- DWORD drives = GetLogicalDrives();
- int nb = 0;
- for (int drivemask = 0; (drivemask < 32) && (nb < 4); drivemask++)
- {
- if (drives&(1 << drivemask))
- {
- wchar_t tmp[16] = {0};
- wsprintf(tmp, L"%c:\\", L'A' + drivemask);
- if (GetDriveType(tmp) == DRIVE_CDROM)
- {
- firstcd = 'A' + drivemask;
- break;
- }
- }
- }
- }
- *drivenum = driveletter - (unsigned char)firstcd;
- }
- WindacPlay::WindacPlay()
- {
- scsi = NULL;
- sbuf = NULL;
- m_pMapDrive = NULL;
- buf_size = 64; //make it configitem
- hThread = NULL;
- decode_pos_ms = 0;
- inited = 0;
- need_seek = -1;
- needsToClose = false;
- }
- WindacPlay::~WindacPlay()
- {
- if (scsi)
- {
- scsi->FinishCDDA();
- delete(scsi);
- }
- delete(m_pMapDrive);
- free(sbuf);
- if (inited) FreeASPI();
- if (needsToClose)
- {
- needsToClose = false;
- }
- }
|