From 3d94188f92ff70f7218c09d0d906870814a06173 Mon Sep 17 00:00:00 2001 From: chudov Date: Wed, 28 Jan 2009 04:53:13 +0000 Subject: [PATCH] 1) Fixed crash on source files that contain zero length tags 2) Fixed a glitch in filename corrector - it sometimes didn't replace underscores with spaces. 3) Fixed a bug when a broken cue sheet was created if artist, title or genre contained comma character. 3) Added .zip archive support 4) Added support for cue sheets which start with data track (mixed mode or "playstation type" cds) --- APETagDotNet/APETagDotNet.cs | 5 +- APETagDotNet/APETagDotNet.csproj | 4 +- CUERipper/cddb.ico | Bin 0 -> 318 bytes CUERipper/freedb.gif | Bin 0 -> 1055 bytes CUERipper/frmCUERipper.cs | 16 +- CUETools.AccurateRip/AccurateRip.cs | 64 +- CUETools.CDImage/CDImage.cs | 20 +- CUETools.Codecs/Codecs.cs | 56 +- CUETools.Converter/CUETools.Converter.csproj | 101 + CUETools.Converter/Program.cs | 86 + CUETools.Converter/Properties/AssemblyInfo.cs | 33 + CUETools.Processor/AudioReadWrite.cs | 14 +- CUETools.Processor/CUETools.Processor.csproj | 4 + .../ICSharpCode.SharpZipLib.dll | Bin 0 -> 192512 bytes CUETools.Processor/Processor.cs | 563 ++-- CUETools.Processor/frmProperties.Designer.cs | 152 + CUETools.Processor/frmProperties.cs | 51 + CUETools.Processor/frmProperties.resx | 441 +++ CUETools.Ripper.SCSI/SCSIDrive.cs | 16 +- CUETools/CUETools.sln | 15 + CUETools/frmCUETools.Designer.cs | 302 +- CUETools/frmCUETools.cs | 4 +- CUETools/frmCUETools.de-DE.resx | 29 +- CUETools/frmCUETools.resx | 2674 +++++++++-------- HDCDDotNet/HDCDDotNet.cs | 25 +- LossyWAVSharp/LossyWAVSharp.csproj | 8 +- LossyWAVSharp/Program.cs | 6 +- MAC_SDK/Source/MACLib/Assembly/Assembly.obj | Bin 836 -> 836 bytes MAC_SDK/Source/MACLib/Assembly/Assembly64.obj | Bin 1259 -> 1259 bytes flac/src/libFLAC/ia32/bitreader_asm.obj | Bin 3928 -> 3928 bytes flac/src/libFLAC/ia32/cpu_asm.obj | Bin 1012 -> 1012 bytes flac/src/libFLAC/ia32/fixed_asm.obj | Bin 2016 -> 2016 bytes flac/src/libFLAC/ia32/lpc_asm.obj | Bin 9664 -> 9664 bytes flac/src/libFLAC/ia32/stream_encoder_asm.obj | Bin 1084 -> 1084 bytes 34 files changed, 3122 insertions(+), 1567 deletions(-) create mode 100644 CUERipper/cddb.ico create mode 100644 CUERipper/freedb.gif create mode 100644 CUETools.Converter/CUETools.Converter.csproj create mode 100644 CUETools.Converter/Program.cs create mode 100644 CUETools.Converter/Properties/AssemblyInfo.cs create mode 100644 CUETools.Processor/ICSharpCode.SharpZipLib.dll create mode 100644 CUETools.Processor/frmProperties.Designer.cs create mode 100644 CUETools.Processor/frmProperties.cs create mode 100644 CUETools.Processor/frmProperties.resx diff --git a/APETagDotNet/APETagDotNet.cs b/APETagDotNet/APETagDotNet.cs index 3d10d55..1f19a99 100644 --- a/APETagDotNet/APETagDotNet.cs +++ b/APETagDotNet/APETagDotNet.cs @@ -263,7 +263,7 @@ namespace APETagsDotNet bool bAPETagRemoved = true; bool bFailedToRemove = false; - + while (bID3Removed || bAPETagRemoved) { bID3Removed = false; @@ -445,7 +445,8 @@ namespace APETagsDotNet // remove a specific field void RemoveField(string pFieldName) { - RemoveField(GetTagFieldIndex(pFieldName)); + int idx = GetTagFieldIndex(pFieldName); + if (idx >= 0) RemoveField(idx); } void RemoveField(int nIndex) diff --git a/APETagDotNet/APETagDotNet.csproj b/APETagDotNet/APETagDotNet.csproj index 1fe6da0..45933f8 100644 --- a/APETagDotNet/APETagDotNet.csproj +++ b/APETagDotNet/APETagDotNet.csproj @@ -39,7 +39,7 @@ prompt - bin\win32\Release\ + ..\bin\win32\Release\ TRACE true pdbonly @@ -61,7 +61,7 @@ prompt - bin\x64\Release\ + ..\bin\x64\Release\ TRACE true pdbonly diff --git a/CUERipper/cddb.ico b/CUERipper/cddb.ico new file mode 100644 index 0000000000000000000000000000000000000000..3aa1d8f2eeb17926949a0240afdafbf3700aec7d GIT binary patch literal 318 zcmZQzU}Ruq5D*YxU|?Wj&|qX>5My9q&|qL-0Es9tfaF;iK%fCcKru)TgeOjY&v5J3 zFNW>gzcToTKVx|I>=#2#!yAT6mwqvvJNJ#@@85q6$4`D^*n8j`LrV5bhFSAIF}!;9 zi^1CY5!j@T&VBD5hjesw_`Q4g?sZ2;$L)9T-aY8(=;%<`9WVn#w?wv+QhaHGM(b2IFO7nr}866#RP;2kkc41&hWMC*^0+BHc3`zMR znGDZ!7=%(77*ZJ+iWopZ7(~2aWMBl*AS?nRAee)}nSo(10|Q9S1_qy}3@?NjgcukY zEG*n&AfgNmU7mAw4jk-$^r*bNoI#qI0VZzX#t_2<*2%zNvBfRsIfJke2Ll6Bk21qk z2Cyj%3>}Ny*diH(9X%Kt7+gvmo~=y~+APeliy`GULmlJ6ZiYwY4CN8R&V~#O9SjWR z3=IEY`2A;m@t;BHKLbOE2*Wd&IfrgAY-eQX0jrt8>?Q?sgT-@(7)GcYOhBFhdFucJ z!zo6FZ46NL42lel3=bH({xUGu2TWvm%J@Kt;V%P2JtI>KBf~331|dcU2A>xx&lu~3 z7`ho4%2Px#>KFvO89K@t$}3Vfh&|uXAtVfP+rkb1CvW)QA^g9bK_LU-wp0doD+Y!a zV7Gy+hq(>R-T>ish%iKg!UrTKrU4=uI2jHwFjz1!z{8orgn{8X)WdbD9~eY58D2a; zP!6)0f#E*{{b%s`&j1ad{}%H9V;KGmgX9<<$}>oVwU;w6EZD*z@&Oc+EV2bTPPdg_IcA4q%y&;9?8{tNm2XJDw` z@ZipW=@&xJg&4{iQbIP=J>Sp`4#NtD3t|ky9SkqZ8Or}NZ1}%_!+(F_|Df<-gnB)N zAvTdgx`g3HDnof514GO?2Dbv?M0bWV2F0H&AcYJ%AQF@(*g5_%uye?GY*=uxnT?f& zfkA=cP`iMnSqaC+B*!);oh%uRhQx**CMT^k77h>Hn;C;9>1YZ*cIxDd_fomJQPp)C zukk4s0infCZA`Y`o>&SjJ}})?TJ5N1!9(B0%yZP{{wT`un(683#rtaFEC1P=o8>}J zeO2>az~n5{vdeT;;1Xt=M>Sq1dXejN&u?RK2uQs(nZ=jsUv=r?#O7*Y?YJ{LHa=%Vt<^Oj#srS$}TNq{nx+PSDh|sV+{8Ix+oXn_TzLjpt_SSb8tX xy}9<{&9aN{Vq|9L=iS;RyIPI=PF~?z&Y9oO{xK}^>i26eyLWD{bwdM#H2}^qJ`w-` literal 0 HcmV?d00001 diff --git a/CUERipper/frmCUERipper.cs b/CUERipper/frmCUERipper.cs index 7591f27..7be1d81 100644 --- a/CUERipper/frmCUERipper.cs +++ b/CUERipper/frmCUERipper.cs @@ -345,11 +345,24 @@ namespace CUERipper code = m_freedb.Read(queryResult, out cdEntry); if (code == FreedbHelper.ResponseCodes.CODE_210) { + Encoding iso = Encoding.GetEncoding("iso-8859-1"); ReleaseInfo r = CreateCUESheet(audioSource, null, cdEntry); this.BeginInvoke((MethodInvoker)delegate() { comboRelease.Items.Add(r); }); + if (Encoding.Default.GetString(iso.GetBytes(cdEntry.Title)) != cdEntry.Title) + { + cdEntry.Artist = Encoding.Default.GetString(iso.GetBytes(cdEntry.Artist)); + cdEntry.Title = Encoding.Default.GetString(iso.GetBytes(cdEntry.Title)); + for (int i = 0; i < cdEntry.Tracks.Count; i++) + cdEntry.Tracks[i].Title = Encoding.Default.GetString(iso.GetBytes(cdEntry.Tracks[i].Title)); + r = CreateCUESheet(audioSource, null, cdEntry); + this.BeginInvoke((MethodInvoker)delegate() + { + comboRelease.Items.Add(r); + }); + } } } else @@ -478,7 +491,8 @@ namespace CUERipper if (comboRelease.Items[e.Index] is ReleaseInfo) { Bitmap ImageToDraw = ((ReleaseInfo)comboRelease.Items[e.Index]).bitmap; - e.Graphics.DrawImage(ImageToDraw, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Height, e.Bounds.Height)); + if (ImageToDraw != null) + e.Graphics.DrawImage(ImageToDraw, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Height, e.Bounds.Height)); //e.Graphics.DrawImage(ImageToDraw, new Rectangle(e.Bounds.X + e.Bounds.Width - ImageToDraw.Width, e.Bounds.Y, ImageToDraw.Width, e.Bounds.Height)); } e.Graphics.DrawString(text, e.Font, new SolidBrush(e.ForeColor), new RectangleF((float)e.Bounds.X + e.Bounds.Height, (float)e.Bounds.Y, (float)(e.Bounds.Width - e.Bounds.Height), (float)e.Bounds.Height), format); diff --git a/CUETools.AccurateRip/AccurateRip.cs b/CUETools.AccurateRip/AccurateRip.cs index 1246678..9fac6ee 100644 --- a/CUETools.AccurateRip/AccurateRip.cs +++ b/CUETools.AccurateRip/AccurateRip.cs @@ -17,6 +17,9 @@ namespace CUETools.AccurateRip _toc = toc; _accDisks = new List(); _crc32 = new Crc32(); + _CRCLOG = new uint[_toc.AudioTracks + 1]; + for (int i = 0; i <= _toc.AudioTracks; i++) + _CRCLOG[i] = 0; Init(); } @@ -131,7 +134,7 @@ namespace CUETools.AccurateRip { CRCs[i] += baseSum; baseSum -= stepSum; - //CRC32[i] = _crc32.ComputeChecksum (CRC32[i], samples, count); + //_offsetedCRC32[i] = _crc32.ComputeChecksum (CRC32[i], samples, count); } } } @@ -153,7 +156,22 @@ namespace CUETools.AccurateRip public uint CRC32(int iTrack) { - return _offsetedCRC32[iTrack] ^ 0xffffffff; + return _CRC32[iTrack] ^ 0xffffffff; + } + + public uint CRCWONULL(int iTrack) + { + return _CRCWONULL[iTrack] ^ 0xffffffff; + } + + public uint CRCLOG(int iTrack) + { + return _CRCLOG[iTrack]; + } + + public void CRCLOG(int iTrack, uint value) + { + _CRCLOG[iTrack] = value; } public uint CRC450(int iTrack, int oi) @@ -170,11 +188,11 @@ namespace CUETools.AccurateRip { fixed (int* pSampleBuff = &sampleBuffer[pos, 0]) { - if (_currentTrack != 0) + if (_currentTrack > 0) { - uint trackLength = _toc[_currentTrack].Length * 588; - uint currentOffset = (uint)_sampleCount - _toc[_currentTrack].Start * 588; - uint previousOffset = _currentTrack > 1 ? _toc[_currentTrack - 1].Length * 588 : _toc.Pregap * 588; + uint trackLength = _toc[_currentTrack + _toc.FirstAudio - 1].Length * 588; + uint currentOffset = (uint)_sampleCount - _toc[_currentTrack + _toc.FirstAudio - 1].Start * 588; + uint previousOffset = _currentTrack > 1 ? _toc[_currentTrack + _toc.FirstAudio - 2].Length * 588 : _toc[_toc.FirstAudio].Pregap * 588; uint si1 = (uint)Math.Min(copyCount, Math.Max(0, 588 * (_currentTrack == 1 ? 10 : 5) - (int)currentOffset)); uint si2 = (uint)Math.Min(copyCount, Math.Max(si1, trackLength - (int)currentOffset - 588 * (_currentTrack == _toc.AudioTracks ? 10 : 5))); if (_currentTrack == 1) @@ -188,9 +206,11 @@ namespace CUETools.AccurateRip else CalculateAccurateRipCRCsSemifast(pSampleBuff + si2 * 2, copyCount - si2, _currentTrack - 1, currentOffset + si2, previousOffset, trackLength); - _offsetedCRC32[_currentTrack] = _crc32.ComputeChecksum(_offsetedCRC32[_currentTrack], pSampleBuff, copyCount); + _CRC32[_currentTrack] = _crc32.ComputeChecksum(_CRC32[_currentTrack], pSampleBuff, copyCount); + _CRCWONULL[_currentTrack] = _crc32.ComputeChecksumWONULL(_CRCWONULL[_currentTrack], pSampleBuff, copyCount); } - _offsetedCRC32[0] = _crc32.ComputeChecksum(_offsetedCRC32[0], pSampleBuff, copyCount); + _CRC32[0] = _crc32.ComputeChecksum(_CRC32[0], pSampleBuff, copyCount); + _CRCWONULL[0] = _crc32.ComputeChecksumWONULL(_CRCWONULL[0], pSampleBuff, copyCount); } } pos += copyCount; @@ -204,12 +224,16 @@ namespace CUETools.AccurateRip { _offsetedCRC = new uint[_toc.AudioTracks, 10 * 588]; _offsetedFrame450CRC = new uint[_toc.AudioTracks, 10 * 588]; - _offsetedCRC32 = new uint[_toc.AudioTracks + 1]; + _CRC32 = new uint[_toc.AudioTracks + 1]; + _CRCWONULL = new uint[_toc.AudioTracks + 1]; for (int i = 0; i <= _toc.AudioTracks; i++) - _offsetedCRC32[i] = 0xffffffff; + { + _CRC32[i] = 0xffffffff; + _CRCWONULL[i] = 0xffffffff; + } _currentTrack = 0; - _sampleCount = 0; - _samplesRemTrack = _toc.Pregap * 588; + _sampleCount = _toc[_toc.FirstAudio][0].Start * 588; + _samplesRemTrack = _toc[_toc.FirstAudio].Pregap * 588; CheckPosition(); } @@ -226,7 +250,7 @@ namespace CUETools.AccurateRip { if (++_currentTrack > _toc.AudioTracks) return; - _samplesRemTrack = _toc[_currentTrack].Length * 588; + _samplesRemTrack = _toc[_currentTrack + _toc.FirstAudio - 1].Length * 588; } } @@ -438,10 +462,10 @@ namespace CUETools.AccurateRip if (CRC32(0) != 0) { sw.WriteLine(""); - sw.WriteLine("Track\t[ CRC32 ]"); - sw.WriteLine(String.Format(" --\t[{0:X8}]", CRC32(0))); + sw.WriteLine("Track\t[ CRC32 ]\t[W/O NULL]\t[ LOG ]"); + sw.WriteLine(String.Format(" --\t[{0:X8}]\t[{1:X8}]\t{2:10}", CRC32(0), CRCWONULL(0), CRCLOG(0) == CRC32(0) ? " CRC32 " : CRCLOG(0) == CRCWONULL(0) ? " W/O NULL " : CRCLOG(0) == 0 ? "" : String.Format("[{0:X8}]", CRCLOG(0)))); for (int iTrack = 1; iTrack <= _toc.AudioTracks; iTrack++) - sw.WriteLine(String.Format(" {0:00}\t[{1:X8}]", iTrack, CRC32(iTrack))); + sw.WriteLine(String.Format(" {0:00}\t[{1:X8}]\t[{2:X8}]\t{3:10}", iTrack, CRC32(iTrack), CRCWONULL(iTrack), CRCLOG(iTrack) == CRC32(iTrack) ? " CRC32 " : CRCLOG(iTrack) == CRCWONULL(iTrack) ? " W/O NULL " : CRCLOG(iTrack) == 0 ? "" : String.Format("[{0:X8}]", CRCLOG(iTrack)))); } } @@ -544,14 +568,16 @@ namespace CUETools.AccurateRip // Calculate the three disc ids used by AR uint discId1 = 0; uint discId2 = 0; + uint num = 0; + for (int iTrack = 1; iTrack <= toc.TrackCount; iTrack++) if (toc[iTrack].IsAudio) { discId1 += toc[iTrack].Start; - discId2 += Math.Max(toc[iTrack].Start, 1) * toc[iTrack].Number; + discId2 += Math.Max(toc[iTrack].Start, 1) * (++num); } discId1 += toc.Length; - discId2 += Math.Max(toc.Length, 1) * ((uint)toc.AudioTracks + 1); + discId2 += Math.Max(toc.Length, 1) * (++num); discId1 &= 0xFFFFFFFF; discId2 &= 0xFFFFFFFF; return string.Format("{0:x8}-{1:x8}-{2}", discId1, discId2, CalculateCDDBId(toc).ToLower()); @@ -590,7 +616,7 @@ namespace CUETools.AccurateRip private HttpStatusCode _accResult; private uint[,] _offsetedCRC; private uint[,] _offsetedFrame450CRC; - private uint[] _offsetedCRC32; + private uint[] _CRC32, _CRCWONULL, _CRCLOG; private uint[] _backupCRC; Crc32 _crc32; diff --git a/CUETools.CDImage/CDImage.cs b/CUETools.CDImage/CDImage.cs index d6d2a0e..3afbec8 100644 --- a/CUETools.CDImage/CDImage.cs +++ b/CUETools.CDImage/CDImage.cs @@ -241,6 +241,7 @@ namespace CUETools.CDImage { _catalog = src._catalog; _audioTracks = src._audioTracks; + _firstAudio = src._firstAudio; _tracks = new List(); for (int i = 0; i < src.TrackCount; i++) _tracks.Add(new CDTrack(src._tracks[i])); @@ -287,7 +288,15 @@ namespace CUETools.CDImage { get { - return _audioTracks; + return (uint) _audioTracks; + } + } + + public int FirstAudio + { + get + { + return _firstAudio + 1; } } @@ -295,7 +304,7 @@ namespace CUETools.CDImage { get { - return AudioTracks > 0 ? _tracks[(int)_audioTracks - 1].End + 1U : 0U; + return AudioTracks > 0 ? _tracks[_firstAudio + _audioTracks - 1].End + 1U - _tracks[_firstAudio].Start + _tracks[_firstAudio].Pregap : 0U; } } @@ -329,7 +338,11 @@ namespace CUETools.CDImage { _tracks.Add(track); if (track.IsAudio) + { _audioTracks++; + if (!_tracks[_firstAudio].IsAudio) + _firstAudio = _tracks.Count - 1; + } } public uint IndexLength(int iTrack, int iIndex) @@ -372,6 +385,7 @@ namespace CUETools.CDImage string _catalog; IList _tracks; - uint _audioTracks; + int _audioTracks; + int _firstAudio; } } diff --git a/CUETools.Codecs/Codecs.cs b/CUETools.Codecs/Codecs.cs index 9118c82..6e61e4a 100644 --- a/CUETools.Codecs/Codecs.cs +++ b/CUETools.Codecs/Codecs.cs @@ -131,6 +131,43 @@ namespace CUETools.Codecs } } + public static unsafe void BytesToFLACSamples_24(byte[] inSamples, int inByteOffset, + int[,] outSamples, int outSampleOffset, uint sampleCount, int channelCount, int wastedBits) + { + uint loopCount = sampleCount * (uint)channelCount; + + if ((inSamples.Length - inByteOffset < loopCount * 3) || + (outSamples.GetLength(0) - outSampleOffset < sampleCount)) + throw new IndexOutOfRangeException(); + + fixed (byte* pInSamplesFixed = &inSamples[inByteOffset]) + { + fixed (int* pOutSamplesFixed = &outSamples[outSampleOffset, 0]) + { + byte* pInSamples = (byte*)pInSamplesFixed; + int* pOutSamples = pOutSamplesFixed; + for (int i = 0; i < loopCount; i++) + { + int sample = (int)*(pInSamples++); + sample += (int)*(pInSamples++) << 8; + sample += (int)*(pInSamples++) << 16; + *(pOutSamples++) = (sample << 8) >> (8 + wastedBits); + } + } + } + } + + public static unsafe void BytesToFLACSamples(byte[] inSamples, int inByteOffset, + int[,] outSamples, int outSampleOffset, uint sampleCount, int channelCount, int bitsPerSample) + { + if (bitsPerSample == 16) + AudioSamples.BytesToFLACSamples_16(inSamples, inByteOffset, outSamples, outSampleOffset, sampleCount, channelCount); + else if (bitsPerSample > 16 && bitsPerSample <= 24) + AudioSamples.BytesToFLACSamples_24(inSamples, inByteOffset, outSamples, outSampleOffset, sampleCount, channelCount, 24 - bitsPerSample); + else + throw new Exception("Unsupported bitsPerSample value"); + } + public static int[,] Read(IAudioSource source, int[,] buff) { if (source.Remaining == 0) return null; @@ -527,8 +564,8 @@ namespace CUETools.Codecs _sampleBuffer = new byte[byteCount]; if (_IO.Read(_sampleBuffer, 0, (int)byteCount) != byteCount) throw new Exception("Incomplete file read."); - AudioSamples.BytesToFLACSamples_16(_sampleBuffer, 0, buff, 0, - sampleCount, _channelCount); + AudioSamples.BytesToFLACSamples(_sampleBuffer, 0, buff, 0, + sampleCount, _channelCount, _bitsPerSample); _samplePos += sampleCount; return sampleCount; } @@ -975,7 +1012,20 @@ namespace CUETools.Codecs { int s1 = samples[2 * i], s2 = samples[2 * i + 1]; crc = ComputeChecksum(ComputeChecksum(ComputeChecksum(ComputeChecksum( - crc, (byte)s1), (byte)(s1 >> 8)), (byte)(s2)), (byte)(s2 >> 8)); + crc, (byte)s1), (byte)(s1 >> 8)), (byte)s2), (byte)(s2 >> 8)); + } + return crc; + } + + public unsafe uint ComputeChecksumWONULL(uint crc, int* samples, uint count) + { + for (uint i = 0; i < count; i++) + { + int s1 = samples[2 * i], s2 = samples[2 * i + 1]; + if (s1 != 0) + crc = ComputeChecksum(ComputeChecksum(crc, (byte)s1), (byte)(s1 >> 8)); + if (s2 != 0) + crc = ComputeChecksum(ComputeChecksum(crc, (byte)s2), (byte)(s2 >> 8)); } return crc; } diff --git a/CUETools.Converter/CUETools.Converter.csproj b/CUETools.Converter/CUETools.Converter.csproj new file mode 100644 index 0000000..4349d15 --- /dev/null +++ b/CUETools.Converter/CUETools.Converter.csproj @@ -0,0 +1,101 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926} + Exe + Properties + CUETools.Converter + CUETools.Converter + + + true + full + false + ..\bin\win32\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\bin\win32\Release\ + TRACE + prompt + 4 + + + true + ..\bin\win32\Debug\ + DEBUG;TRACE + full + x86 + C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + + + ..\bin\win32\Release\ + TRACE + true + pdbonly + x86 + C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + + + + + + + + + + + + + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} + CUETools.Codecs + + + {4911BD82-49EF-4858-8B51-5394F86739A4} + CUETools.Processor + + + + + \ No newline at end of file diff --git a/CUETools.Converter/Program.cs b/CUETools.Converter/Program.cs new file mode 100644 index 0000000..549e9d6 --- /dev/null +++ b/CUETools.Converter/Program.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CUETools.Codecs; +using CUETools.Processor; + +namespace CUETools.Converter +{ + class Program + { + static void Usage() + { + Console.WriteLine("Usage : CUETools.Converter.exe "); + Console.WriteLine(); + //Console.WriteLine("-N --stdinname pseudo filename to use when input from STDIN."); + //Console.WriteLine(" --stdout write processed WAV output to STDOUT."); + } + + static void Main(string[] args) + { + Console.SetOut(Console.Error); + Console.WriteLine("CUETools.Converter, Copyright (C) 2009 Gregory S. Chudov."); + Console.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to"); + Console.WriteLine("the extent permitted by law. for details."); + if (args.Length < 2) + { + Usage(); + return; + } + string sourceFile = args[0]; + string destFile = args[1]; + + DateTime start = DateTime.Now; + TimeSpan lastPrint = TimeSpan.FromMilliseconds(0); + CUEConfig config = new CUEConfig(); + config.lossyWAVHybrid = false; +#if !DEBUG + try +#endif + { + IAudioSource audioSource = AudioReadWrite.GetAudioSource(sourceFile, null); + IAudioDest audioDest = AudioReadWrite.GetAudioDest(destFile, (long)audioSource.Length, audioSource.BitsPerSample, audioSource.SampleRate, config); + int[,] buff = new int[0x1000, audioSource.ChannelCount]; + + audioDest.SetTags(audioSource.Tags); + Console.WriteLine("Filename : {0}", sourceFile); + Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.SampleRate, audioSource.ChannelCount, audioSource.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.SampleRate)); + + do + { + uint samplesRead = audioSource.Read(buff, Math.Min((uint)buff.GetLength(0), (uint)audioSource.Remaining)); + if (samplesRead == 0) break; + audioDest.Write(buff, samplesRead); + TimeSpan elapsed = DateTime.Now - start; + if ((elapsed - lastPrint).TotalMilliseconds > 60) + { + Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", + 100.0 * audioSource.Position / audioSource.Length, + audioSource.Position / elapsed.TotalSeconds / audioSource.SampleRate, + elapsed, + TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length) + ); + lastPrint = elapsed; + } + } while (true); + + TimeSpan totalElapsed = DateTime.Now - start; + Console.Error.Write("\r \r"); + Console.WriteLine("Results : {0:0.00}x; {1}", + audioSource.Position / totalElapsed.TotalSeconds / audioSource.SampleRate, + totalElapsed + ); + audioSource.Close(); + audioDest.Close(); + } +#if !DEBUG + catch (Exception ex) + { + Console.WriteLine(); + Console.WriteLine("Error: {0}", ex.Message); + //Console.WriteLine("{0}", ex.StackTrace); + } +#endif + } + } +} diff --git a/CUETools.Converter/Properties/AssemblyInfo.cs b/CUETools.Converter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ec7fe2d --- /dev/null +++ b/CUETools.Converter/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CUETools.Converter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("CUETools.Converter")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5ad82fad-b0a4-4f7e-b159-2773aaa3f6d3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CUETools.Processor/AudioReadWrite.cs b/CUETools.Processor/AudioReadWrite.cs index 02e0575..c1c29e6 100644 --- a/CUETools.Processor/AudioReadWrite.cs +++ b/CUETools.Processor/AudioReadWrite.cs @@ -97,22 +97,18 @@ namespace CUETools.Processor return dest; } - public static IAudioDest GetAudioDest(string path, long finalSampleCount, CUEConfig config) + public static IAudioDest GetAudioDest(string path, long finalSampleCount, int bitsPerSample, int sampleRate, CUEConfig config) { string extension = Path.GetExtension(path).ToLower(); string filename = Path.GetFileNameWithoutExtension(path); if (Path.GetExtension(filename).ToLower() != ".lossy") - { - int bitsPerSample = (config.detectHDCD && config.decodeHDCD) ? (config.decodeHDCDto24bit ? 24 : 20) : 16; - return GetAudioDest(path, bitsPerSample, 2, 44100, finalSampleCount, extension, config); - } + return GetAudioDest(path, bitsPerSample, 2, sampleRate, finalSampleCount, extension, config); string lwcdfPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(filename) + ".lwcdf" + extension); - int destBitsPerSample = (config.detectHDCD && config.decodeHDCD) ? ((!config.decodeHDCDtoLW16 && config.decodeHDCDto24bit) ? 24 : 20) : 16; int lossyBitsPerSample = (config.detectHDCD && config.decodeHDCD && !config.decodeHDCDtoLW16) ? 24 : 16; - IAudioDest lossyDest = GetAudioDest(path, lossyBitsPerSample, 2, 44100, finalSampleCount, extension, config); - IAudioDest lwcdfDest = config.lossyWAVHybrid ? GetAudioDest(lwcdfPath, destBitsPerSample, 2, 44100, finalSampleCount, extension, config) : null; - return new LossyWAVWriter(lossyDest, lwcdfDest, destBitsPerSample, 2, 44100, config.lossyWAVQuality); + IAudioDest lossyDest = GetAudioDest(path, lossyBitsPerSample, 2, sampleRate, finalSampleCount, extension, config); + IAudioDest lwcdfDest = config.lossyWAVHybrid ? GetAudioDest(lwcdfPath, bitsPerSample, 2, sampleRate, finalSampleCount, extension, config) : null; + return new LossyWAVWriter(lossyDest, lwcdfDest, bitsPerSample, 2, sampleRate, config.lossyWAVQuality); } } } \ No newline at end of file diff --git a/CUETools.Processor/CUETools.Processor.csproj b/CUETools.Processor/CUETools.Processor.csproj index 6b1ef21..4a9e873 100644 --- a/CUETools.Processor/CUETools.Processor.csproj +++ b/CUETools.Processor/CUETools.Processor.csproj @@ -78,6 +78,10 @@ prompt + + False + .\ICSharpCode.SharpZipLib.dll + diff --git a/CUETools.Processor/ICSharpCode.SharpZipLib.dll b/CUETools.Processor/ICSharpCode.SharpZipLib.dll new file mode 100644 index 0000000000000000000000000000000000000000..e829ebf4baa5601ed650a56b821e266ef0c0d9cc GIT binary patch literal 192512 zcmeZ`n!v!!z`(%5z`*eTKLf)K1_*F~P3uoAfkNNq3j1t3=9ko5OD#ByFn^I?g!Bf3d{@)0t^gu0+|_@ z85~%_908Dw0GJ77fhaKEa*c^09K?FS#Bc*{2uJ{inHhLsOj2kC1_ll!^&AQe3~&!J zFfizqq*jzLFffR0hx!ZTSFk$~niLoq67-6Si;@`_AZ`Qs9i-+0C=3wl92giJ^omk* z@{<{$ZiR#a14unW87S18khr7F(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S^99 z0w1nH`jVi&DH8)LLq{zmgH9wP11DM-1Sl{tfcpDr!Wi7u3KG36Uj!eq7IN?9%Xwdz zzhW(y(hG~GMSsNCZesF(xKm@=_DqxM&o)K&TYRuE zeVLQsV$rJqeOC9b?hlMd=B`n{u=jbO!`?saUvx`#9WLL__%)MHF(r|OU2XHtzrLz& zxqOnH$>Gng2yfFUn=Ea>#1O^6z`)4BAjqW4UBt-1P*5zyz`#|-tjk>_jNtJw74tDL zuyL{F3o|fqaclE4vtP;=VPJp>u!|bMy~o9-!^W1+$iTpL=N=b_4jTuAt;N8=D8sOgzji#a19kFu@$b26Y5f0KX$3Zct;8 zbAi|ka)VI-ge}LUAj0_C%%nS^#85tO!GBGfGVqjp{%FMuUje&vTE)xSo zG&2K(KO+Of5hezPTqXtvJ0=DOPX-2tJ|+f+TTBcLH$e6u ztQi;>su>v=)_~l|%)n5{1TnvviGd-Lfq`Ka0|P@m69WSW69dB%W(Ee(Fw-4I28OL5 zb&L!Q>lhdq+M)icVu1Kph>3w=7b62hC^G{CX!zzQ0|UceMg|6ECI*IHW(EdDCI*K6 zObiUunHdC#uF)}a|F*7iHVPs$kVq#!OVPartWMW`YWM*Kv!@$6>h=GB@n3;j$ z1~UVLFB1a;BNGF|dqxHZd1eNNg$xV~F-!~$`i zEDV?!7`8JrFf3qTU~pn$V7SD@z~Iloz@Wm+z>vVez%Y}Mf#D<*1H&3-28JFc28LzK z3=F5385s66GBDUNGB6}ELelO6CI*HA1_lN}W(I~3wO7#SFTF)=WJ z(jzFX2Qn})%x7j`0I3sYW?-mgU|^Wd$iTqK#K5qMnSnuvk%7UKnSsHNfq@~Mk%3`7 z1EkFT1x=@H%nS@?m>C#^85tO!Gcz#ML(>UJeF7r`LmdMHLnJc;!yaY^hBQV722h@N zVPasY0p)onNZQ*AO@DKtes5!7VA#gQz>v+z!0>>XfkBg*f#Eq51H%di28MIY3=A7U z@xsW!@P>(j!Gr-4@2{B{7@C+E7`8D$@*~J!5sVBBs-W}?N;^yp4F5rCj){Rm59A+4 z1_n?b0p*WIW(J1c%nS@Om>3wYGBYrAGBGd|LhU-u$iPs`%)s!3fq`KoBLjmg$URI9 z3_Oes4D*;77(OsCFr-1t7m!*|xdBRxpO_dJ)R-93u~F*7jCV`5;Kz{J3i#Kgexh>3xrgAt+!l+QqEuNRb-m>C!x85tNHK;;7y zB(A=J!j_qVVL1~6!)H)hhL&CV%nS^N7#J9Am>3uum>}gQ$ek7p3=E)j3$phxs2pHm zU^vOhz;KX}fkBp;f#EO%1A{m-1A`tD1H(qBxtffSvI;a7ZNUslztfo*80J9BqA*4V zhBzh$22gzEfXX!{28J9)28MEwy$q0Y3RI>UFfuTBGD6Z%B1oK(f#E$91H(r~1_moe z28Qd*3=Cz^ytx3Bra@uP04cXYdHf1919;dthna!l9;p0dWMD7^l_Q`$4z+U&69a=S zGXp~qD4jAhFzjSzU|7P$!0?TMfuWEQlGi}_{~Z&gT()M0l*eMs3=9g43=FfGA$he5 z<|1A{gb1H&;;dIhC_W(Ed(W(EdjCI$vpMg|5RCI*IcptQya zsV_ir0}Ah{Opv^Dfti8fJ~IQuBqm55(#Z@dUtTgXFdPI`)XWSFYD^3a3D9y6nFdSrNV6bIiVAue16Eg!t3#dM0hNP=3P+i5yzyLBABwoVEz+etaH;fDn zn;0SG2&jH*1(kuIxMyZyXlGzx;9+K9U}a`tsAghd0Lg*UMG6BXeSymMr3?%VKNuMp zW`Ob>1H`SMG7OZTIT;xkPBSnt7%?y~%mKv#1H_(t(6Zzx0|Uc9Mh1pdMo7L7VrF27 zVuqxT6`;C-iGd+cfdN!1889#~s$O`<#K58<&cMLcz|FwGqNT>f%%UL)Z7oQFXeB0Q z4QUVqEF}YHu`w{PftnQTAR45I1H=F;;smi67=#U&!Q~<|sQp!3%fP@^E6KpX!lVFd zk@cD}Ffi6iA^7GXz6=^)7R(QFV_@h7%gdqh<-vTgc_8o9DuMViy`Tm`tuhi@1&OT+ zVT0AHf!Lz8njlKNRtrK|fG7=F1_mxME^RBOYLG!}3QUX)480&tiI@7l`EsBjhH>OU z94;{}7+(RzhjA1^9K9lSP)k+`)UFMJ7@@-rq4Sj?3d-RM^osT)u>~0!3W~uR^@^h5 zY;e38fZ7e9>QI-vXe~$z+-?@*(w0CpN152Pm|55&*e}fi`s^657a9G zHLO8wAqEBpDFy}xZ8;_leFg?LZ80Vd0}#!}q+tl6*_bqp7#P^tv_N(-gX>Rl`V*^_ zW?*1}L?|fLu}#p?VX6kFw`!0K+od^7)u80Y#subHn!}_DW{5|Cb%MPJPPs<=pk{;W zc~(%`)=&pG+`$w#6PV(GP`qsNPR1ha@=?b89P$~)T%7WTMy#CjmWCWm;(7 zHVs08^utVpx;=`CxfYbEn8a!&Kq|#*#lb<$AZ@_H;KslJn(r1A_$2YjcrK{P%#mP|*|gM{ z~n6RL>H|)uIdxEKxj6O!5*M8lWOX1e6Cgw7@2U;!-?(+ggKc6IU#Ytr5!5BDKBEkU9=lizwt0IuvH0iibn`@qUKd` z)VwMV$*b|g+|XPq4#}m0T;fTB+zFt>1r1k@S%REX3}y>*L4y~}j}$W!LlXh#IwNFf zFja%2fnye$$|>CJoW_h=>^ki1;ttNB9=b4(xG*ofE+;7YMhNq0^RkN@a|-fE2=Ycn z2=fT?iYE#4k`*>CGzf|{c>HB){{R1fc5!Qi|Ns9B@`y(W^FS(RHnE8lh54WS_;M>Y{1HJm4ShQ6O_*xVNGE!HZiez zkl+zx69?yiQ0s?FoLgIljU6eVKp{B=5?J7x1+3KYju?-&4kYk6Ch{^>D=;vyuyIb| zn8(J6q!${<9O4l?9FRCPJT1b-1X0dZ4JuQn)Ea>zU946gLYaanupPCAAZ9hFt)e5! zBvxw-;)>OpfG7=JP+N#eLk~oO>QVz1hPSXbOEuUGaFVe-32DTDjH)#N>4dnMsTySK zM2HnI=YWKu&Z!1jrfb4f2kKcdRfFuD0&##Um?ItmaR-LA@2Nl14F-1LHo=VyaF%A}zLDt|SQx*}k| zGlRzyK;CBpn+XYOgH$GnW>P$k+fg#4I11E;d;@Y2DEPrXW2y!Pzn&jLPG%DPt#(8S_936RPsC2Q0#sO`vlq-1@%!t z?Q=0^0|{n%P6J^vNUOzw3qs3t8gduihBpwHm}^088fINaEpQWuIf{#k4cz3Z1y?(4 zy`Va&7L>HK^okgn7z&CtKpk_vqDT-M+{n-?nvKMM3}=JOSkNc~7XyQ!7#AN4x3;_( zkG2pi$7FV64i+|!d7wThxESPPGkOUwNBLL{?}+hgb1-v?&4aYa#f?6LTIBM~tb#0) z#Un7wQAjgMkcE%U=(e~ptF{8OAS;q8WOx{T1?FHoEo4hF)e8NWQ2?xFz_-kFlaC^ zFjO)?#L_vnBJV8uw{Q>U%)OsQKpx#lf4;tSW%m)usf#vzs?S|?7$l?%QX$5r&CdiHe3}TErv;6+ zu^PSA0*{?kgUU5fI|Vc@$Q%KV$5<|=YEW>C>iIz!Y{mvms@1U!3@qXiwIGTK%u)Eq zz`$T=&!pi43S(##iGdYpK?TLZJSH}9^l3q9RI{|Kn8d+x0d8Dyf%{1)V^QAlu_#c| zf{aCh6IC@xhV9~9rfN`{Vq*gHFV1CB1vA7WYQgd#?}EJr9gAXN5ChFcfyRrfoj?ht zI)Q;NG^HJ1g@G>ITqQE6ANp;FK+< z)&H5xQxnOhqNawk(Y$N}O>5E?u<2@+sZ1&cFPgA^r#9m%AT2=gV`8oamHJF#wH_ePi`BYAC{WCS z#~yv5aiHzUR1K1omq_MKGAOe%FmMww1}g>{zyg)~5)s0jpg~Cm zF=2jfel|hAS%UoX{Bs5Q#UnsNkb;~>uVF)uGDf$VszX7wi~*}gDku$sc?u^O7#Q?f zC4_mkEg|v>pw%1ttdhdK+Uih|4J;rvQo_8Tx&mZ|LINj9L|T|vn^^`lIw~vxQ7SAb z#$z!Xv}{69P#{_uG_1)X9?7c>YRK^l3NuxM8akX)AVZfz`s|#7oZ^v2k2pCD)dU3u zdG!#Dpcac?87;CB^0mN{UAaOA1N~ z@*2Gp6PD6e5EGWx<`)zdl$s?dEjCY3T0BBnT2LAs9a7>E!cu}#g1n#>G>4clix_AS z0~Dw>pk+fG@im3`K zsR}Eq3M;4z%c}~@3CnT_D{IFyRR@CxLzO29s|d=niOmvJnVb=kAuKB>$0iQr$O+1` zNx(Srf(mSsFph$tBAXP9qbR7vCJo~#2`Y<62rCOJa~jSOln@h?ohv9IE+{uwP(ngb zey*T|q@coFK?x~A#kqnK(t=8JwY@lmRka{A*kLD3RcxZ5XmN} zK1)yyvyhaZMSp?ZY^9JH5y&C8k5>qv(WiH4e$a--uq));j ztf{RgC@RQ03+htDuBsVfF9-e=%V#Z3#9(tyzMiAc9j~ zL?exXflW|LJVIDYP)m^4=n-tFTFQR^-~azbghfS!#YKcA1bO9*AbC=dLjkmqQlC?h zLjlxzFoX!p^nyAO!rEfO`r3Sg+JgFm`WNR4>WfDR>kH}&@`5HN477creleIVtRp6D zD5x!HI9XUvTSCxKJVMw|P)}GFDg>egb>|A|264VwG)SJsx4eF2x8VDL*oGWM` z9wBTXXduX8v=*90jKqYEwM7Mu1dWlih_QHtu(6=AjL|bOVH53qc?DrEF=1{oVN-2A zHbIkFf~J!NxeYm?Okr*)Ly$`!F2*HjDjp$hDrhRmX>>-ATV4d}UqLQ$eTdHmjRZ|* zfpu~Tatm^5q=Q1#L_9*+M9@T#*Qgsh8zpQeCTy;4B4{RPE;dI@*g{(tQt1ntgC?CU zA|~jtf#k&J2wI3o2wMnR$O{pqZf61RWDGVQXzos7+QNo2($et<5VjVymKQL(C}<@fA#5dR zB`;vKlSxvL7gBG?^9yo-Sz^LA+InKbw%U9!X9(JgM+n;r+Ct;VX0p*!CTMjpXd@mW zY$IqR$YFFwOxR94g-y_Ime^!rdnRc?d#G^^+D=Ro5@3#?y?BJMy`Vivm7v39qvzUu zOcIhXsYoO#gXeH79K<7p9RwW&IgO49+KER9+X>nU@)}JO6Xt;zT>5D^ODzszM{RQ^ zHfYl1nGDNRj*}(}8etKg0&$I_c!aQ{pd+W@5m5Gm4F79S6yy=)(1WB4tvn`q38rdi z1_l<5NKj>_kpd>8K#djfxCv-6E)N5PAPaLOXkt=ApHT}m48jH(?O>_~_3;H+rf?d) z6J!yO6lSro1ow@g!aU3z5nOC6wxHENOw~c4VdyEstZdxcau6Onl;Vh-GLM}jlAE2G zBSJjVP=W~|&Ke=e${L}O#K6F&dkQKn$O;~^VPmlcEz5xjvQgDwgM8|n%2XWzYV1`< zGBB{%JqJyZR7Wu|uvp&t_y4~ZB=iJX#BBD1xD22DO^wngkqU8 z56WPh$1ENpz{nyVA;82c9x1@gDrRsR+&^Yx@MUHIjqM03ykKTv=;dHwU;-C0pqbl# z5RbVwnSp@?&Sj}hLFTg7rh>TO$zO}VObiTy++c%XWi7XOq%b#Jb2Z2)VRi%`WR@@o zf)6rGm=iRL6)7)b#3slo&t<5|B*-qvA;_r_14@0!!33H`XMzM1Xf>o3Q#GVt3`$CZ z>{A3eBg7*nq6l(e6J!_Uh!9VP%4lRTFt7=;2(qj4a0zm#@^Z7W8-yX7!3I?*$Px*f z^VHRYgfZI`(Bv7&W;Tcb2Q2hC1bOCx#t%Uqe(jBdtYQXiVCFJ(lVL7KGnsvgFfYVN zXolc~nanB3I}g-eV;7I)2AgaIn(^V*2AK>^6KqpJ^LR+kVuxvF7vuxy6Od*L@&Et- zb8_h0!ec^^9W~koIZ)#r)Ye3fdeA5vhah_-8%LxOD;r0oHVcR+%*rIl&L+qjDafi3 z3#wH(I3qdPBaK)&*(0@C1UWb(h1rIrn zT!P%-#E9W6R&-|}ISSz!R`Ccl@34tSqU#ioz^a!GO(#Y`AnW25v;F<&|9?oIij6^; zm4Sf|HYNsX;0rx? z7+r>Ry8}VRrWiOTq3YyCA`G8Hbc#VJnEr`#AS{Ii{0t2GP7njYX@d>f0K->IVzr>c zhlxo{Ram$dR3r%s*MiF@F^CCb;LNBcCd?_urOheG2JiTTR_YkOhnO6KW+1=;121UaycpK}PagK`bjkA_FYxwO@oszG|#keZHA z5%^d-SPR7NOAy<{A$Ge$cx)0NyP>vn3vvjvLrg%PMHP<(PkBSKAXIt^N`M({f|v#g z8}W#Va!C*Y@re=KP#s8)#A+Z!?>umDvamso2X|u)--`=#OA2yFffm>Za)Z;1;d?=D z$!KA2L2fSXOhFd5DZ*TA+}h%TEbJh}4XQ8&xg)vR1-Zo|4ecOKfXawR$R$ld5s^!p z5(yRHLYCzMNf@jK>EnW=4~TpE1-Zo?YX1NKFUAG#q=D?`5#zR)!oa}5A(zA+!3!~s zbBY3JIbl4Q)GLJx{{Mgfe>|wP1jQbwc*GP1u!wjhsFN$mW2najT38{W5eF(UI0bnH zc_PIlB7`}St4KpmNWrhes0B3_DS*KiCV*oNJYNHLwp}7=9Fh1=%6e!a_{dpv);KC@3^fP*7e(Uj!xqiR%dQ2tlEFUEb&NfXa<`HQh^kt&^{U1wNTrTg2-s17`L`6M4TPuNF<$DBg61ABxiz( z3%fmkK_w=rO#|A8!w;H=;}+wAlp&yDba>$cnprS}#Ht~pl(CTH?LJ-L=4w=Belz6ET#K)!v9GLMid63O;RTIS_(00 zCl&_K9t{@I_&-xMXaWf$8wD;fnZ%$4W-Vw`kx3jzf+TxIiW1FJO$;1X0)aC^TEW{;-4BBSx5;Si0+|g3^O$O@Ix7q0*uV!kphe?FmWg&5;RpBDZs=g6$x5B z3u+*UM}QMAo0!dP&~ObnpD;6&L;EVo^8s8;Y~m5}A`y^zd~m~^4a5ac<%0@NCg`+2 zsDZ+yz{tP|*$7YzDxV>-ry~vtUmbo(KG1=dlWI&7Y*FBm#9GkE9BAB^1-vIv5Z)F8 zjrDLbX?TOO9CVUTm|ct;G?4)sJ!Kbzl&^y9hVR6L*+6S0xwSdj*x4`6g%*LJkzu2E zV%!!i;4Up_-Vov_h*Q|7Oq?vtA;!bTF_~9e08~bC3bTMXY#f3ta|Jm#jbF2gan9w? z<%Uf6TkHgl=dy~~ftH1U76X9#780?-oPwOLpq2O_tP5I!9|9dQV-uSTS+5Bh?iE8S zaiL{3Xw(GceL*&H6s6*rN(EUZjJO0@B_buFg;}-R#6Zh9AzC@aBQj8Qb6{KD01Xo- zP~Y{#zyJRQS;g!?dzFzq!X?N>e~-YzN{}7Z6M`u1JID$-CPB7Z&ZRZi@Kw^WJM9T-#unseF=XljGqz)p~#U0(`p z0l#>}6o^&)Q>N&%L8m`B1O?!NMgk!Hg6x9)Q|1Zs3-f7j2lE9$%TcEA(#t0A+v zFdJ-LI*Z{kK{j1REpcHXZ3RINL7^#f$-*q+f-Dlzpn-V~K_NjFP!a?$dKVO8F}iJ0 z0bXPZn%f2KX#lsoxLCNgl|jp&n8C}Rm^dIE5m5QX!N+3sl1)5`3!K?m4R33bS59jJg{nTTR5HzqE%iXg`15T5=9`aS-kY_evXXpW01ZoeU>~TYc@m6@Kv4|OQKtmLHoe~p@ zecIZ{&V+>>#I5lU(45LD9;qt8ET(@3)eKP51G{RP0eiVlBHz1Rft)iXkL0rVf5|E^ zU7GxI@zj)gMjf~Lmh8AwDfjZ~gN~b*rfd6bacKOFJirma$OHQ`s z|MiuZqxXbDo^_l+rq2_{gsVk`>5DEtVYYF~+R5Fw z9e(av^El^*QEAM5*YmvB?nK&NT)oENrkWMQy}*XR>nFq#FYMp?Ws9Qnk zzjW`8c{`XiI67G4H{Ikprt*?|V|z`$zMxM=#A?~ZgSNV9+a@^PDPt?V&A3P5(hMzu ztM5BoHx|lo-Nv@`$^QAqS9ZKubdtTo%n4Xg|kufIu z*_XiV?4-mTnHvVFt$qwipWaSo%c)+`1s(tjpr^RF>H|-iK?|$r|3fHifJKs~nls1q8VFwJGqNRNa~p zzPUADf%8h*&iPLg&++}d7dPYNO--d47dC8Jas9Zs?dHfv-Yt68F?+YK&DnK8p?SyK zZJYPc;(4@V^X)#B8#wSL(e}~vIW5biapH5G0C^XBFe9o4gS0;Vs-vjN- zol#Y{1kQNfP0zo-^XJd^`}&;sZ5O}Vw;|!h;%nFHCSP25#}o z*gaHMsX~niRD~n$Epk zTS#x?nca7367RmNPq)9nQ=@qQHusfFm)o2kUHSN9^WBWR=3DY-#r8EutL^;uuzW*) zx%+mBXHgs-1zG(6Pg%32#c(qU{-2lHpSdpS$L0UoiLU2!#3~+fEqHf{_j*V(i{GKm z%$A92>C3;1C0y`z&-A=qo@eKkb#dLDsB1UVxbHiBu)bj)yl&6Rqw{v(t3SWV{pJ6y z1~Q-a?(I6X>y*Ld&B4nSZ&6`2yRd6A+x4@W;rBxJr{7f8t4iCv!z=L!lXOPx6zzO1 z^L^Y~7WVNRmcGv#)%%`FHxE3p*6YLo+MoS_3AR5QRGfk~T!YVYf!ADhpyEu4NwhWx zv_49WsTxG5Wq}G3&^QKYpEzi}B}80aBAGdni%m?Q18fCb1Q!!TLM|z*E*msRIyEmb z6Jiwh(z6L<9kkv8?O6wzjatDW>aEZ4@)J>}BE;b3DX4}j2Cw@R9CSvPUsRCDINQ^q2koqbe%lW&_8Yk<4lj<+0Y{2xv#UAxw$ zpLp6^J7qSH>E*VwhFlB!Z1(Q;wFq6!x*S?XrjCXdjpg>f*h=Xk9;@CU2Rn_wg&ZfncJlLi@BYgFvIeongCt6NO zm}+xCy}SGFv;LspOPiiPOKFRU*53Et?bR-`gq7PHYcn>t=<2UEHh8!4mDt)PvD`Te zCgd7jQ7`y>;a}K>yPn>KH+`hdj{j!+eppFi%ekqxrKdC+tUk@3`}>>Q?j65BF01_i z<(u6@=hy$A&N{p2h38I!?v)R%n71}_j<3C-o86I zJLf=9{?=!LNld>lr0sW`AIA|L7j>~#HasoiPH?ipY~L%oQJ%cqk}kW%Za7Rowseic z?UWTi|Ee$bd+=2nm&Z~n&nuKjcD%9$<> z8FS~RX;09qel_K}?3M=s45d#x)y!VnS$}_PoxS06Pg&vj&;X-fk9i~q3a*o(Kd zhYU~Koo~DL|8#TPj;kiKD=)s?Yjr1T!S5UI9`IyF{ym%9aJw(T{Fr}=(KL>#*6x#a zF>AYuUvKa(594L=e<*O&+rq5PtzX;SsjHeH#y0I>#1n_6(BN3-zYH2WHG!$_xWw*BnvC~LKAqRbOdUt#xnJDuzQhcLch3j_sx_g)a0GJCS5 za$ArrUzq;Ko!;-hCgiUDalIht&m{%zN2#{2p6!ud`I?(8em^UJ-d9PVd=g6 zxhc1@&MF_dd*RUmmTwEsZhoC`vaZ)|@5u@OcM5FVvt{|}+6{|-Tdfm)_IuTt13Q*i z->qDHEWvDcVeR+%E26hdl6NbeCM9Onv6lODPl@h^#={1MturTd#p?BXM}A+;5#q4z zWPt0lKEF@D{k^pB^0?1AaMoF|wyAnrf^)sU8$;2L=!0c{x!W?l#N2Zx8?Yp*=pIdd z={;L8E-Xs4y+BgJAoqrhsqK8GCWSb*Xf|2yH_~_b1D8!Uf3`cw*nX~{T}Q(OtKJLK zRjkg2DLj5HsvGj{ie{zS%A@D3GY*Q&YM)ua@an|UfVJ0zd~+_H&ep$QQ}*um!P5&L zmt9MEzW#&qD~Y#{-pTG=`eD_AlrP0?>OYUne)gC1?~cxW4=Q`pk6ATbxc$53YWJR5 zNz-cQ?cQKFnP=_)=^F($tY_mbTzy~LXjz8Y=S8_`TlUE(p zxdYuD98|yFo*_=gHDYAGyI@k80O-m zpdGd~AWe0cVoWR$`C5>?6->SstUL^b%fwO(Rs>qF&&&Wi2SN8xI>3NB(ka{rfLu_=z`()|9^W+uooxfwTaBt$5vG@^8YIKS zk-r+l0B{|{%%H}=z#suOqXKM(jx=*IC=j{XnAr1YgLJXyx52Ch_X8n%B*A(rG4(9Q zu16hmu7n^{bvZ;2$bbC|3~XSFrlV_eViKN~*~G;q z#x2I9EyGj|3S%~oS^2v`OGDV$I7Aj{Gl@ec3)uQHjqWiqvukVvSx^l!QOAv4$C*tS zJa}U)$SKG*i=v|g2F6JoPsPGn?a^B{gb-K02|X0uyqa(;8$laG|boid2Fb5N}AP16NpbDE2v`L2{fI%#cK@fBv0w}Mv zx5LJNRZWcR9s?VA?Kx=23pXzVt1SZqBj}umi3|)3vY_;!%Uz_(20H^#oQp|gKPZC5 zc(l{mIcDj^v2)DIHv^seVi?TMF-t7poPmK$UfWoVonw|bOiny9--3aGi&tA6p+pyl z5*BujS-hMuCxS;V*!wb#Cc_;II-3xDW`qDkRTsp)pfQja3=9l%3=D$uFY#g?EA{wx-tUM+Yl7)07gfJ2Za-->~O zE8iLvQrh`UoM4}^8S9}aD>7zdC@880g^vwrtU-_ksxaRctk0Ys%GY3IV9*vbl0Y?A zkVP!to`Hc&n;%UhC&V508UO$P=eXd;z`&^C0CJ5Z0|QqH=oC0mnFfk@Ezo(5pfj)J zLGx~0Ox2(yknhC6z@^I~&ILM&0W9Fmz`(_$EyO_j z-wmYY{yjmCQcea2MqW-GHcrs;Fs?gnS`3iA3Gxi8E|6_gAUi?lfWYhorL}y@tbp3V z$DnEqu_KC!S>qsNn*_7QAqECEv44zOVvxCj6OeOm1evNqL7)qoLk2OxDU(Z#+X6HX z$;Lj*5_EMvCk5RsYj$)gc4mGN?6#~XYq3A zh(SW1Q(h9Bzo1D+gsB=7KB%JLK{&R)O#9IP|NmmbHI7O{Vf+OTkGM-CT|O&H+9hRoU$CMA+ zxXP3d+OZnR%g4sSS=<3$Ny*B`D#(&QA9Q?`FspVZk{3Y@Au&Ty4nel82p%zER%RA4 zK{hn+f^B67?T_N(V*#yO=F(9U7iI+ub7QqdkR`thoX2&i2(s#mVpRhl(19J!3r!5N7Qe@hJ&i-S9HcevmxM56v<5Ea9D{comF_%dkT*b@B=<&gr z`VOEIz$CaOc(hr-MK(mefgBS%Of5Hzsc(E2GR$vq6-lW+7ZZDaI4CJgWE^P;h zA>xMSFl(%gbtHHpq7sG@OcDsQp-g>aCP`j4G0yx5kV&9p+88RrOoTeqU6m(PgqeW$ zf7voJFsMV*P9!|unffwy1&WeENfj&zPO6g7QL<04-XQ2CD_b@(HnFKp>=QLg7#Kj) zMr`6!*~F$^ikQbH&L%!pfwhH$BT77C9-9Q4#8fu%sqzvjmmo?ZzU|92+AGfkUJby* z0Wu0QgK=pNhd7(qRJjy5SAtD!s=NS#FA3sHAox-s+dvD8;xEnNkY*D{)++xUKj!j}J+#-2SHVI_S@?2~ZC^pM;g9MPYgVI$bXfro7J%P^5(*T8ObteM@3&`mI z3=HuS30!P!;)zjmDVM-|-B=lVq4gf9#A<|xJ#$~CJdYlC(L|6)6sQbhf`oi6$TTLf znPSY66Xhk6m?b943nV2li%*nGN?;b7m@p3_EzT?pmX?7?OM|7Q;L;Mz^4wr~c`k?o zc}}njxrqt$Kz#{j16Bsmd7B{TK@1dwQd5~BaR=dwL#e3{8XW5oCR_#{{}6ErCtUG>3^@ z<0)()l!Z0I=o+gQmpB5+F=;#l*^2H6VFO%l_=MsH(0nV@4N6GXBHY4`;es33UBD%$ z<-{zf$6a&~lt`jMi3HpqXJZfptrh|G*Lo!w7#O+O#N-p?6U2&R7#O$~v1zesf!qq} z(`h5Ck&}a~sAH<`0_{*{W6FBi3x0FegY^9`7tqrrI_*)85p>VUx30JP3!|m zOpZz85tIfe4DeZ~gpNt|Vqz|y#l*m-0J^D8gNu=YP0NajnFWap-h&zfO8B69K)iMu zsF9=rI-V5dZ&40d#R#h2P2oINF$3-*cMuoW>YEJG$5J~HL@~1#D>E^$)lLGniR757 zL1uynxWEi>nZW`+i&+;mo*|ZHz>VA{sRkJZsci+Az#L}r{3K8>ky%Rtbk!XfGh3EE zGjk>vrfQIz^H(u3u<0_1Yl&%y4_>zk@#9J+1~wh;B4aLwf@08lx>c-P5U(+_ zu;njjVqoKDVUG}CVq=fwV$(5zNI?Qd8Om7!GJ%6hLx7QiP5Usr?t!9kkYQfT3~W`b zY@o1ZhNLY8P*TfcDy|0g)24$Hg?RC7CI&VZNGb%4|FMA2@CVKDFjdb4d5DckLx~X- z=rceY)S1MzKn0tI93$xR1TjNCrfQHuAh&{M*`Y21#hVTrlZG-Q1Nc~0@EIK^K<9xo zFbIOJho%Vd`J3GApu;~JL2d@0oWsVRUjgdq$jj?-7i|OyvoSKTRYBtzd|v~a4t535 zf$e(SMWWmc1;t?1P(zS3@o=D8!vQL}Y7rVZz_uc3;N?Wsz{Uwy!KnZ``95BUyXYod zGic+PHj-A*0y;F!f~;WO&=oZ-GDa6TrQ$7bF@W|NvuUGfW*0>BADbW~NCcsWWl9)b zK(b8Ch!2^k&s~HFOC$-u!%z% za!Cnn5>Pg%ImQNVnBI|<5Y9xcILr4abf?CEV4P}5_AOmHCT>x(WC4km*f=lx?Obl$IdGUg*d3xMM zPeEP+8^k1D3o2Sb9m`@*aJ9(9z@VW9DytyXBAm;>06HrS)ZYeGjZEUT3qWNUyk6Ai zh1HA9`P!fXL4hJ)UWS4qusFEy0IDy`;i@p}%XuL4Anmu>IUqJm?OafG3EuMvx^Dtf zE`r4J1DP1uv^|)rK^&%PkZLgq)t8wc#RMrG&6uiZgGx<4CWw?6n}#m9ECpKx(FEyq zLd?kz0u|+}kvO{CMV%lAgKGw+YLGr~UmR+%5QGMgbux+6f-D1#t%AY@T(^T6Mo@jA zzA{L57RXC^%sK*)K{;IxCXrgO7!xyu_JWwoEXK+#mY)KuOCBZy&Q?n$d6DHiNs!s#1fIS3iT7VAz zf{b(XGbkA{fST6eGz;sKh(pRJHZkToOl)G};BgMEFo+vL!%d-ZXKI--L0b!spd6S7 zZ7nPWKMdL=1LchTa1iGeQ}rT{AK92R z+`*m$@x=AGi=siAA-&6LkQE@efZGwwEUX&#AO|pj!wR(e92{2Qz`3UaF;7xYib=8- zWEPW#1|z5$1x@L&Ac2m{Gca&)Fo3U|2Bl%pxVj;z4}i^0#&t{*P!l210QQ6*q~yxw zVgkDoT#}0B#piNE%6(o=G4@MyIK|oJQZCKmlwg+^0MU}{pizc7oKkF;=5R{0f#qb_ zAab&75IG)*gE_=F`Z6Jr0`esTgM2si_UQkhHW@2J6XgB}L5RO~E1AT>js%ZH@dz=2 z&Y|E^*u>7jATC~<4w|eIVg`#vDl|-+!H^Z5$tBMPP6DbIKEuXMKs5u%ZGtS)Y;wt$ z<_NNYTnA==oCjubL)^zM#tw5IQ9T^6A`ejX$uVhof@sif5ndn$Sjrp3N@8NFUIDsJ zM|(;AP=~u{FGw%=*gGcX;#Z6eP<;%bF>%los|nPO_aJppJIvsAM1qV4 z*%1q3fbBq6sKZ^vDacSz46}oWiGi&ctS^tLdJCw|;x2LqDaZ!(>Y12pSAsm5g-xz{ z6-Ww)HiB~4jog68NU$7sZR_!91IsM{e_%K|Z!C4Ua6;lZYn1DcN#Vq??D1x+l2rtl%-)NJzlb$KA6e9)K< zGaG1`KNmMk{#sD=z|O8w0rC{PMj>cMnFGud=Vb@a#(|2%{34LChD_C<)UG4I#8MO~ z$WQ?Gju@}Dq##RvF#`jac)SiD6HC!dgcPUcZg4-2l^rxN$tBFj1kMyX-0T{ajNr*% zVO9}gc0pDhPC>TfQqZhDJNO(RaG4D1n1SL%kV8xmR1bjWen5M##0*0PS#_MnAiXbR zK@LIgiSk^=DjH=B3|yd1KA=ukWPUlwIPg9lP+y4)y!!@1a)VCPF*>fjK#&b&HYd1- z(Vis8s>313o?i(X=n`bh2UV7!_8qqY3qvTR`e6VSi+@4cA5ykp#yX3REOY)mMg}(K z{6%1L0hnCE$iSv?160K`vuG4EGO*p_WYJ;OxXH-C25O=}>tjU*EpO1V;tb$BIdqs9 z7|g-*|03MX`KuTi*m#)pr!q3Il^8NGF!3@~gL0CN0Vh*6CGOVE*JoZw_&1)3G%fJF=!nX2Y(%dZ8Au!FWJiwVN2ML|}1F7UCW+Ghk=!EL;IJc6t`?1HS| zrum(FJc2Ab?1C&19w#Klfi?hg<*#96U}NVI0VM)Z5v8Nc2~Oio)gWGe9VkIcp$LHz zyLbdRxq~!;ibEX(K@J@erfLwoNK}ZSK#)VD9yD_&h9m|t1S}3Zm{*5`Q;;KnE-0kH zr2uEXEE5A8B#3nMSS)9Nj(*Qy&&U8>nIyynUYZ1nR+NQD&$Ku|D|flT>xz()HLoDI zAg`DpFLY87bS;LMp(Lct0ZH(I)1x4dARp)+gG={#1i5wC1-T(%#ID274w(QmWMkK8 z1P=m(3n@8JAq84z#KbU}!S(_J4=BkpF?2Ho--EFaGuksTfyJ2(n85cFg4KXiv92|f zcrB=cW7aW*I0dxw0cl3RSN1ln*xA$bvv22f!Q z9y_#WU|_HU`46SJ#4KhYP!uo3P*7AZ1luoFTnDZom}+-`*0zh(?gUZH`OV;wNU$A9 zO(A&^jV7#iAk^ToLj+<66RI8HF^T|KnqY=_kr{kOKorE^Od3^;43J^++FhWwMm5N- zIwDM>wR=EZCXE_K2DaMWpnzi%gNTVixS;l*4RpN$sEl3>@;A7QX70-b+o8u@v>hY} zZrF)&X>&8PP1Io$(*kWwWCN=(dMmDlYz`>g5#})AGKUG9IiT?vXP95X-q7VPdJeK5 z)Yz|Lss?!i;vXYnCXEh81~y&pB5`4cf?|jQRj>;22#EK<=X&Kr=h2v8=D8!3gH_`( z59~p3Qs-i-hJ-E11z_PQHZd>_9&KYnu^2u-2fFjq8kEjpb}vTQ4T%CVE=crogU0GW z@dmMn4U(<0csRte4EfkNG9$RyIWi-;*+I9Es8)mGRXhS5mExcw7?7ioX^=dK52nHG zCRPSeHDv>ui_zsSLW-YiP>R;&E_w)e89eG$iX2543Yhyc!NYZ6&w^PRZJnMmg zxL#+1Bm*XtIMo7;D}e5X1C4b-6zg&qEkrUG6yaiq>c{~MO`&WMd)Oj1IzW{iI6fdo zfbG-z1mWmNGHFZz)jZ%Z2G>SRkkU;Hl2JfoMWFNulLE1|ydZ@uQ}Jd{iE;o`qEulB zF;#;knDeiIio#hCX;9(v8RUL&;ljk6e;L#uGXnL|L5e}`MNk=H#=yV;>K7DGf|R<| z`xzKmYC!}W#8fnWY)l%U20Xag0m^hBGeCn?NM?W?!=$kZTwsIN#)8JMkmT7Q3i8*1 z6@c>!=;mvPJD5vBZALCO9U+KCY~Z$3ekZ7@3%XGeVtW^e+XV6=Vr?)pSS3UkxYY&9 zj$p4EL4C3X6g*}S4s-ri5DzA`6U2c_?E>*&QoBJMxYQmH4<>aQ#DPnl0r6l`XF(je z)Hx6jw3h(X#${sB05yTZdketrTow&bGZ-|a336`!evo3g)&n4(91}QR;7ay_1mQ~d zfq0-g#ej(c(SHQRA*f>rqQMOmEr`!`lp%EfVMYcvc~d=TK!aPI`Q4z_DtNvY94{;k zpmjaA&@v2>oIu0yjN-7tdL~GMVc}xa=mGWIdO@urK_~~**abIrx!Az{I(hwkaL-Pg zgH0SN4zU{4P}Y6T3?BW-KL#q(*uZhb0(QJk470*(W(J1*9UvKb)BGbKIv*6J;6|p7 z3^SMmA;Ci8k&uN<`g&r_5Mi)I8hs!)f?}UpEGr)rcG?Ea3I`hDW*b1vW=#HcX=WHKnin8orhfZQjRe+e2lpz;M&ZrOqBCQzK{@IoRL>^)s} zv0hNZ*Mf>o1ecn9nP5TCo&lTXpO&&a^02A;cSW>^AUhYxBqAmS60leppW$qWuBa9ZGEf@BmXHeGgb z7-_R2qJc>)ACyy=#PUJ8f(aU$Od6A5!NA0(%OY=}%><1u$S@u_ZlO$2mVq)sS%e7^ zY)sH#1GW9rVP!qIjmcCbD$Y=#aRO9~7Ab?6r@&0ml4K1~lrn)AxoLos4^!Q5(9xq{ z7uNj&F~P2^`v+n|EdC2(LM+bG0L3e)$aoGaW1~PJf>@ry#9Rv&mSd`h(Jw&CKs$QC z3^}IimoNb^LyoEX6-)rkkYlQT4H7707R%CyuESLa1vzXTE?8EMsrn5_6$7&Y2mCHh z=DKGfhfV?IO{mUDgid}&jj0R_T>Ok0(;(Dz2sHyj&4f_1K+}G+L1V07^W~VT--7Is zW2$}!rQd^SkcYqwIi~6lAOXyP01L}8Re!`T4HlMTs{Vvs8Z0cwRQ(ww4K8C?85}@& zNQ2549cd zE)P@DQgMcYS}>o98A8i3ReuG^gFFdl$T3xag9(5ca!eX?K~)QAESQxco)L1_C@3u; z@`@N26Ei4R-DYH91MkrQCk;0Fln9W7oW?Ci(2c2}RKX^PETjQSiD*Kg6bTiQ=K<>k zCqp)Q9h~_+SW`H?QMg#6_a4uq#0b3-2 zBn-+?Y!YB$c?BeKP?lknSHP42WgwUY)L|N+(huq|m=LHWWMa}d2r3sfo-#79{bQ^J zr#*0=A()YY!5)+bbh(SxgAzBm*#c^-gNk@?fP;!LE~aWw$YwFK$!Ro>^FehbH#;+%JdegBhz?K%tMQDHfh`Lm$_BbEm6w?f6pZo;kegEFjNU^8m^46j zFp5VWqD3*2v%VPpX1IYH)9P;-!r&5{><2o8eTgGh&sU;$8ovw_<+8uLLWgNE`T zDS<5?lpY+qz{)_u!3J)Y7}r3;nk^p`;$Y|KWHNz+n=Ky{=n$bWCJj)Cv*m+Gh>$ZR z)YR?fA_yJ;rY7|!0hF>5ys2rbakEJ#f!GF-SrJ^| zO<^2HXF=;SnHfqL7#N%|%w`6iLj$_6sR&W+fcO0$7H23x5@TkGU;>{)a}gvCk}QTS zy(nG)Du9`}wS}43C+di>F|kjCY%>F|z-DHNFnZ3WwGGs;Kr|&l4Mn8xCAhp~W?|)H z(YOn1udp&iL)$C(w2ETTR^*XKsK{4Us` zATuKw7#N(PWg)_qtm2Vepxd)RUW?>n63a3)VB*#m0}06+u*+t}Uy8Uihg~w6n@v2D zi%rZ(h+Qnp;Gs4*M8O=0sQyP5)(FrwZ7i(d@>9zRv=~r463kHp$${%+X3+j!2GANu zG0@_CE>K)YK#p!=>dQ3x07++{aU&OSJ5!8X8(ED4=qy*GcVax+oZyN9++dY6`m8XA zfq{V+q?B_aG|@th1J8@fF)%Q=GB618Gk~YQ!L1%HAqWRP53U88b6{rBWMBZ@pCbrX z#4W@K*1-gsERTvPUIgv``cz2@#CsW~ydlWMHx6Vq{=ohp_uHvkX|+GqpKjTpkERjG2W4JPZYwFydqq zsRd~Vtw;pXeVH7Qyqw@+KVcS#E)GE!F;1{HCP5akVm1!YkX%+IHw#CE0Fwo1bd9MR z6zuu!pg9g!K~`PqB5g^A0`{IL1_s8WP)UXYjm4mLFLD}G1X%^yAkGjI1j&FEX$uIlgNy)agRJ;t6J(3vVi#lsxk(VT z!HZoi%NDd}mPr*HbZl7>wV)tm10@WwODBR#Jy83T6`EYYqM*@axDqhO3KHnhzy|l- zSQsoA7(i=#1rLXW@m$iJTqHgCJz&v7;NRCDCpv8&MeR%W|qMX(3&dH z(tQSL16BqfCI$vCP#sbIAGB70NkogOnuU>p1+?gw8MKxN5wcutx|~enwIFrc{A?Pn z;E7nM024$z50gkONVf&(_B!xT6*oH@csPnZ{}5!zxKI*4Mkkg94izSLa2uf(l&VB{ z*ufRQypM4`cx(~uJzhvC2(y6qN%LsCGjWOuvT%aD%PPo{sm;s@o0(!2WEC~$E?N$< z#1FLAn1fSHkQLE-&0hkVnGs|WWX*~M%@d1d8Ej_KK=-HxXpb(`A?d~2^1&_jM z3o${IvgNaZwg-UJF~NcuqB?&y$N*3{-wP3D14)9|AR3f9p>bFARFa_pnxVQG8Q8$X zw@`j3j4ueC&H|0it8C5-mAq zjcK6VCC3aNCDD>&28SDb%MYXo2Q8BUjeUaVJv<@KWq=gupf&+w)`*F@mJd`QGP8gu zm}+@J97M{j79v9N0oeuneq90CT`qf*C{)bN*6LFVqUk zV*&5e01fqkR5Ir;14+V61g!^lXOB_O4c@#iom4H?j4OExAA(9|oFh9YPJ zwvDNplaYZ%SAt2r7Q|rEkN{_UkVo^u#gq|KHJAe~kWe^wOx5fl|5tM{GO+w(0fi^1 z-QvT@02-SY1cjur6l`>mIe#{&rws0bfCdBQQ|wglPmgHrLFDs6#<3&m%Ln<^Xc041dIKn} zf5b2uRZBxWZL?(BlR&Kd!UiM~vuDi{l* z3e>y-1s*g_h(ScbtpH{gh*F3Uq#b~fs^H-bN_c&l&=3c217c;56kuk8guMl5(+kKz zkX;Z1S;3aDuto?lF{y$hm^A_%Ppqt<^F3o(A-4Br>MLW@h^j{m;xJ~G{628vgSdtV z>N*anv%n{Zg4$fOe!bFCO70}G1+ zsPCZ94yHgiA%ko4S^-d*!Bh>RYK1`Mr5sZ=Ka>Uuf<|8jp?sLU2#61AFo79|n5sdv zn4uaoQ#D8lQ#D8fL^KjY5^ zAZ~%|Zv)ju!Vm#n#iGBU1PNKcuL^cBdj!}Z@QyAqgI!G3qM(+OIunEeF-{Dk9pX&L zBK%sATeW$ZATnSc6T|}$#~MM;CeQ_y&(Qn>y2BTAwk|7Z6AZXB4qmCv!o|w19RcyM zn1LXZ24q_u$j@R1Ok!H>5Gn8&Di6d#5L+SQk<4t6COM={9m&n43JzF~NU%%T#SE6P zg2IlKfjahML=}<;J9802Tm|piM8J<4_El7})ZdG(c3Ayh2if76a()S*gP02c>lqm0!J^=Oz@T|8(7ZY5@$<4-Ykjw=32fKb0GmC)_#3fJ%L1dW0B`y=hyUY;JYC+UN1yy;WVZaFy1`iTX zoWl%qETfpgWi2K)W)=-oaIOXIi=GO(^Inhz>`#US++6DyL9T4rEv5VImdg*qsqfzu%?LpuWl1E@TMxSNX=qRNm9LJKf!i$P={ z{76=)SGZWYS=m4v=L}^bfdsaKBN8^W0It5+1fYS!#u^D4%u@#~$AF|A_DFEbftV_$ z5A`2AsElI)ANT}Hzf4SGs$AeeV*{(!ii5-vB>RHA3#sMcT?%j+&CUQis|=jCsudU+ zSeW%onW|+$IjCBWk%7gSNfdM=x;$7w21KfYWx+WRq>K%^;f|>qSr(M-K(g#mS-GSH zCb04H^6^OtwP52^Ap!yswIF+$szHKz;>;iw;*nYLnOaRus$fBoPztgh=18y>aGWrK z&piP9pIO5moaV%g*qN9$9GF0Rf8`+7YQ-^uy#w)DBt%d$IYMg@)DDP}SB^FYC#l4 z14MJAc)X4_6KbUKh(pwIKqCzjZD{NbW{A^4=IV17Erkas3u^=y3!4EOXeP;!8{AZe zoL|H$9M>zUZVUeQux5*5?%1{IEKOw3Rg z19*)kXxtxE20?Nav#2qvi~ysy2(y?GE3-VOAwxBz2j^w3*}uYK_1Ovuce&G}xT{UXZ40kU{w= zAT35r5KbC0CmqC*W2y$})3Reytp*t+l>jzR%L&St=Ya|&F@fdf<&1eCj?JG2(hpj{ z1Ti}a#Dz8YKwI~;CPB2wfp(>ThDQ;^DWE-di69-X@P|>g0jT)V6J}zr1+k!-^Rqx& z<(R;-pg{zXSDEuOL834xfVR6r%ECvC3=DptGf=o74wA1o<}Ol}Whf{HXF;f-fXyuM z8F&>84BQZd#UsU&c{s$3SU4mNnIw7GIb@O&xFM>=<8@fsg}|LH%Y> z6td?}1&2K-EXCt>EFccf2L(JYl${Dz08-2;FOUpX59UJlbwfnt1t2!b^Tb19021n; zaGTBqx{s4ZkOk7A0>z&oOI8Fp0k8_PfX?HxdG@fj!%W~ z&(CtdUw!o`|tCBusSlf?bi zXs06#D}d7lNEHKEjumw3Ayhr+*h~-xsR3=-0NwftQVG%v6Nk|tc@PGv0b!6jki8(a zApOYdKo`4#EdvRH=6TRC==LLY3>yCfjrM}f1&5Nt@Bg4p>!4X6Z$<_dc`oopJ*pSJ zFu~4p_dyo^3K#Z87XAho_Cpr_4j1-E7XASj4ghs?VaJJq=5tb^Wj>QeEGW{MYqLNl z7ISe4sMN~_v5WIThk)dOnBXfaA+3~n2)}`W0dj*?I2u0!#Agy$<*JQkWME;djR9E< zZpT38jr~D=Esbm@1~z6L0jBBQqJs79I{)W>B61&E`SQ`eo2o zWMXI0C;&AdAk0EAQw$_p1ZHv8Bk2J#h4E!cBxwIJVtMo>XC#JGQqTA(&EsI3Z0A57JtPzGfK&>y;{WJ5mZ8cxodoF%8iDSlCsvrJf;Uqnp|w)qzNi^ zK+Cx&GcYhf?^pvx2U9gDy&D=rLXW8$5>X&ANI*m6BgOJ7K;a4zg9Icv1}%1hQaw0I zASxjT_kp7Vk71Q)hG~~ERfFO|M-kN>AQy^9LYrFo)!mLJy{Zf!GHS(Ak*eoE`JOd*GQ#B|dMM8okl8cQATqr=YOC)G+ z7?FD-xtOZKISg8QKmr-$Ifx+<&^cFdvPD+P2HKp-#-s|?#})y}pQ_cMWCfZ@1<_2Z zV0W-ZK+-jsqre6_!$lC{7Kpp-J;0SF$jOpMY)s(D)0)KuizAR*CQ2tEbHyVjCf0_5 z5-upcvM@w3Ffasw%ED@pAgWr4h>3}i{w_Bpn?OPZBE(b;%2Di-RJrCtnGo5GxlHU} z3!s%UH2jal#yG%f5uDE;&JqK&VPg}Kj0}*`gveSD6Ix1ul|+K`JCiCnX+uRoDO!w6 zTMyy_wn^X`E}k38h3s6_XBN|DhcF{Ekn{g3F&>akQ2ytD>Vy^t9GqbD!8#$#$c(uh z;t@QM5gDUXkTzr-69YpaIP5?ck)VB(pmYVgB5h>3z+4wc|y17r?JL_Bh$Ag4nrLTn;LHRnW!0E8g;PI!Awjl8Q5*H+@bwLN5 zLF!hB0JJ8B)`Z|<4pMkWa&-SRt1fH)??m z%4VQr%0T5iB>%BRfU663&}re~kp4R>1L&&9U~ql_c?Vov+1vpo9II=L3=Cpg5O?Yt zV;T+#Dv0wUS@O|~caT<4Sq3h)4cVB$Wj4e#N&7dTGzD&JsB&4}2XU%F^|6FCc-1C2 z9M~ekeziRal4aA#XJTNp+zMhtYc!DAOx2(QClV6$`8A+}v7m)8L?{wk5`*$DQ#Gj4 zHgJJD!N^)$6k1Y2n>mQK4@kLqq$)2sUOB}KuA?f{R)X>&mO$eWT--~*3Unq&GlpH) z!J-ez(V#pC3Ac&hO|bFMniP^IU=D%QBjPaEgBw#-pjmP^7SOpopooH;L(M}VRyZ(X zg##4%kRX7>wamZ&|Cz1C{{8aJR`bwk zgM~C~1@ki8>x8NFve;CU5eeSpY{(9aM@jn@a5RFF2D?EuEZjkfP&|??k{z7* z)Yv7!vsGYGXtF?yOHkZN8nHthti~=Lsmd*80J^gew;pKtK@ya<5Agvn4ryNznYI#P z-Ur1^Brnt&7EbXKV>;Hn19q6D^@Hn>+s6)fR06OrKfgN-}0JMM3#lXM-YBY00`|6<0_nh&-wfXr85WMp8F=Pzym_5W+Y;_`ChFo9Z#fUuM-L_r;huK-%)4|Y>+J%SGk z+1dtBL-!DqSZyOnLaeq4L{)=~&2I!%X4N1Ap-hljU?zCY#};^h0W97MRt?q&VS+V6 zm|)j~4XthiMJ&h%k<#E%FQ#gUBuF(_QXEBsSt?QrtWFGcsy$RK$iC_pP}dKXnAoOF zlmsgQcU+l`ZZd&wVyXry%kKm`3uHQy0C?Z?c?Jg1ArpdPTo$0|MW$*{P{5{OxS6U! zA;mU{heK67l1Hb8U89bPfsGepHfMel=zI+Y(3L@vQqkaLgod($EYb!N5dW}?3$lR5 z#>FG!1zEt3K6>Neat3|GzR1KneL8oUZa6%M=eIv*+30$fOvP_JM-~~0@K@kkjdq&sAgjuyg zszJsUVBm^gV@#Ee8(r6M>all6H(EA07LG(bZN zS{$6lzL2PpfW=P)EP_Dc11`eA?#OR}hY`5+09ywU)F=l@L81p@m=wBUY#L=?HApJm zAn6BODnMG$pfcMJo}WP}AEHETE+ktpse)4+c%~AR^w>a40KnM{90ttT;$8#Phyu6G zSs3;~>I=|4IpFdIWCn8vn&F^1Gmr!ai)7@bIV_Tq;4H_56f|s;j1QpJ5YznfV z&c7IwDmYr%V3{)lT%<9JM}jjTHzfaoUCoZgG?nwqdHJ6#U#%k zKT)113Br*|265$*5+GbTFjor3mFG#Gn2-VL3p0V&yn@CwnZRvPV~BgTz@<5tHYb}@ z1Q(NdvH$~0bALZY4j9y zgh(}LFc`e33bYX(Vkry6QqUYJ=zgqFaGwd}m%dCjrfQG}!9D`@!yu;jWkUQ5a+ny8 zwlo_D`#g50YLJgPrpWViM1qQA(EZmDJRA@MjP8i>YP&%k&p8p4#l;MbnW{ksaIy)q zh(}I=v@pQze$bJ+s)Zm@TwXws1!7zyh!5Uz#RRUqj5dPPJ1avn69YpSlAF2Mz|Q3s z;}HXwH+~RD3$jcC6&5;{9IE0GJi=_+JnVvO?1Jo5=7IMYu!$LpK@_qJvWZ7ZM5_w3 zPnjghYH*WXkWG+fo*)anbYe4Ft1ZqcVZg@gqKg(RZHBZP$ng*c2( z2yzPwOc55==3o~DDVj1*P*7D^NX$?OVgxvB1gA_96gIfWE+`}@Fb`zCh#-%uc!V&I zumH&20#SneU=IjHiAM;EfPBC|1)LY-1-S)9piJ-(gRm&bK0$6l{wZLo2tm>L5YxyO*}#(8eEKlW{g0kE2r2zXbA`^m5p9ON;*(+$|fEuHjhm_ zQkc~Ov@()eLXb5|JYtHdo(*XC%@pwn(C8qfEH>nU(86q>F=Rm&u-Yk5T0CNkAe*W% zsC1d9Z3fm0y6O^SxgfiEBy!Ol0WOgt$qQzNAnTM%b3kK{prTgHru6^+{~VyREy1-2 zWc(Ox6sV{Y=9r@M0a9xSav&QV2{jn1GD1}tMH*r+2k4R-Mg|t~NI^(_174=aBM7Z< z#3PNCaEKX9fS3>QFpBdzAjTleOCWoX1L6t^_9)OeHz>G;xwKs%$_2T^Bc}*+Yimg` z3vz-=JXzxpa4E88Lx} zVKjO`#R~i;KyXjJwj0!P0Ob!>2GCtZpt6PuvRJ7fGx1X1DU|i3_9r;Vn!i+?gW=z z_{>0+12scI=5sL13nX8fgDMGH{|S=hWR{mmzBEUx548LdY$w=z&`Dm1Us)r-fdZNb z1qBkM|HQ(O2pLxqWU2;jO z24bJQKnk)o@&b`ydm!;<4s#ohGy;lYRCmBFV!kv-ON$8{>Y!0pNZJH-Jppl}9Eua=ATDHu7|v7;O4E^`rXeU=pj^-zL9qY9vhX#6V&DwGBnFOnZ6&Df zsA^QfT-FG%Qs~-xO9lqeK4w7_E5SLB3)u`dF}A);$V4EDO`u(+;FTYcysN|{rUAMN zM(Y#2hp-CNl83Al*#KtRfkuy3gPFD<<{A)_89YuPQM(Y7i$UvR62PMf3=B+6)gTj) zq(R$~R)X}1W!0_#(bXWs^4&pw&1#Tg`8FV?NbOpXq)6>L2(=zWiPbI#QPm)qKo$^y z`XrU`{wK&Jd4YWB3RHd2G!EEwd4YWJN>sTdHo4>k$V?^|o4kCi4tLQ`c*}@Q0ko_* z9(|7+6&77N<-SVOki8(FdZTX zb_Wwv^&&%?|Ef>dUf=fkRQG799T2*nk9txE530Tu|8! zRvI~_b_pnM>gFK}fxLB(N3BR+4tB8-)OUtBdxSvoUN;})jw!WE!H!x0;lP~ZkKr79CV4KXfuKZ$~HGy!Hl?BK2G$_rh?q zixn-GV<=d}E{?1Syg_aeyF}4Lu$&}B6I2v(D-5_d&LqzR_AU6XV`c_NCfK+iD7o@- zx`HMIKobR^2?9`~0CY->8Y2Tk1|tK*Iz|SDH)vRxfq~&OC^>%sC1;Jfpk@Y>#ykkM z08CYb3I-j0NNJV5RE9Sd^$`ojZWs>IxI}elrK#?s8PIp{vNa;=zoKM-r<8|1X z#KDCQn|LxPqk&fjfffRSF1G_+bg%7>Y=b1&U~NyPy5o!tEReFR?gWSlPNvXApv6?Y z0aSE?OE?*b7O|qYatsBK9n%^sKqn4>gHl|J31U99SW^{dtzE{*z#_|pD#H2AF6tQAj zMV@fy!IqmY2FZZdf3u+6TZyu+ox7+Rqz}B)4Sl_z2I#sqUGAcOkP7IUWKfj?8ny;4 z&qGf0kTedu-Vmf194Am|@M1Y|wg>66U}9i{))4Szv7lXqT2+v61gY@=sZp&4)qbp5 z5w##%D+_g{B6R!Sa*z)}{qu9sb`Gj4#2WqAAXkBpe?zS0msNo6hh<>}pRdYY6bKT6 z?1$AAWYSm#iVb!qjfJ4~VPaaKqdP!ZQ=VJTnF;PAYtTGByO^N?#J|ie?BKOk;2o%J z>=B@CaiIE}Ju3oSkF$a{r9yT_fX&ri4KXU;3X~o|yK^8`7*7T@Iv}Y6lvF@B(12vb zjkzGDE2vQ>rj^H34HA{-G3G}$2Yj?r5fdZ^c_A*#2bW-4keC8BnnBLevSR`VG?NDC zf~_pjT4jixpxslT8XJ5r8>s&Pp0i|QU;xi$g4PCeGBAJ-vIfm#f{H4B1_toFC#V<_ zXJ7#LPe3)TGUR?s24e;W25ZQ9JK*#7l0jS385kHqeb>bd3=D@E7#KinPf&{z zG{EV=z`zJ=2*Mlzs^_2>wFbx=Ag@|6FfdGFU|wlXxx2Xt=)pV0|DGrVqpxkEjJvFg;9Q z!AOSU33gVsvAhBu?2{RYOmWrqaQOr^hx5x`a4A=!y zELM92L`j0p(Y9blsau&L)hbgpNNL?pkiu$^@+oZKU05Kdcm%`%us9RgYNK6D5FN$a zKy}0(kT#K8kP%E!+oT}2nKM;`J)sKLtSZb3HB69|iT#qQFk9_mP{qkMhY2hX@w+j& z84NO$8QgqS<(B^tud@x(>}8i1G~#3u1MAb~gJ{!bD`sZ^T|~(a>X04+IYt_6eccWa zyBZ`ig@>5~9DvZaBQpm$q&VxgBb0!a`hh&m83A#Kp&Ha&R6nr8{J_ps4RZb*PF3+p zUeI~s=$?QCf<^n^|DcFa) zhaIvw%JUnp zWfEkCOtT#W&-yblFbH$X^9yrnXTXi%7Gz-)(NsuccW3C{lxFDB2CsX-L}7kGe(;qr?1KDLK*coJSYZJ{etAv<4X9lLf_ze->p(N+3JQn|^2^J|Cq;m+ z1_htqVsuN}7p6|(KO+M}{3KyPaX~?Oe$XD)Bw-;zL8;_aVL_-GK|uj|&g29fCJG7} zU1t~M7i0m=6Y@hmGf$9DJOXrQ3Ugm3ctJX-R(IM_fAo5YQ(gE`*`wDg39S&#*6 z2^XqjkXeE(258oZYC*NJf@U_rLopC-Y?HXz#f-$jx>zxFfyUvO8B`e<7-GQZ0Wwve zWn^ICX4esCW+|S?z`(}C&cu*NOS*@m3|7Ym+iW~x2~u}hk{xCLYtM1YASe>PZG8;X6PO9bPf`p!V~ zi9z*&oVXZS3#i`?@>4ui{Yi*=ke~WN7J)QON7f+6RDB*ahz8pG0%qhff!dj%<#rAl zD?x`ZgG3>vfL0n)u_-eHTkTy&1{NlX+WR01e8{y{6D}Dh=Gr?T^W~VTZ-Z!%Jz$0$ zQ}qLw0GMIKR1GpW|0$@TF@tcJ^PhouauA*t_>^RX6SSC^!A=3S!9i{T-#!Xv$T3yl zgc%NI$T3ylf(d{beoV~ZYqLNHd-AbrTn1U=g(M~d5dxh%2ReH;0TkaX#j98t*fdUn zx>YQ-S3tgJF5b)n8po==1RC+-f%r*Bkf|EPhw$=s7(q8#g9S8BGcmB`?_^v#PIQkM)^+3*X5U;%e3Q^YD>mZ7crS=AhW+{FSYK7ecvH4hw_kcDKUIla5 zAe?Jp4tp&qnwgl3moqc4sq)lbW@KRD;Dtm0C^|rV2rqvrGblPh0{J_b8Q8eAi`epA z7#O%p0vQ;XxY_gdnHku0Oqi-c2D9fYFf*`$Z*I#!%)r2=4z`C0BEhC{g9((Z*mT&~P{YBR zK{o^3MFyW~18P5knq;8#gLI8%^+nJLHlX7^1Q-~=4WC+&2*kBImJqu7H0anP9Ttf7 zOkh1oG7x6|K2Q#4*0{sKz@{yPqE_QJ11R-?{Hy~y#1O<_&ffz{qM#Vnk~ZLAXlG<# zNP(8WptLNZr^%wR8Wi4&Ow}L(U2&#rP~z6%htMqf_dr3f%_PRfW(hix4&n?QaV7|Z z8Jr69cf)Lfq#jGqh&v0o5aWh;L>HImy&&d5Ja5ZX4NCmX`Ma4J*w`UDk>nvvXb^xc zX3kdxWrDk)(2&5Q897YQoD2_`dtB@~Z0wL&g_H?8JS@!lav+1(fX+P8I1eh~)S2^z zKv_thIiH`IflX9T48q{yPymf=#PhIlXsl&m;JT;D3vs88C^U>%IP-VG!bcm_i2_B( zKdE~RS`3Ub3=B*R*$j*MAbANCJ3nI?H9=$Ep!PUu9Yrc=KTf^@s62p#HaDA&Ju{>% z;Ag772P)n3cY^Mm))r-kWOH7a@Gg)ryAB`p>Ns#~K$}sFON56_M*^ytg`G#6hh4)R zbgvrt9!NHwOb*C38i`OP9MJq6$N{~R&4U*-PzFk2Iz~`6FyFFs=I@02Rt_2j?6`t} zO-BIg6%Hn5c8!~$!Wc9r0_rF+bTDvEWbgomg&Y%Tz>Q0*j7diVax}G=AwQGGI?&Y^ z>lqlh#Qw2piD@lkl8>)_0V;ICH9xbiKoO@RLqU2 z&p>r>9%yh8`JxJNu+)O(K(|$Z)PR}^&p`~(T$=$icx(ui=b4x_-Z3$-2{1w~To5x< z(iUWfu*D6arbVr91$S{!EI%dpF z)gbR^d<2`zR1LCLhl5#TBiJmaYLL5h#33}ZMgdqif!o%19jr zNYE*;FfuS02s1Is$AeAQ*aQwi(2jI2@R}x8(7Ct_X$%a4;1K3w>&ujk;AZc&WME)y zcnMmoAXW#W#9%Y2U>>`8q`cN#2vZ_b-X6iUnhWw9sIC5!fdRBGUl8?3a3=5#DUgua z3`&L%7#P?D7__;V#Gv8E0CBmPp&XMK_`GuY7`;c@f=m!$c<{oN3BhGxs;@8=Ed_-< z=r$cLZ80V`xXDQ3Y-0M)n7}^B2c;^|x!;yd#alr4(P*o%voYsy1>HLcvDAn~luMf* zqMA)SB7Ym`jBGYB{TuAy!(;`ZZUG0jAzSfwaPk8sG*FB}!UJ*_BWRvfj7wV*Y%kkn zW@GN6)u2=X9-{^?RR_!TWg6XOmXFb6WtP`B<}SJkSHi>$PV-t)b*4-VELw6*4Pd&6 zNtX?r60|hFfKJKU2`b9On8DYhYWcw>nV9-AHNJuJ#3E*x1}5;lZ@dnl#x4d1E@m+n zh$dzhh{8=63I(7Fnfo%KN||A%<}raT;{lB%AiD#6X{gpLX1E;8N*;(w5P4>eUm%CU z4syuS*bU0>dqBiq5U~$*yad>@py?2KT{#T~W(LrZIx`EL1DYFQW@v@xDJIccUnT|? zCb`;B5G9&b8wsMJ#RYc};;4N{#syCd8447MDlrs5Bq4|Q>j<#ObLn#znJY0AKu-B# z0^dEZArET7G1vNoOl7@T>j$D)F4hKtXg(IOt)RFEorfR_8iZzGU?Ais#M!S*%+)?j z3@o)Ef{D2rWC_G3=IQ{DIEY|kt_}pTK?DD8#kQ)gZ@1e85}{3N=X3F;_=`)Po2n=4w#zLBf!^ItnBXBAA$~qd{yC z!CW22#K5AX#{^-(R>Oe=AtGW-U=?Bz9&~AjmJ<`$t5WfoAm_z^<}g53ibGF~(duH> z;b&3>yG1;q79<5a7Yszp|BHw4{g}Ygki-l%W*M`NFjN~@9965r|L_0*Lv_nBRmXtx z6R5ZcGvpw~fqQZwdq8;^%iZIiR?b7l^;43p%(A9E@5?Ow5p= zR0aD{ULfHTI7&fBK!Cy=vYu8ej7dWT)ZpNT(DGdW7_~r~U_p1p=|k_G0@cDW8+7C$ z3U#<3v^77Y|JFi#RdvQkOgwdP%Abuse)q}!i6SRh!8VGOfKnS0z@2q z*9qu8WKem<1WqVA>=0T@o{Nh~LmK2*R(V}6Z4)^rZ~`-Cl^5aCR%6lt_dUQINhS?u zh&mB2Z5}2$4Pg+ES)QAVP3s+#h8Qygo4l@pK9t3!CkJJ5>xn>FBA^RiAnJ_SnKVG{ zA}uj3B_{D&P;vuB3YZ3sp)i5Z%gzARec%Mi#ir}Q1kN7Z5QppXL7l_KF3*z%I!FnW zg+%jASlLDM%%vcTKuuv#wvg8a@AJ@R5eK!P*tC+EG^Cgr*mU_Iu`Zeimevy2ih`tF zx%f-E%wkzuOyG={2a5LGT5$G*#Je0U+QH|=uro|&U|`4u?f0{mfM}7IkB`#W52{w= ztsx@PDf0I5U?FaKafpyScZ$3`M2tsVo(C!@nj+5+5!5)qz`(@|6_!kqua8&Q!_L4E zAB6xYbFsmR7rywf_J6kd6qAM*1Q2hbBjY(@q@Mk z$+Ia~b1*QNiGwLFc^+wPJ`U@1*+DVbvc+s zYQYkqn@>S=9)_qkq7=ID@)lOq3L9`REMsI~$Oh*VkU7N#pw0%HczzW#0~_>2R!|Or z6bbUW`rJjUL5>5rTcH_`Ex(+ZflW%EyGULcc7!amE*BHHW)jUa=3!#XZv_p|fkGcF z0SZ`T2@s!I*BzFdjBQ~$Kt-vxJ|r{3oM0pmGg*%dlBGrSjJb>Y;dZmhbAg?&lLc{^ zoIZEacZ6(y8#4o&nzl1remgS*8#jdFVHY>n;*giH2c6RbaV{@}QiD=VoEnEf4OCDy zuf@iZ-^t9t#+F|R_W2eqHigg-1_p?=Q4ni|S=jPBm>JkW>!!uybzB5lq>b#^z_tss zF(GbD0p~Gcb|H2R(5;7JVq$`9V#S9+RviJI;lUxqp>Y(%16wS|1g^8S7BTC{qP9~& z>8way1-9sciMbY3uY>X~Gw2Q@2GH3Kko*BYPMwQQ%uofwXG7fYD1#;vqsPT0F90s7 zwHd{^*+DfEs6^N0hL+!uWeP@28tR}vGbs6j+Bl$jH_-ePXj}+#5gd3JiwjcU>*%pT z7|4keA|l2HX%Rqp&}7O6O8uY~kCq;joE|F^$WC!B&>UCD`6c@Ma;EnARS0*PvKN615wMYVGC+TB59Fhss>vF8D&OT%ft+^UXH06 zWDB_E0cOZCRfF8CH4A#5AvmS!3l#aQFcd&aBXC2Oi5cuIP}qX}1=bH{$T3xCg8T() z{eT&AOx5Wy0Wd?2iCJ936;$Ga>n|n-9YzL*9B>%|aw;=;NTT>3X!M8;qBoz7nSl*- z=m*F^NPCP&gqKB!of&)|C@-faXn6={ei7(WvmKxq1$zoK9p%anx$qo(fHi1R6*N8o zy5I;jNgD=Qe3Hb*nSTrv+n^kx9nZ#@e;m#WWaG>~0p~fhaps?d^Gw+|^L^kvbvDlY zQ*fRn8zdC-!Dez7b%HV$xX@$c%=ZQE>akR#&4iuD3+BEvQ3Ozga;gCrx_Ty zcsMLUXWei>f@}pm$ap!42`~!gRT&{R9gbd^wl6zJpPi7BdfHLEqi_!3ux&eI4_EegRaQ}wXB3$g;-&w zJ_mB4&nCnMF7#_l;buw1U($h^!;7!>;6yeDR(aHx!OfA1zocUiagQ(yhC!S{oG=Fo zvLKtpCBy}BQ8^O>3-Y+>Juc*taRvrQ69xuQHU+J90F7b(gRUb371bbd@I(wF0|V&3 zD=-_hmdt>IL70(&A)kRku=p%en6iuIm$QJ!gF(TWF9L3|f|#I?wPdOR1rON0=m87! zhejwUuLv<|oMT|%%H(C|%I^VEBU;rl5sYpfdzO`w?MbdW%URmz{w@o=2WnUPNA3-UQsv(C`CYDJ{XI@Qs~; zL0n!~Ql3v1BH;_V3r8H3_CbNFwTf9I64Dq2H7uY59jcI2od8Ya%;4k+(gF%Yd|E)w zXHbwcF@sYgNDC;u@M!@xkD*$?O68cqmV=4_a1PV@21~rf>7WT=kgHKeK#oEc0T~3H zH0G1%0_A5`2G9t80k-@M$s=moN$mNZpv()Qcsaz4-8khXj3U|dyIDX-;xY-cfLn&O zwM+~wP(fBEK~{)h4MLEONstX9SjWV`qAkJBnI#UskVuU^A9QIEdp_tMBclnpa~C6c z&Onf%x(71v#KgeG&^H6ZmNsBws9|7WD8!YA#K4J-T|B=Bl%wP&AT(1A$k`efKvmiV zkOWf=$jK-IAm<_kAjy>ndurv-g1C{FAu zSk~col@ltjo(J2B}|~L6s2`b1j%& z#-vfq%m6vB(2%>x7E~L78xu^`Ao=__&_pi_1B0|y9YjQj3qtp0>hPeLs0I@UpTVNW zz`#(%z#u5X#l)-u>apoaLgbmM>%j$nBNGD)td;`rt!H5X=_y9l!wl2Z0N12Z2JQz! z^?;W6mq7Gzv&(boaj}CdL_IETf#O_{LT&!yBrwg+RO}C8uz^;3`+^%fa!l1AXMiFK zj^<@fSD*6X>^L6*;pJR z3OWe|;?#eju7@_G7!QXI=t>fhO%Ti3z?O4pwSn3i*Fl~Tf^^>VeV7^8nDhNWoue91 zLSbM4we_|$Fff#X${g?@vjGb;=uVoqAbsG00u~)smcC5zP!m{zp+M1pRfd8hVKsQ~ z4xDcKGT9=eBDi63&&|%H0q%)ML~^r3G@_(6W{nn5&zBvXKzSgZg#*o3lz)%iZQw7Z{(c)Z?gdzpHr3w-N@DM}} zBry&#$n{jv0FICXty=|Y;N)P3gkxVOXQT%BnhZz)vT2nu$!T%`0__zA+a*DaU7&ppAX6mZrhwwv6*M;qI`4oB;x34b`ZDzmApr@=>CpUY zCTH~WDX<-FhZpbqK4TEywMnxBAC6zBUnKD zZkbiRBqBnzf*@%ZbQB^uZ>WG$w-u9yAt=`|*S3JNP#6lAiKVs`Br3;L4VIN-ss{5x zy%8`2(c_r_RW}t%!}t@S{K-&y3Y4A%qNA8pt3eXt5w#$SNvswu3^E>U4rrVdWB`*m zSOT-6G6j& zAZbu70H#5vff>`7bvPg+S>VA;uox3$`cLB_Xk8Up#EhvLL_-!eYH=GdF~q^rh(zrY zP_+f#d|$g7#DuKHTMuG_M{7W34PttaiMe(TNQxP}2&i@*h%H__A4F;VX9g|xQDYL< z_{q$`_D@O+vY&&2!JC027~ExH$q`6X&E?pkfm11ua#pT?h(D@!G|pqy}lvr7>{iLEL$d2*+VF2Nd6+{v_CcV)?&7vBb`# zp~b+!bq7?wgX{tIEjc;C+m{%upb^NVp$E!t;QLRF7#J8TLFrYOyJ#|~Y=BhJ;FU^T z#j8L~1a>BH%3x;$Ckl3m$JxPcAZBp+Q3cg6%m5!w$Om0Ssw+^m6cnLgaY*2yL^MJi zY!Me56W9jOxJET7;ek6fV1^!3^#V|vE$bf>D64=&QI4s4E+{nRn5sbuLraaR8WhNV znV=2)5LT9!A4HIOR=y!K0~>g_71WrV4a%F`MOQ%{&IY$hzjKCEJ6Pv~!aAOS=KA@qsYEZmmh7S|O3g#=b zG#FSI*tp=_e9&k(Hxtw~%vWaRD>E~&6`O&&kqAZL*-&{V4!DR0BS-;iD>KtyC1ZU z40J|r4G#AgPX>h?s}2V%n@IkAP*YWxSwfpp5@e?beY6> z?lEv!27^vHwe$t;W`^1TTI6bJ1Gbi*O#;QH;%WxaR0_;O4bU<{VK#7~4{oXnvx{X3 zb7-pzvI??`33BFFF)*;P>PQH32y$jc2y?Ira^%kixeMx1K{k*wcIb`Cs=}ON21oDl z2(sz03qn_ULVcF6$_%<&Ccl({flW_}Eg#}J9#*!ZPkSZw@Rrgedc_8+(A|j6m zE%NR$u%uH3Oh>JB@*X0aP}Gf{wyq zU|;~93I)1ULIrXbCPXm<0|Tf{@r99rL79mGyaxib{tuLf_p&fB)PmD6s1i~Y7Sg!E zz`(^K0bLQo#R6L!!VL*_NFmCc&&$lf79j>1V`0+x1L}eYcr&x;DHT0b2i?vKDr%vs zAa~t@5@|6wBQa_GW@cc^;DOS-P+FJ;#$bgp*dQhgvqR`SVGbCB6QV?z3rcefazWB6 z55$>*JQ_C{7}x~4A)>rcQC^5BFL*8%wCx2t8wFHdO^-yQ9VIHj$Bba?xG_au););4?Gbo%n4&~aLUE&1POAAX6cCvazd8W z>TwrwXu@@Hh-T>-3UV-mOE5k4A_uq>hrF(lIM^aKkVVGaMSXBNcAXID+D;#4@cLC< z=%h9{Y&qn04Y)YuMGU1u-VrN$rpZvi(E~d1R09zKoC*mB3=E)KykfLqu3@tTr3?;v zdxIDbc`m(h4tZ|9AP#vEJzoxaQ9Tb1c}YEI4tZ%kI}UkWJxdOGJv|c+c_Tf24tZle zEe?4TJyi~QTRjC1c{@F64taY$v7)b9SgjT~0I@n%8)h}9c)X4@hrEcsSkX#tYR(rkzuPK>_43VL?`17C|;0?xG@uoLs!Fm>@ed zxWLN=83vaUYiZ%7j0%27y=L!K|oP^L)70A`^eheVbkH?jb~xW+~n z2GB{E1#nfMWX%II)qoA;Y{Lk6;#Mk}V8BoSN$KD`FUSd|kTVY~wJQ|~7=qM-%3rV| zK@Kp5td>iVJ3?3hrNEJw%Zd;b$chjayvHFZ1j@`@cLW7N<)0&X{1$Qs_!1TdhD|Jx z^TR;}pb=B`dL{-I_(mfT2eHuz#M6RI0fYBCf%#0#wP0F~sT$Pp(K^Hoz9(8=06fiG zwA>IeTm+H_jeIdfdPpL*Yd|eZGp6dLObjg0UX>hEHK->AZj6E%;IXP33=9l)ps^}l z?xKqz6T$6f&@PAfa2}Rc8I#6F(DE+sB32_<)G;yFt^jooSZY^-sN!3ouFi506Vd|e z%PhVP5&}61BEloat8K`^Ig1P8PPSqp76!I_YtW)xrfQH*HgKzy9bEk7-(g_j0#$XK z9DSKaCz&96@|_qMxUy=Ofvgd$T?L`mfhdvMwU97iF7^a%pgIX^GOc6M*a8}97Gx?; zU}0cGl3`*hjzkqPTk8+CahJpk~USZ!{IV7>yR$qA|v!OaYAcCjoF zWXtbh0rg_p;aeN-u`_8rW@cc6^p(JAu!(_xB4kXSi9wQ~WiF)OBnMFk9)k%4B}(uZ z3@(2$7t4SaL4aHcb&@;_Y>-=s2@ zBiR5sVFsLHAnsvdfbC-f4Hh8v4>4Q)EU;Btvq4@157;t6A{y!wjYFW8bUtW95f>XP zc@y_2pFnyMg#li@V)>6in*{k0fdJ}bf%>4JwL(M~1a>|P#28TM z!h#jaL`b;$LieSSY$hKIB+6LfQHEkRvjGcy-v`KSq&3>$Q~;@3#IlUJAZ;cw&?3Og zps)nDeV8PeivhNa+@= zR}3^S1j7cs> znHfOsc2K?r*@y0TCT5K{(5$P1VmcdE)3uNcUj}LXLf0Nc#`&Q_ur3)wr2x(ImEJzxZti7L@`nVWF$lt#3Uw&LI?-qR7e9s<2Pt?CwpHe zI8hjK7sVnHb-pHOXa==Jd3{90xPHV%ks`OOeEs1XQZi|5yYf{KGfJRdxv z#>SCf2pS*J0>uq`UnVR>Kn6p3?0uPHh60fAU>5@oJAh`np!Vr1?d7KVN%28Kp(+61{CJj!($VFNS~ z>T?%)o50#=kmf&FH8}qP3#K7?nb04ZSD1f2Tpiu|W zJR^`M5ECrQ4ofub&_u%yPBT1A9MBZP#GJ1K3KC{9ZEgq?+^K>Dsu(f_*?TIg$HxR= zf#XG6655vnuh#_?Rod)KV&F0hGQa^1IIs*T;6N_R1k1C5(h@Xnf=@^Vryvd_Q4TQ< zXu5*9OqT<)$U$2`qYSi54D537zAau(ByF5xoKS7@dTf1}5gdJ)5uAOQ5n6|sszDtA z&^B!logVMcWiCXHvHxd3e=_P$Iu@NxD$tn6YO z`GKI#6r5s){4DHZoZuj0Rs#>c9|#l|is$O0bH zWC624S)7kWkR>ZpfQ1uu3pcMIibjP5NTtBxQu zxUymck7|PJ9MBvo6L@V1sBRbIg0_`GSxPQmM_8T*CIT)YndL>eKoiTLwi{?34z!km z2^xml{%qV3FY>VPvE(lW4b*Xnv4gz?I)q1+h1CZpiU>zmRUgi*h)_Nj&a4Ol7W7bE z3oXx1GB7Z-fXg#*UjdZoxWIu5vyqKgEK8V$qc2mKjZKg(OP_@;Q<#l~4`HJq8`vSB zHThzO4y-y{>>Qx*28|Z8@Ug%hCddkoVLldBA3;`-yI7$NHbK^`NG{MJ>RA!Opz|jU zS=q$040;7wIQ3+~p$-XeK^F9p0(hviBZoSu{l^48XRZ}8uMRE1o`BLIq>sy<{{Xb6 zT?oc|$iTq06m+m0I10dXTcD-TF#Q@tY6ZnzCIbUQ8z}vQ2dlZ5^TDGooJ?%Y8cd+Z z3}m>8heJ${jYCe4TU(i}SQ8|!ZOSIkDPHUiYRaoJGO%&8i{)!FGO)38X-gLwn}Nnm zK(#;*+T;W%$uLM8urYw{18WDbCt`v0`alE!I!Y}0(je2>bS0RoK|=%(NtS#uP{+^> zEM<8H)Q%EnV*}4bah;;r1GeW&E3q-vj3r8fl?FQk3TSs#7a>mjSwcvg^ zD6K)IC$TWFsohgRo@Ri$1)@MK3v3v44c&AG-X*X;x)sCT@1X0pKw}PU;61G!pnQPg z5iUrWL5>LUf&`t86SD8PnIKBQGblVvEbJT{;IM@G7jb+F@;XF_f52hI3(?QX2Jtzl zEQPH3b7Bw*fw|X|K|2A$2HlGQx+|;`y!Hm77d$Y}>I2@HsH+HR#z6BZG(1=#f?x|n z#j?1O^vO$Qfi9l{jeBsw$M!*k_0TbTVHPC4oOuy~EO`;!Y&uG;sy^%-ks#er!$8GH z1QQFm=+BCX2-QLo7t1mfWP%zb#wx_9@fy^)g9@;+YrFz?;6Z+CV_;zDLc|5C88J{U zsI~>!%mr~88;ZNRA=3lUNdb0_h&<@BP$m{gutPLKjRLt^44gJmr8S;|oYV*EmaT@T zbS5$IL_8BSc)l4jX|FX6I>yCa^cAEKTs1L4#K21;G(Lk&0*!51GcquA!^;P7GT{>8 zhSc8q-k?EO69@<5!hApQ{3STmbF+(smu^F4K+9g3M8K}l4ut3d8z641$^_v;75amQ zlt6I{;X}*;^5*E(9(N$VODm90B=?{HhD2{lP|xGg@KKi6Woq9HHYPU zc2#hCk{8H|0M|g!Q7h0unlKByAWL5+WKFCfix`*#s%F_CYjg9LfzJ2f5oFb27i5JU z7y@p*fP(>a=n9zU3+mc~!w(wR&@*!uGo*2XP6q|$Usi@Q%nS@Yp!|@BI9Ys9j^?iAT z#-wo^)KxhFO3mOEH9F#gtdO-eh*hYyprtkt^YWcROVfEQdO@eZ@<2``%3xq%0^L2L zQ!U7r59-_s^9u5UJC~p}7@#v@L1&R^$8zfMF$uB?vI((hd}L-|)Aj-LG(LgY4iNSS z5ZeUeaa}=99X>%;u*U@<4F`y#_sk4z2q|zB3bP3EN(UWMBr3>L%E`dM2%0R@ zVHf0sMi4kWu^0=r1Y#09vPb!~RRsBwe90lmp(DfwI@J$S(L4h8!?*|kzW z_X=8o?jRNvL~=5>Ah#vxzBobdd`T7tHnA*2b3ty1>%m1wmZ3V-IH(G65))*FDFV$y zXXb-?UV_~D;t&%G5jsF35FJoM!3{zUgnm#jE&o1v(i~9JHj+A!Ak-eX-5|YC zF+p$$TPZ@KR}d1&LV`j%?1Dm&Kmjcq=efslPm@zejzdQY>co6y1_mxDn;o2Mwb=z( z^Vfiezd3ZQICZ3;Wg=7!SUohaLW&$nA;Sd8Z;1R1HH1@FRFE|vG)JJr17&D5g2ta6 zr$F|-tYlzdSir!*;K|6q0J?t;G>i_)7n2wn!0o)lXyP193=E(F85t(<`S2j+;QcdB zObiUq7#J8dm=WfHBP`wS>GY|}2Lk^k4(e+{yuLTYGqb$SHSPv?gG$G-m1Ff)CxxlmV z5J7OD-D78i%yvPi5ujzC1p}`uWPU-3i5a}G4rDiI?9v{3t~b;S(Do_N0rcEO8$r(1 zfUH*n7yKY8&?)Z7QfwF5!Dkd`xj`yW2q`a+l%VAYoq~r_&?UFv`5Msr_g;9N2F`$7 zpw;SpEZ|Cm8+ktyXzdqdZ5a;(pA@V;!^*IonSr4XZU$tj7kANFkfXsPrJw;5R@g|O z0s{jVv|7^m2kB*kmK!0eC5XG>tpM=CgFI+sCJ(gW0JLx+PnZ?z8DTbv24QwVb}=(G zLG}mW?yWEfBoqZXKykpvB*>xh9dsBIXz7?XHxu|gm|74=Oqdh0I$TeS16*0^DRF}7 zEImm<7AT8fkX1BKk5iCMG|vIFT3uY26XYp2b~Z8anj5fBKm`}LisiL{Rk08^sxfK& z1ywlQFfOD}=LQ!X5V1UA9zh<30B<(7EIsieM+=4mLGGR;1_nl?B>)gp)F9qPP@v#Y zgO~!fh!>&~6joq+S)qJ3CeALzszgCfT?0WjHmNK@)`&=bRVD~akS!vz7PJrqGKVXc zWx!pu9N{0Z%OO&N@USVUIbFQ}{r?ZzJSq-eum&lISU~4e zf$n({6yah44{ORB8F90KJ9F|5@w(2%OrSn46AO5j<*3fQMt{1(GyaK#t;JgQx=Yz2VkBhIv5 z1P+6VpuSTns7=Ym0;agxbh+7eS;Tm>^F?{Iv)Of7#Cfz+AT3QD9tbV2#|%1(g_j-N z{?y@t&`?of(3n^x4~MQk8)S3=)caybFe5>YXR$1O7EvB;9zj;IEMt&mOyWEopt?~M zRGDvL63wdJ16m~@npL|OM1vQSGfC9$1aVkuw}U9=+TEZP1m6fK2JhmA=%@zigH0?# zbZap&v&d=ifY#%ZZO|@|Gl+FFSaBP6Hy7Q7$Lv1rDwvp|L4a6i4ECCq8j~2a254pz zv~C&XO|5B6)jOCNSaijhn85x<(g6~O$bwXZ!W2YK?BPOKB8l!l>||*13GpEq*RMZ1Z=!k7E?9I8t{lSNCHy#f`mX) zAQ7+>NC3QwqZTBjWyX}R1hy6=t`){4T6+lOR!CZ7u005Hq7_p$h-Rt=NzKwyf-2Gi zwVy!yu0Z3pOsZg6@d#BeunBAsJ$;$~ShTE|G-N?bPnc^DgN$R-;u6y`VyXslz-?bR z2egnKB*`b11s78UWd^VokSO>RDUe3c<~~s8SnC_qaF*I*AcwQo9tTm(wMRe{Q#FVJ zSD>{=K>{qbC%_bIMD0nCTNprVJ3;NwN#M2=Sh5-u??>Rs;K~%xUalqz)LIpHS06JO)v{nV=Lbj|3u&3F$ z@3Dg$W?XmJVeaB(NX&z{ORD%8sI3d7K|Sjki|@FU`IlX&|=fF zg0LXE!TT0d2tq_1JW| zi|RpshP2U{!M(WJvmo_qOw3{$5uh@d0d%fR0J!(Wz`#^}4zzy)G(-hrh-<`yMyEhb zCWw^AOVEO~GobCUV-v5*jW$}uz)xZJGc`H6>0!AJ?_b?iEwe~inBun5gNft|4Bjf z2Wa((T@r&ls2>SBn-Fwv56Jt>5Njd2k$nz!2*ms18m~dlfp8=xi{F3(0OT!*!@+Z5 z8qoLxZ}S3`F}jk>I&4tW!Dc}Z|z&>$7)EDg|sV?5fS?BWsJMXc5g1xy^^rGbzIf*S4MDLn9@$GV2h zIy#)-%|F5{_jm+Zbl3%1Ama+0T=zuOAVz`?YXBR0kBO6uO=ktD{D6#g`!g^FGJvkx zVPIfzXOK!{5CUBZq{Ji+PHv#O3c`?Ms=fe9U|!HIv*$qtU^R#Y&4PkxloY_k1eOEu zpe=q23Qdr1s2PWl%wUEN4KhPCfcs?N_8RoqW01+9wiz=x--7mtBf?(`ynC06Sw|Ue z3erXjumO^jGT@re3}OH?xZetw0wrQN2Q=ISDlb9C zF|&ZT8h{RS1arZ|PoR?*!8{hov@S9qT!(`9J25eU+TEadf>;UKJ`K{vR1NZpjsTku zFOwM9*KCjo0PpFQU}6BB9ViHyr{fX_6&a9~JK$4JpldWh=RGh%*Jyy*Y?m~^G;DbW zNHM!k1bl@Ch|dgJ3nR=VssZ9cDT@x!(jmw^p)Mz6B}Aq+bQwpcJWm8fF=VwwCYYlg z!J-4YEF0t-@Bn6h5va){29`vZDgc+&;2}j}4)Bs7B+Iq=m>{~K6vRu=2~*ID576oZ z@c0GF3Lj>~LJwgUsJHUib(uMIG6Y$`3qII&WCU3tZU!&b0C7OWlVFavkRXd_7MO{| zfGp<_WPz{TQMQJ41X*+>Sp-=iOLp=>9@6FnsRJ(+5@Z1{`w(Vj;_S1%NL3mRja0bYxc z6$#$y#w?np#m2{y6)Bdb@eb5aV`J9`i7~OMif2V~!J0H0pc9LjjUO?ABMnrRFv0ia zL97BxaDj(~*ub&LB(IaD0Xjs4NnRJ?IT(!+Z%oV(MNos3;q|Tv7sPI23eX4U-0lgbjy+Vl$5k9I090;m~D}NJLw32}*p-mHlP zLBR|XPss&`IH>LijZ4%*&mI6xa3a>7f>x?P7pWwIQX)GCB*tNj%|Irz$whEMvk_?L zCn#q_k`yG%gV}8I0ufx=a?r(RFvo${4nQ~{LqOF(c)bN^%?l{~LBf-ZO(DRW9kl=E zG@=lINM+^cf=Vj+WpDI^p9;mXfMK2P;>MKs4A3Ws=f!JL3JOP5yez}3)FVyfzbKlpgCR8UCN+! zA9l|WW+(p7R3>S2COlW2?v*;-lDcdj<6s6jrVHS*qXwrBLI~`G7@B%SeBj$L?JAU>)!9H_&$5Mwx?qrt3V zhAM)PQ}%>8p`pYH3nfr+2y%i4bRoLL!GpRGHf+H!XxSb}A(#(|E^w*@XGgItBe*q*dT^6R1(r^Y zKq&|0W)uOCN44QfnPNRDh|%ETW>L^q2hg@?$R<>% zrgF&LG)xREa>m?D)e}Jl${f&DHX^kkuS3dr76wH|28LP4Wzv376d{#Kx{O+oXqGdM zgyk0JBCRWoYat2AX_R1QKroVF;asUG_Sx8o^m=1 z@+~AmLd;-?X#{yfEX(*blbFUVP>o>(32|K}F)eY>VOpR-)KP;7!g2_#)CXk{t)jnh zvx|alVFf*?9ssS?0FCuSW?n!6C=Om8DQ3VVs>LQY5mMu8=@pg2wdoaY1+l>{1@}P; z7#SF5gW^qNI%q+VMv<}|XlpgdRp7Z4ULj_U_Y4eNMN{n<3N-4GigvIP(27G#$ce9@ zdP|qPXr>*kB@Lbf;eym`;89cXfiT>V&}CzX%(UbiGcmA1Co76Wp{riB8|*1iR6y2sBK9dmTq6Q@2E<6Q zECbNhQlJDMuj2wsv+@vy;AA6aCp^g6I4GuC@gIW`yfy`x~qy|bO z7Z@2B=78cCTmk7-G3tmJug}1sYryGc zLpf;DWX*yW2dZEXfw-Wu9HJdGgC)+T%@4leo!tSJeOSc|`5#K-!v+f|*G}mJxFFE@&PFG>-tHnV2=!gOUaV=!|dBi3BKj1xdi~3VO)I zz``b02cpD4TP{Fnqk(zQyMjOx>=K~6g4p^prQq5gK(v79hfN*DIWu6 zN`fyQ0*gw44AXkY#H_KF1^F%}8D_|#-`$`+q*4$LxQQvih<*zbXinue0|Ucc(3~WA zsWEf@2hd4UB`!n`pGyahzePzWxQZw^{aqOW&_xk%rEp#ba-Zf!AUcIcHxjL72b zV*1aR<>NIrfP(|+aws{7yS3Vwm}^1)f^c;}%_}9Y7tZoMNchW&+066@KzaR+| zFZeD<0(H6(7bHREJshF;n=nCkrE{_Am@w-IGJ(?$*k-YREL_?OObDll=?gH)>*s%D z09^*gDE1F_n-#=7(7mIe^G2C;`9tut57_k3me)+NU5& zuJ##-g6xHdEdpxg}EW6TD&0yI88mw|zWIX?_kyfK5F0ve433Fe1GE={Ti*$Ntj23xNM z+FJ?I0;$g7J0?LwXkC3!H+~nW=?6MjQ3J$+^woDm#6W#@5EGUzels&L%md{WUG5@8 zpPZ>0(p)I&4p!~zeq_GcV5?BFvXTHM!|NrZaxr^#SO2I`wbS#sp8WhId z%#f{*;0t@=A$=#Y+E<{nyP-`TV<~1xHy+&11r2C}wor<3iSuY%LnOqqj5wIVTM|J> zce3fKaDeW9(PCs^)0LD1-El39Vggtt4~MQilLlCg0MrTaU6oAYUBuuf zc40yW96&oMQPqR)aRVLe0Nx792I=gvK@yH=RxLP@fMZKsPZ;K0eSRjekc2TCGk8}f zXkdexMFSM_Owci1P}IQ2bir)4OW^2Yf{p2d6muYr>4NysK@iZGE{Mw{3O3RLbo&ew zzA;^}VuY|+g%0j=P<3z@>TF3S*a$B;3UQ9`f};jB9t(~f*a$Bu#4tv96`)2-FsW99 z0*a{`qzpX98UeNhWDIzi7bK26%*&)&{ep>sMP3fHxelZ%A}gX6B*Mg83(9s()u2)f zbUPaxo1C#YQ#H7#@BtMcU?w}HC=tu5eGbl8peDJF8azRRc4UIKamouMY3v78{m^*= z2nT#dNF_4^!+cQvPz|yVG@}K|&d{6>GL(y{8dO%w8EZ0CgZN@uh9XQF>flZ%*fsv3 z5hl>l7GNI4Z6LFtxm;hE32Zb(H@F9@9S#u!tAL2>xkw?Jc@EHK9>_Xq(@di1HCR*< zNheearPT(u7&J@>%FYnAY~bPrbk8|ll1&+%K`@mB)x(!?qGtH$w)~SbPyM4 zn5`OA9m1v*AjW`)3LxbOQ~*5q;ll(@_M%zF+(q7wur@5jNQe}gF`&M!#vV|00yPE{ z$Y25RAPG3kKtfQfpo&1cpd#Q5#tt(T;$KLI&vFuIKnFaG11Zg*nn584(+oBr>~a$( zs5HnnumfNMAj=>Ekg%1PfaXkX6g^NQp{9T|K}Ddt1faSg6)RMkH3I{e8j}b(hr{Y) zP`d@R4i8o$@W3=eDk}{=MtE153*Q<&4P9`~1Qj%BYxY_j1h{~L6eV12VtV{+a(axQ^>eHm_Mol`#Fsi;OrZYdL2yw8 zj$@EP;Hg$npT!S6W6vOnG;pMC!wTjZv4bgXMpkZS7B=Xa&rBc&a(J+Vr)gN(BL$dQ z*dqj(Sj7wuXhHV%uro6-ECiQ>;1&?079@~B18QjPo-EMDA4q&cw%Bl36f-d}2y#Gn za)3@! zE1GA-E6BnDF4MtNt_YWaG8ar5#D+?P)^@^#L2R%vXucJEMgx|aSB`w}K6}^}c0msC zI$wyW2FMSftxbpq_-nW?z*DxU6*`k3sA~%r6N3ajgyP5t-Mt9fq7Pw#<4{|Y19C+( zc#A$b)InSHK@1M?hDh{q26+b(&e$6cpsF5gg8<|zgan%yh!0M*?DBf>HUda6A}fMh zkOQ*Qrt$Cp|Mx@%IUqZ2I0ZR%Kzoru7q#4h6vE)G5}-{7pzFE8&5LSKp9i*GiCu?X zkR7suhDoFrl>QO-mY9I{88b03>|#RfWdZG3xx>W3AkM(R@EK|Ei&Ly{69&kB zm@*?h13gm%b0g3J<_xT$d!`t6%wk|ru47=+q9S4t?mhkAn6HQlgdWC)RBU{H3-0j<;kb@4!ZZ5YGnZ`0=FVqjqS z#c0eR#sIb*bY>-JZzm%&1H&N}28IR}1_sc2%a05U;Ke@1&^uTbg6^z_Vk-s)23|%6 zh9=OE7G!S=cyABrx>t~YLDyD+*bEF@U^^HX*cje(yx?GC_y#6LIk`F67-Tp>B5GjL z08GYnI&rcw6oJWRut-0coB}2{an9#tW7r2KPk_leT=iUR4C}z;elCz{N4P;I-xmV0 z-+;*s5szJYhJ(pPV37}C@;_LFH4r4L0Va#VWHp#<1CwjPjWm%#nnr-sbVh(o=!pc8T(KY# z`B)G;Hr6MWjiEcXES8O76_^x^2Ze1xJV?AG0i>on0py082_Rkn!6Zi_Hzz2WLsA_m zUokQYFsL!;Ft9R!c%UV+UQiwj1EYcfLnK2!11AFy0~?sv&Y;5}z`z4euL2Cy7<3qT z8F(1@7(n@IIhbe3V9CJED8R52v_q63nIRKY12PjaDN;0xC zlryXY`{*yDBqIYuJ;P2gkB14u+YMGJ!30uS&#(u~QwH;z7>D zFt45AGB_lH!74i$ZZb472r$G$dH2D*0;XCfS%yxAhYSo10t^e7YMEFWIvE~=dE1$4 znOYdS7+!#Rx1hWaU^D+R)iO0ObTRw@^8}gYnOPaS8JHPCacjdY&n&<&k%5H~6n|dK zam>676B#(bygp`m<~a=08RWsdd0@F&3@TvWW@dTjB@7E092l7y85oX$cNi{a@Bo{6 zf%z`80K*C>?y12n75H}0~08h7K3?58MlH}wzE!UWo0O)AJ$YT`=!3D+7Zh!&An)OrRPmj%6w<1H)6shaiOvcfk6dGCl|U z=p*Y?R!xRij9=?Sp^u1m^_$4u5Mxj zxw?qS2du9Ttgnd4AIzHr=9MsoflXNpHl>0o87#LMELX#n%naIjdjM=oJyRYtsO-56 zmaAvV2djL*HkDPBp@pfB85FnQz z$uNy+9$2LzSmiXPMPM@>z$#}lEdsmDgB=tP8<<#GKp~OH4ho44Oq^g|4w$zY#A6U( zsA31Dm+eqqCzQv{0!mAh!MuG;GGN|ZFz+CfDwwx{oq>Uu;V_dXn0FY=JHlkf0t&%v z?4S@l#pDX+y@2xESU~ac8|=vw%t>GpJl3SfwY& zRMr!WXP6?uycjU=JW~RgR|r;lktu@(l#(03yemxkU|v7RR90SwYfL3zmGe2Kvd&?+ z!88RN66-iXp>&^VDGMmg?*r?*&$JS(@;t{>)+G#&m^OoRdTanFl-@BNW&zz0xHo`- zL6Cuo8N&M!h|GHky5bft*B**2*Byq;yA+Ac%Zx(i%|hY1MI+1gzOZd!W#a7 zNnS1xTOLfRfJsd-X#ytgz+@npOyZJfFk>j>3SkIrILRf?5ZG`VOuhw^|G}gnH%MF! zOj>ixGcYpb@q)-=Fj);IJ9%$1Ffz;pvloEL<-B(o7#Y^^K44&E*aQ~Y$@_$Xk>LoK zJP#&sfXOGkAqH$7`GtEC8C0$@R0+P zT3``K*xCx-WME?m5tL_OV+aS6QGy`9SAkX53w~q>Z0HdD$Y97YK`@JvkzpB_y#>tP z4>sqQUMus{t*(Ku2#K`bp1Y{$J zD2Nmk&0u0=kOGs);?qPy?*Ae7gdwa!Qyi3EOu(cSm~;S>?qJeaT%Li2p+j7SnT4T8 zT$7oFVTSly1{Q`D;vnUPgw45`N5VY|kV>?s+HS#~jx16-@pCldO_{%!~{? zlDW)`3|i74z2;!jO&S!ZzS1DO!och}FgpWG7J|tdu*%8Odzl#-W=bDoW@K0(eUl-q z;jb9TE+H8ZsVW09M^6^yHY+gcE(=O~A+jLxG%#5SCR@Pd2RV?9U**hM!WyLHK_)1H zNi8sG2qrDSq!XC*0h1wMG8Rl`fXQMoSpz0p!DNs87lyEg>0ojpm|O`aw}8prVDb={ zJP9T*g2~%p@-div4JJQbX*^(31Wc-cNfR*X0wx2&WIUM6Rj6PLYba5uU<_=i zSLk9iWSF7=N=1=MApgcGfkFck=8(`%RsyAj3?-17dT=f%Py)qHgA%Ab=>+SV1SV&I zNk~jV;%EWbw3SNo48jbXz~nwKd0MH0QJCQ-n0x^i`35Fgl|kZS$`y<(45ySqDd&oE z7b6S9Juvx78I;DpDhshPGW<~%XJujFRFPq2WPrqJh6>1?MJgcogVHSvL%Rw{?*tW) zt~p>5q?d&O68j~pAeD8hpfu11W={jN7l6r4V39qlptKD#Kd^yA4OCVLtATXMseyE< zg4z0D@;_LFT^%GV0w%L1K&6npIw<8tg2^l}SqdgQ!Q>2ekeLg?)@;_W1`aSOs5P54ut8P}v%iB$25pcoNE~r#&t_$05C)6Lf=M+nX$U55z+`|nC^jRt zLE)AN7RdsWkT5LP-pk6!P_2E4HL#&e8x-=Bz~nqIxg1Px0+YMI_7fgzSNqI1-r4NcnNa}^eg&A1HUSExkk-=48n~jknNZ){s zks(IklnoSCAQBQU-}OPh_yZ;x4M1#mFv$ldg$+P%lQ00eO&&~w;)RjH)c_PSK48*P z2V@$=oe>5g7si6gBrur)CUd}KnE|NWs{@$Muu5Nuh0ojRnA`y-_k+pnVDc51{0Ju5%|Rycfk{m;X#gf2!DI-S%mkAK zV6q8J_JPSIU~&VPJOL)pgUM@P@-3L;wE&qf1}4qGWB{1V1Cupia<+v$gCN5q3we0y zDr2e35!RptCN;pM0hlxelh$C;8BDr^$v`j}2_|E~WICA429x<SknEY6B{x z*4hNIGcs(k0p-(OHlS2`2yDU$8&Fw&6-?f-0j1j)HebL#1+|6rO%pi68aU-alQ+QRGcc*i!^z3Wkn0R8ZHk@sI2jqLoIxSb<_xlTk~1iT=R0%4 zO}pb9$r;x0&^eMbu;GO>s3!X59LLGXu-hG^3)0^??hbO*1$R&z8`NuHWVquFGUvVf zOfE(SkZTzket^|ON+&iCQ16D{1EfaHV?GxngR#eAE=C4tj}=^u451z%lT$rF?kV&D zg=($GS}sP0PO$h4kAG}1pYnK~M=7iEcXHV1)_H?IA1_=2c%!->RZ7GDaj2P0)0U}?m51o&<6G6 z7#WuMg7mKS1^MWxFDREm%z@;o^S&Uz-|_|7``Q=ep6_516l=nacLEZ4gc(JHUhxPs zG6Wyz6=oCxlS@LM@d-1o2n*mBW_%yXCnU_s90el9!K5~rvAJR0ckV064FKL4Y9-bXX@t z8%F?l8-pN28I+gA-NhitP!HxE<0#>7V-RBKf$|!_yqQp5512Ox%A3jE&mhFG63SZw z=52%WHgZp95Mnq4;W6yvmSzxUxDMr==bphJ%yTU!0L6qS=ly{GNK7$y;Zz%5x z_i_eF1`g1X*9^xP-f^#CkYaFw@;-A*GsrTeKzTp8w=l>uTmbVL8JKuLayq)8kZ)w* z2JTn6*LKzWbAycW>(G(#i9XE5&rl*ht* zkU@dL-x_4fLH&=Btm)n_~jXG8FHY!ll;;Q_6)N@mnASXGF%7qc0hUW_*EJ08B9Qn zsu&s>e)6j_Ix*BhdH?xU8C@A}fG-kjWMC7JX7FI(2#2_uAI#eU<;j70IS~*!O9355 z4~7R(5T2ueG=mpIN;HHQ1LjSP1@R^_%}X;xGcY8A%zVZOGBcWi2g(DP8O;y|=S4BbFqFV~^BH0p{E|TWCNs#D-jkJzyTlh6ILOhD#70$4S8w#yo~wP~IiMHikTgM^N4~!7he8 zhSw0D#0$=P#(W0;T#%VJJwK0@3ltXwDFE~>fN*Sg=cwpPh8RkHF`-P@6mNP7Y z@<47WXIKN}f!qQ*Ym9+`8C-`iWvl>sfPtCe7~>70)r_F?j6ib77=HG zY=H7WVYZYJbXy)osi!Md+Ihmjl^170&x5bczwQUjU@?7$Zm@Xb&EU2eEGsT;&a+=Zy2LlN$I7&cK_CxgY$HR2up-kI1|KLdTUe248^Z)BuTnUHVF$wzD6d^O zfng`Z4=8V%@I=O44BGi1Q`#6-3QuI*!(apEH8QLdp2!F~bsHpijP;hV4$}b;6I^P% z5Y}Nj2)oz`QmFClN!Y;|yP*JYNw*rV|Vi;MH)?7(w=(WGDdh8W|!) zq!~^zxRiiQf!KbEAp*=h23C2Rp&!fx$<;HSVK@!vc`}`6;3$RZ3u3y&kO1Z#V*uH3 zo#6TqKt1HiJKu_gN%~={7?dga=m7JkF+_{5WBSF=0xkfiF=U8t zX8O%=7Ifu3xE~aK@%zMT-TXY}Oe})_=Z@uVoCML!e5FY0~(KZHl z#??^X711pW?2PN6yysxvMkwz$SmhQ7kFknhnt`2h510qBkDc)hmlVAjB*<6>;W5k=lV%WPtbp)1R)FPZKzVz_ZZHWl?tt=+h($39GQNTE z7|w`EGYBzC)Pr1ojNyjZT_zz$9VqXG*j*+OMh7qt67ph<9$+3M6^JngfO(LwJ-pgd4ZT$%9&lm}{wD>HtD@<1(dWkyI~kzgYrOaZ*@i^C=b;3)?&1S@@mB;n6(+bpgd4Z+<>tF$^*CH z8J~iAps;RWFlPJ==SeV{FbXt5ViTm&j4=buYh<`0F3n)cXalZR8yW6{c|D+|z~DN( zfx(h-KAdO7Y{j?%&a-B=VFaBr$iQ%n@s+qVgFWMwc90E_evUok9VibJEB1^}p}ddc zZ43^KpP)Q>i4sN!#$QmLjzj{31EUz|*foY021|+g433OCP@bDa0)q=<43rlsA%J>7y1I3stBP+NOaf|~LW3G&X5FR*= z+!$q{JWw2YFls`1puUqQqbZaJ3Qtc)M<_2*LW0?c(HF`C#aJL?B$Njl1qfrTfbu}` z7shx8$^*r87~@|k50nbR8HK?O8c1wLF)G4&5{%J|wh$h}35kOYv5Zkr-bINm3~`L< zVBRqXkSTGDOQ1ZEeTj@8pgd5FB{D7nZE9y|WVj_E&5+1w1a2}x@@*oc4VVYAU78`8 z(FM*+U`S^4h4WGwQW(R*JczzD#zZg=qA!Cn6V6Lu$Y3mj^HLcyL5rc_ZN+RT57br+ zX3mB4ehI}fgHGK*w24X?YkC+M6d2k#6eWw8%NVCZc~+7|%;k*hz&0FV43n&6u3$U{ z=7C%$%}~Yo1kP(@u3{7iUGoC2fjXG08GXRKX$-lN{meCt4RGFc=32%LP+qfSKXX0f z6F6@=a|5F=xMA7GFiWzFp@~r+!sA#a*~ZY!=mq8NmF!|@W=w>^6pLQX82285_X7Muvw{8<;0D zK9~YB^9UnoOkgsj0l2|^j1iPRr!YEzd61ElDU1bR-b2O@Qql}l7%RZMi45G*JD8_1 z9)a={rOlY8G6qZonc2nxa`iOE2ndhCTxJWyG{yu7kHZzr%Yg70LczQOFb|SKrZIMd zdD9qDWG*sKV_X8~-DIB5_#Voul)1<}laT}5F_^|sDRYx~7GnsQ2O7yZ$S{X-1DMyw z&@c0dc`oA*FmD>eESVR~^B5gwfZfTkPDYwxKH~%^Z->kcrumFKGeL5V42NXe80IsU zf_ZHmXJxi9%xA2H@EGoad94s0$44-)7s6v;mIbMt0p*FyMlsH3G?@i5vyDMq_8s#A z#t&d#BZHExG{YiB4{&#;5nMYhVq6U7wSh-?7BM~m^B^_)BF4{P9w<*oF)m^h0(X2s zysylQ8EwG4XN=or|1d9MYyk77G3=FPU|GVr0LnWf%fPaf@d%iAjNySSJIgZ0cTnDQ z*)0sq8GnO$Z494fd03V+%FG43nu9@3m}Lc{3X})xL9bvmg!1_05*Su6+CzDuRKAkY z2g(zdJIJt-F$&59rSesb=}?}M+(Cv_jHOT>C_k)bY=ZLi1+}<6J1u zS}uWM4dZGEkHJ$;o^dVXZYVE6?kD4V#?ufUN2FXV(?-S{P+qEB64OS;XHZ_DTnXbQ z#&=L&m0Ul=CdS`TUbEa}hE0q-;ErS)M~_?^!)C@92#;ZooFvO;#uf9y;li+1PLX9R zBlzkahBk(Sa#4(183n*y&S?yn2#;f>!WM?zjCD}nCWV6xyBXV|JW$B*VeE(UKq0?} zaR!tJ3i-W^3!pqu$nRxb3FU$OzK?Muln3(rKF0G<9w-F&Gv0vmKq0uF(HyiOo}rCn zx55^N1B~`i-U)>^h69Z5P~IJdT}%fU{h_><3dBe|dCZCl3;z*3nAgTopcut?g7FA=aG{OimP8ceNk-*mAlr{IfO6F-Mgu4hl;ch@Mu3MJ zCNtD1E@e5**ahYFDjs7v&$tE5o5nCtaV^VvMu8O|Q>HN-R@};RiE#pycUEy9%T>k$ zaNbFlTa4=90gGu2XB98A+-D4d^X{@dW~_noZYiE*dCqtN%6p;sjO7iZDd>)HhG`7n z6rZttU~~ZUCNgj+J!AR87y{+VDZOX;!B_$1=_$Qu`N?xiRpmrn^(;Fxc)IMWo z`T^yET7Ya!ENei1IK}{KW3n^pKzX1xCOgyewGcT_P07Wy1C{ku+R1{eeyfdZ46E-2CQ;S4>p7BYh&I#XZ@+6GeD$PlF>&7jOw3Fd*qvw=aGsU6OfU{qn+3*m8WSJ}d# z#&i_QJF0SnNsZ|&ly?y6V)vY`b-9(ZFmfA z4EA82Bb4V2<^@A}p{o51`b-%R9!G+z3#&ep$}Uhyv@zV{KFDCe)Bxr+GT5l8G8!`7 z0Q1@y+|}e6O_(O^hN$#Yi)1xpGT8&+MXJqbuwa@3k!cl#$8l4wjlq#=4}{0?Mr{p)Bh!Zc2$#7q zJ%IAQsm*6_VOj(p)CHvwX$E(uHE`ZR26v_%a9$~^2a`N_z_$%NCg;Tz1mSV0Xl!Bd zVv2|I^fdYzyqI#JJS#A-1i}NCm|jdRP#!3Ecri_d@HpHx+8Df;)aL!`tS z)<~ukP#!3BqnSL8L*!Jn+8E-PBA~n^jrk05OmCn(PN&7U2*T@hL z=7m6cSz22dl9~2EdF5ca37{LP85$XywRW&3GyORS(KkhF4QmS10?@_B42=wnwAQeu zF>SaAkz1#=hBbq!;|hoe38gHi6IVezNGN47SziP5z^NyjDF?>WImnRBq;nl2SE3`$ zki*1r1Hx<4dC!`|lmg{V)_Kobz@&8xA~#Q`jiH3e2FhEivxBvSX$F+HPDh8alqu;p zNaZw!9XdZ)%bDhYc@r59>-=S{V7dV1oz(fuTFLYg%mcZTiLHuB;|@q4B$d}O#Y1^~ zx(6BRm^z?5DP3uXdZr^#o~kYnTRqbiD9=P!nxT=Y<1WM$dob_EeF)D}cMC%!lfeTB zFG^R0t&zzEv>BG6jUiQ6gsq9m;Sor#ks)7Knys11@d=0ra+x$k3zHw5caWilDFwm< zhi5BO50v+W`yfLr(-tUivhG2KHl`m?-aOrd4DC#%Pr+s~h|A7r=wO-&;c+b2-NMk# zv;@Lq*rF@V(9IUZ&3w9>)#cHikYXhUXBK`?%LI^fB## z@}BA5V4BGE7s3PQqlrvhpzXcjF-K{JiA=(9UKhherT_>J?4wCcd%(O#hIIWlhDl5= zFF`gmGL(RMbD+F>FmK6gh+Hq27xM|C=XPg&12dK z<$=n`c}(Y^JW#1PkLene2g=j)n4Up-2lclw%wxLo31kB#AI)QO{0!njQo%eX9|(_O zmcA9+Jf|$8M#P$blI|pd2c`Xwklm{AXUdtp7lAmeCBh%}g`lyoGE#nAX5~E7|riJ^2gv5rc`*X10S& zKj6GwY)6<({)6Ni83cq^GoEHz1LY|SA7(tuWCK2jqmjYh=p@^DraMrcztIJ@i%dPB z?aB<^H5#_SJaJYG;7J%;l@ zarBsJAJ}D}9FV~9gy{vGC(ZDb=?8?z!Dv##2s&O7G^E_dA#9Ss@RUggyc4&LL)D~> z;Te+(lxJs!iP3-!Sa~^QLiZviQ#amgz8*cg*59`&*{d z5FW!V3kHsNOfTR(c8(8Bf1tcq7Q7rEnN-<9wohYtWg*J(g$cBR6m(zIUke$IZ%lbm zxxW@l9N(Fyf_ad!yq`>S!90koe=_X=^B^Jklj$g!2b$5e;rPXL1MD;Fn4l-Y;WUOXxYZV$UF z)no=%W;-a)$Eu%!joA%8ogz{czkIGC4!d5sJ^t#+_-Fy9CB+Bi;GZDHVKeh=l{v^vPZ$t=SS@=+UyisBXqF6LS& z?}b$x0~hm72#?{Hl{5nv^C2jY)fyys2EyYI2J>`yAf_0Ad9F~NzjZ$Y7jq1h7i~S6 zfs45U%1gJ7W#VR*0UgN0(8f_>oy5e=d>G0Djhpf?pN8^4<8D0651~BJxEl}iPbja^ zx}SlUnV%10`xNWR47|+hP~LLueg-~fM<{Q-^<)M<<|-&}yR{DoKXVh5ch)+HgP(aG zl=s;B29p5u3MlWRbrhoj^A|9$nc=^67lR=4G69Hv0yZU#Ld@%+JQErlNj?1Fz*>Bs3a0+UI68RN+NOQ9bjG?$4}cP z4hiN1P#&vYHHQTANhnXyE|y7>`6863Y?s6&$@~M#Gqu~oAjQl8+V;=T#^G*vkU@%> z6UvLU+rl8tEC}Ug+Z|+(W|o5TK)FhWSqaJm2)$(kd|5zC<6859YOTwAs(* z&|$s-<~?HsnWD?gECzDfGe(dp2F%=GUK_^*`x{IK%)(IKO#3KC17;a84`QYvvkHU< zHpP&+MjT;^3G)RB5N{g8Ci}%4Cd}-hBW@VlIQH9vPV(S~@~+q?F_|)3L3uCjW0}mD zouIrQ_DM`;%(+k=yF)CKIddtLC+3jEWX`+*%xmOOby&$^!Mp;>Gjv$bVZpo+%!7ok zCG&eQ58`S|<}VN)*wvQI2c$smg!tWtIYk=8gSgs;c?y`<#xczymdTcR4wSdvA&JSB zc?XmSa+w|T0VogTGCSrwP~HiLSSEYsCs5vPha@I@W(FCM4G@<(z++R=@gRo-vp$lX z3$rbp7scqp90TDoC^+6=a%FCV@^l@g8C;o{L3kW9xwkO5GH-zJ7>pgyaJVu*0rMIe zD(o+DxG_t}f^472AnACM!<{)2%xmLtcHF|?&72731%r8+P+kU@w*dovT z2QsCNq1N#UhYxcGocEf;mswjLBG=|9&EU^$0p(3`JjmeBoB-u5a9qw1z?=u?MKK04 z_d$6p91k)CF|UF0Hai|<2xdMAO+92#=%Gsf00>c_x$xS{D?{ zyb#I*tqY1}UIpPvyx`>HjAPyj;c@(Q66K6%J_zL%%1Lv^GoOU=*qs$QYVY+oKRk<^9{BH zW<@A3&UrFJA~=1*TBAu&9;h|y%9#S^{Sxx!OoQ`4>ngLDb-<=HGO)WOFk~~QLwFn@ zzvnRLLwO*-=P*}*d2Jk^9z!nkJTR}3L(HX(A&+?tmOwK}P88whT5U+r-vr9c^Df1UFuZ>}%OABWyvxhp!oox)WU3A#X znR}qTB`#f@70e`Y-HH)vVyaYxxoO$ zYvTabw++m_P#&nhZD5`a<$-!%qK626xwk4D*;*LU|#szc}YJpM~<0Tn{oVV15SW z<+}doT*%C50WzhLq0)6S!y;x$D6iF(g=;ah36wX<^)TlW<_lI3l`C91xt20#+d_Cp zT%{S7G0%bWuDR+kEo0sS<-K*)VOq|72Fl}fyTP=A`2&?Xjqg4x3kV#*seX|C1G z4E7M7x|;^q24)i|&(ckwYa{alC@3h{{?=Kd!yZE1V#_E;m1}{mc>05Z*Mm2(E+7CN2=(GB-c2Bh1I3ybW#*49A#X z!FkdQ$C(9OAu6}Kfp{5i5Z*~J?}`_McLmIQ3Fbjo!yIS+0_HU`JaX$|IL@5n4N`do zyr$*^a{-vw$neQ6h3h2qZYb}+TL#xj=Ce>9mwOJ^N#-X|o|t<9*GXm#ACM`H4EpZU z3}=~N`$Krv?iE~TnSVfe?(X$m=a_Q>Aabeh^;{R2Spq@4i3}6mJGm|~TR?eB-6wHf zftI_VQgJEcH7E~MLht0d0q6Y^I>>bk&I6Uu_m~U7raWVm_Pow@pP4lXWCO?)X@-Z) zyl~!Ku7}K4aNbj{$IKOQ-cQD7%*}A#W6l@M2jRSTT(6nm!FfNp-ZBdW!)##Ue$VUx z=iOlY$m|8-ae!*IPs~A3p0cMR=O^Y0D9^x?hx-$A1C(duS;F{!9#w3Pg9H9BzpUj+4 z9%#n)Co?aU2b!_{$t(rsfo5!fGRr`C;60PSnB}27&}{r)W@RW3G=KY_Sry8=$335c zfyETe1G(Cio0+8q%!ACvv#~sZ@<8+NY%DLJJkZ=c8%s?XD6AoCE;(76p*)ZcJS;s> z9>{iH7OrrJO3<7zKMN0p#{u#KKZ^{M2l4|yOCpp9@~r?%CX@#X7Xg+WC=V1a0xbDZ z9%%2X080^+cg?GfK>&QN90S8KR!~|(=Gk!zu+)Q9f_$66AjHxK<~?HssT5|J4d#L5 zq#1-+mVkL6IXiA)n3=rd-tOF@FdnO#w-6G~5``D&?TaLr?Cr}f2G<8#O)t)}4{QUd z_Zh`44wnO&DFNq!%tY`&W+HeXGbQ0FL1s#^oCTZtj1%NeDVD2X9>_Y< zAblYFq!|=heBrz(ZbgWf7DIvR#Sg3X})3 zU71BP8f3#U29WJ4EP7yG8wY3bCt$`SzOfkt@L zSR$Z2&$5~cd7#{Hz>*2&fyxkLmKrDzR8E+&Yyk5b8J>GrbDObTi37Q%jR92OTCga@LwG;D zTe)pmRzP_YK0Vy_EIkPjIb)wK49+a4pgemp?+%pb>C?~P%<=)s1GUziS)>vn`arEU z7Zy7x57b(7WeJ4xK&>@5mK-QA#Ah;tJ4+*!2WqW(u*`w-5_~whJXti7AZC{MOy%}s znFQfUyx?qL@L|~p;eqE@d|8e`d7$2sFUxr-Z>>)ogCENa2#;a5vLdG+i%A;D%tnS1 zA87_ZmJd+g5uYvwKb9KM&3O!vRW1H3D>FbUk8yz3mH4x4gYrOe>(BB5!UOl2{aK{J zi^>}ruKTQE@Mlqn@?QI_VF+R|f%5+QtYHXc*^mV`6I?$;u!w+{pEoja`>tV#X8Di< zkpsma`%wO`gSB!EjB$PPmZ=43dJO?VM^28#rE5j!OJXR;{3c?k@eECyg6 zWDGuwli%whQq<(c^=FyydEfKH%imz8h@RkB!=f>c6cx{BpM1&G(ku+)7rLluikC5Q*9Q>$5?fO(A!y}t7q z>R24AAabD9B8@DdQ|wg&7#NrsbOTV?%nZI@5xYQ;taBhp)*DVTF$9CzxMY*SvN>R~ z0g1e712Sz6lE_zOkO)YenW2RbWD7(+rZ~j3#bCWl!Q_50`I#4F!cSh%P6uW_1_l;} zt2&_5U>^j6PR@TG$iTqP@D8jJVgiU{g8B|(7lZ`4fr$aX+b~@P(VHCvayiIkMh1`z znHWmJBIRJR5=?^J%)|f@X$%6nxg`kX=60}bCs?EhECMotk)a5H%n+6N5%DD13~9(ZwynA`mrRU^YaTPcSG{ z*V=&82ZPxVSp=JzAu1S@LO?1R8Ir+zL2M?5QC*PG$O4B+AvpAE;A}<)WRV`QEF^3{ z$brHf!DeIti7+xi)Ieei!kz{;4Vev!K}H5-5@P!Su*$z+Qa%I}o5*S)Y=}w(n~9+% z1e98O!0JJ=ObpAwBI}Su5NcS!vaAdcS%^81RD?-FOhf2}xfxj{DDN|Ya}Xl~g3S!h zO)SuoO)(S{RvMuocS3Rjx(Ew{Nhql7atQ^MU7&Q!4hXHVv7Ls|JD8FEhkJwu49} zh7KgQPZ%f+L&2s&Y(cI&KqVNVk{qH76br~D9t*g9U}fmm0NIN!%g6w734~-~NCuZz zm}=6&t^$!v3>9c>W(H(8W4ZxUZZk5lN`P#K$P(ihbT{Dl1*$B>7IYIB89?rbkT9PX z;0P03F$ie`>;cC+X8Qpmi(K}e0IOW?1BzKlO9Nd5=5mlOSm_OMKZFG7WnzHn1?53V zP6VB^3kpv?Sx^dWkp;1>;3N|RL_|v(Bn~mh9ElAPagzq=^_2#>Ele6zgTx`J`45g| zk#LY2kQ*2o&Vt#H5)YXTX(uQ|fb5C~lOR_?TnKXsrrRJcTqFR}g-jx1jgcWAY}!{j zkQzv7*5m|Y*MP+#WhuljxJZZ}LB3;T0Qr=O0ojibT_E$Bpe6hRu*ncNyn?X7bpgb7 zh5MuK9$4NPLDF_6iO;JS&t za*~l@64>NfU~&nVgrr+gxG^$7(jFvDVv0aif=F1JC*D1f`~^`D@-HlwA>}_J*E6A% zw4nL|7BZmp1JebGHB1qR`4Dm)IPO3ynHjc&eF|bTLD}~DpqK@TFftr~sI&p4D2T{u zBoR=HospqS7ZfkZB(fTaE=+$x%3cu3#83tQp3o=r46zLWHKWI zh=i$um=AI%%(W-HK(2-8odq^II11#W$S9Brm@YvUftUsfC5XKVU|q;2;9^7UIt^BT z9c<&hD3D8DM}bP$A9%%?qCsv0#RU_%ugA#11r~w02PDqOz^x1Ng-A5WOsQy)nT+6& z2lbB_8I+?zvie|MmO3EQAfzo=1hbBY_z_h0qJ|`>C&dJ9-MN7EVurSvKFEAfxIt1N z69aOX6C)041HgJ@pcrRl;EMs72_YdOkajhq9nQpnU}I~OLwuwLHV48chSZG#g_~sz zC{#hU8w`5ptwtp0hP=kSvIg;>X^?sxM8ZTMVR#EH3t>Y@kb7V@BG^m}Uocea#e!T5$&Vm5Bf}x^mw1M zyn2xBObj6PuzDZjDv$^x14tH`#HR8z*!@?)B#6z#a39WQ1e**aK`jtQ24oVXo{`}L zSUsfV1o@GP0o2n(POD4|-@$4i{)P1J8R9{4ikyBxIR%!FxZ*)+7}5?$u(6H3K;jf) zGK7Sr4Tvp}+8m+=GCm1W19B(Cg-i?@V3$C2LEPg3772!vOyJs(nIQ%&0#d`okOgK# zOv5Cb!S0^~Rs&))GVB76Da{3ofZW5xuq_@`2A)6@fs_vrl8NCuSQcasCYu>-0wV)L z79zsJ05KEfPDTb$*#a>QQjRe)V7eAl1maGJ36PM1kRWj;hKFF6Lt+^s0vVA2iLfv{ ziwBjopTI5$$ucs4NJv@A%_hZ|M!J|7)`HF43N{}i4k3|a z8Il_Jf>j;|lXHAQF#_^CEQNsD6{uw$s1-q|wSN(8Z?!HcY$0U=ra71*5Vv8P4{|vZ zbo>ewGLV!269L5ntcU&->ZHJ?aU>mWi1iKIt3lI|Gau6HVB7(4c zkW@m(qadLK>1#lAVUm#Wf#hyX_oIq%F{m(bGpI1|FsLv{F{Cg^Go&ymF(@)9F{m;q zGbl1BGpI7?GpI5cGUzfGG3YXwGF)KrVn|>JWYA>@W>8@aXNX{oV2EIhVu)ajVNhjA zW-w$(W>95FXE0^RVz6Y$XV}76z_5d{h~Wrh6+;4pCwRrdPlgwqT?~wjpi|#D89{78 zM$kE>l3-F1OlpEjLojIxCLO_~CzuQblaXLD5lm(>zTiB_PzW}&5-cJKp4*iKpJ~9! z0J5tSEIW}=A~2O_C73P906I?|L`pM&$OJH%${-0=FUbH}7bD34S}7pOFq6BVL6QNq z-sT|Ge9%f9N$|Nx7a6w)_VHX~+#T4*Gn3I*^aRgMs2b2&Rh;1Syd@bxYXu&H#b1KS zkBm`4?|B%RUT|*Z1&RM;)P&f}v?AD=Ns?(}urM4XWC*R|i(~?+kp$0+gZwVdAPGK4ZX-i{=nlS(4C$eJ z`F1iegdPLC{1%@fQ+22$pC#D+iD12%VDcct3r0pex zFeuOdWb|Zu5wniTkV)FpRu~j7p2DCMp1^RDfg#o(tTI&iCOADj1d|JyjAM6*E@ZNg zz0CiTDJ6El=u4*Qu}4KeGHs4ME&7w`KxCF7e*cMa zGFQaE=iy|oi+|7a5u6J^IsG8RM+P%jTk($!p#3i^8J5I{i?3u@8y_S7kwHFzo#i9L zlK9!;D;Z1@o{C#CfKF6>$?$^HNdlDnq!~cvk~D)N*j`Bn(2AysOdk?JsqR<8B8iDi zzM|_T9x}Y(+$I5Xe-tAqOzuiFGJ?)YHe_l^1f@g$5D`fZ1{MY-1`Y-e26YAw1|9|- z1`Y-R215o81`!4`1`Y-Z25SZm1{nqi1`Y-V23H0S1{DS`1`Y-d27d+)1_Q7f6NVfH z4h9Q`LIw^78?YJ&hB5{Y1{bhi4~A+64u&TT{~0(KUNEpQaxlDM;AG@r_yD%$3)q|= z41A0n41XAe895ndFeWf^GAv+BW#nMcVfx6#!C=4ya)}8O*cK*`8*G@qF>x?BF#TrY zV3@!Ja_tnbni*gXF57$z|HvT!j>VV=Xn!4SjZ&&t7&z!JjB!O+5z$jZUc!2$}m9u`nY zPGA9t5(~)hGr;0=SU@4U04%ZuEV}|MzJ>)9svB59;kJb(jg^C82TL|92g4qg0#+u5 z8!TZg91M5B>K}mBKVbod(hC+)_`Cs|_JIYImcFonV&Ml1D6ap2-NwKQavKXPNQ8qG z&BupvJhBK@WSUDIjus&twU~pgqne4&_ zGTDO-WU>z%$h84%pfCwx1Gy)H4U`6A*g&Z_fejRHDQuun&0qti)f_fOHV%dYHc)Cg z0ygag*t9cX(=LEby8<@t2G}$ac95?-*g^L8u!HQKzz(u^3cEEs2g4e$_y(}}7O?mp zu*d;+kiAFPLH3?t2ibUrJ)E6`;R;yx23Y+a_C$6Lh6n6v>>LbF*t6L=7+$a!uyZiH zVJ~IpVEDjZ#m>R-g}t7ggW(5z3p)qHANEdm4h9B}K6VZU7LLj691I*BGuSy81UNvh z65#;(T7m;)uM7t$^b|NiF{{F{h@FE$gJU^62ZIg=C=3laK>5prV+}h8g9XP%b`Ay` z4p3Y;aBO4eU~u68#fS$7D3*OVcC&LZ1c1p94p2!F0VZR>A_*Lz_(}nj85{@LIT&)l z_7;H25{{$n91Im;vWDXnI|oApm~7zyg?tB??BO`i&cQGNOitmr!p^}k15D20xXI4J zumDUh0gJ2vlWREcv2!qN0Fzrd9;RK{I9{-GFdP7rM>yWHb1<9$lV>R*y1f^sh&Tw{Ch6+wlnN!1A z$id3cz*)?}%Fx1D%E8Le!CB71%Fx4E$-%*}h7;t%4V<9Z+`TzG&J z$B@l%UQ&-in;}+GkHMQ^j-(!gGDEne9)mQ48G{~!HAAMP z9)mMOrsQJgW~L6l!<>g%%@~}yK%_D^h)m|0&9+BuF%O8{%)gnzj3HCHnJHF6L8qCi zlK+5iGt)f&1pQ_vZ-E8+%}fOX4F=6ja|9d=o0*OaG#EBBy%RWKHk-vmFu@+ArqQXH zDM|RCQ!`Veu%dG_(<GBPl5Ffi0IFfxEHHL3%h#=*kCP|v`~z{9}6(7?dRz{SA8(8$2Zpuxbv(8R#V z0J?^znSqf(fPsObg@KU)bX`F!10w_IK>jv{0G%*JCTgBVJ+rc}XcO&l}-h;enc(3r@;eE{eiuWV00G~WxC|?p^E?+5M6WGN{or1>%FAF{t{4Drg@Sh-ykg$-XkeraNkdct3khf5XP=QdB zP?yjGq18f%g-#1y7P>9;Qs|2ilQ4&{ys(zAvv7>?3(?P_e?-N_)WuB19K~Y9O2wMQ zdc-D*O&6Odwnl7=*g3H)Vt2$oiLr<)i93t?izkT}h}Vd>i1&*x5ML_3L43dX3GoZ! z*Ti3oi%3XI_)3IIG)nYIOqG};u|ndY#5sw_5-%jaOZ=7KkmQ$?l+=(kmb8@A2gLyc zkK_&pHU>rpb_R9^P6j>(E(U%EZUzAc9tJ@MUIrlsJ_Zp6eg;Vf0R|}s83tJfS#UpF znL(LBok4{`n?apHpFxwsj6t8lj=_Mzoxza7o56@7l);!GmBEZ5m%*H&gu#-biouGZ zmcf>xiNS%PmBERjoxzo%kHL+hpTU!18iN}CjO*uxOP zu#X{%;V?rC!*PaKhSLlQ3}+dV87?zqFg#|+WO&Jt#qfq9o8c`(4#OvgLWUmSi!)~SjE82Sj_-BI$|#$=!l=wVDd7UybUIw@PQ7|c?~9s zQR6NM+T>Cq2-1Z~3JO&-GBAhrxg4snG_L z#-ce)3=Gy_5?NeI3}n8J7|12oVA2~bf=m1_SPi@QGbRQGQ81}0{)UNx0pj27;vjQ~ z37HiVAbWR6fc%JG{c35D%3abRl}EwkIk3o6X^>rSz#?D4?7v_(y9`JiLQaqcvFCuv zm0;49#fF7}0TP}N6Cipa=0HsNBL@mA7I~13obsSB?cyN!h^c_gCr15hu*x&4AU9uA z1;x}oF#8>t4T-NGs$Q%N47%zdHP&F#OC4nXN)3?6dJT|`+ri`k4UjmdY@_xuRtAPo zx*+wxbrEW==!4i0T@ceC=0MDRp$}5eZJ5r+zz}B)QVB^9rN%t$3=GZ2g6s?oA6doO z85kyjWmkepi0lOuP^jKB0qOc+;>XUwz+A@fRJnLLFPc% zMGheK&0tc^9>nf**bP_7;s_Ffh}(l@pYVZ9_HhD{5nwVCO!hm0Tm{LqtDKEF85mgP zEjbw&wm92!GBE6N2B|;l3<{--&Y&=asD#AJ8V`^NB&Tl$vyX$xD;^*-VPOI?;jstE zgqI$hxEL59zJ|o+HxH03qbJB5NX$a)eeDUd{fnmzHv_{TPmpP>ULX@h!Q^Bwka|cO zUgQM|lXG5%+zbqm^baX}A>}Y~2@ENRAtK0XAi9{mL1vbFhj246K*-zPW!wx5kl2L8 zEF?~mT>|kt!~}?q5OW~5Kx~BA1qm?`Uyv=3Tn15-71QwAo6$qeQUObk;PEEyOXrZQME zFfp8Fux4OnIKyDgz{GHt!IpuM;T)K}z+lh7#BiR$o`I3!5`!ZH6T?LYM+QcQYYff| zObk~UoEaDyZZNnqFfm*Qldl=v8JHN}FnBUBF}!8)W?*7?$KcDr#PFHHpMi_7#9#s@;~7Ei*aXH}1}26i zMo=3z8BC@!HZm|Vq%eY7u^Eib3``8^U^0`jm4S&Ni?N-7i6NV@lYxmLhq0T1i6NJ< zmw}0)im{)8iJ^vZA}GEXCo?cHbTdw6U}BifIGur!VJ_oL1}26%U~(SgYz9V#`HZs} zm>3o?&ShX^SO_K;GtOsVVps$wmoP45U}RXzxR8N~VFlx221bUJjEfnV7*;VZWnf}h z&A6O_kzozvat0=bwTvqnm>9M&u4Z6l*a{|hFs@}_V%QEQcQUSLU}V_ExSoNDVK?JO z21bTGU~(VhW(FpPy+aUXJBMF0VYo|9%Nu*I0+_CGad$|F)(?K@hB*zF&<@LWVpb19F)eu zWa4CGVwl9l&B(+sjft0$iD3m3KO+;vN+v-@CWci^!i-D|tC>U@nHbhEi8C@W ztYwm9WMWvyB+bagu#ZWWk&$6PlPn_>!(k?QMn;AsO!ACO3`dz185tRlfyon0%8X15 z$HC-DCRIj8hEq(cj7$utnba8>8P0&ob4;3yOblnihBsjHGm|kR6T>Gk`Gv`pk&)pmlPRcNWHx7HVqj*rWMpJu z0h4UZ){IOHtYDIz*_M%!fdfo(G21gTF>o^5Gcq#pFgr3bF>r%PUS?-TMg~4GDZuQ? z$i%=8CIy+@8JQS_m^~Sp7(|%885tQwnY|gA7{r);8JQTwnf)1=7^Ij38JQTQnS&Xb z7-X1385tR5!K6HMI3p8-9GFyKj$~wFP-Ko~WMoicj%H+HP-c#0WMoibj%8$GP-Tv1 zWMohSlN!v4j7$vbU{aGgnURq}i#eH*i9v@sm64G_mpPS@i9wG!oso$_pE;9}iNS(7 zn~{;h5=>e%=Q1)eSb<3!=6ps*23s&`&s@mJ#9+r<$jHdx$Xv|G#NYrXotR4*85x|J zOBtCMe3;7_85shZD;b#>0+=fq85u&Es~MRXLcnAgb1fqiLlkp8BO^mJb3G#yLkx2x zBO^mBn2cv`W@KWB1Ct5Nt&EHeiOj8xObp4)?Tm~J8O)uabOs z%)1$x7!EM+Wn^SH$h?=4iQy3Qenv)y!_4~`nHY{RA7o@?ILdsGk%{3L^I=fRXFkfv z$Z&%BC?gYtFw1dJnqfJ~$iyJZavGFoSk8jd49j^&Mg|F%^NdUkk}MY)85yKlE`rht z%VkC;26>jNj7$s)EY}&C7}Qv9GBPn}v)pE6V$fx|3yOD^`=EGddC17fV94^Ak%_?o zOxm$LWn^TqXL$;WS(fLFObm`JFBzE_oLF8nGBG%_yk%r!aAA4R$i(2y@{y5=A)Mti zBNIas%U4jD!15hbK7h$AmYf2m`}crUOS97``#RIKsg2ok`#*1H%s{jVlZc zKbb17FfjaL`tgB*;WtykM+SyJOfNn%F#Kgo_{6~QkICU11H*r&0MMzv%n9EZ7#NvZ zz<1JxGO#inVFc}(UB?Z&$P;>$D(HAV21bVa93Td&*bA^22Ln5UHiH&}34<|%DT6VC zJ%b&CJA)g82ZI|!5JMnC2tzPKBtry43PUnODnl|u8bdNeIzuu;217DKCPOkq7DF;a zHbXK)4ns0SB|`;6Ekg}M9YYO6Jwpvc149i%BSQ^C6GII{GeZqS3quV5Lqzk zoS#=*l9*Rg%m6dODX}=!wIVsSpd>Rt50?=T3lPe{W_jinl$HdS6s0ESLgf8ROAsQ# zC5g$|t~sf>sd*&~p3WJm$=SuFxwtIQgDEIxa7@WbEiyJ@a4t$VHev`aDN4*sPjwD* zW(ZDB%yTVE%`0&%N-xH3P<~M=LqJh}dQoa|F+#aZW>IQ#Nq$i!LI`A@TViHTX;CUd zFrX+uIkmVLuG}Lr59A(@i6C*e%$!stA+RMdzH@$VK~8E(Y6`LYFDosmE zEdtw>S5j07VnECRv5?*G=?ao}O9bZ(24s$7N@4*horNS8!JH4y=qRBGwFjaAl9WIh zHZ?KVH!&}>pfo43B)^CO7Dzag6Iy7)H6WrHY6Pe-C`nDPgsX7POV7+pg>yYh)6#Mi z^B6*kQd1cMQu9(W^U|SigqlzU6=i_=1I}=%%!7szObTim*f6)m;*zM$0&qEjyX=X| zEMS1DWbiLbEh;a{EJ&d*EBEXsuoxTNN!ri0P~B*cnAITVpCLW@(QG7HR17?9GR zZ)!S=>n1g zM=*nTUVeEVoC}Nmkj&iF;M9_m%)E549HL4HNlZ^qO>s#qNn{90EJxzON}JHU%nGnH z#0h>ONNPM0Y?w`;aI7dPN(5{1POU5sN-ZqSEJ{rQhc38q4@oTs)hvnN$Oduz3sQ>` z!8H_!7hIB9QVRAfh!>PvT$)pYT(E`~q$HN4`sSykg1iDMY8f!>fvJZ?I>;Obh&Jc^ z+}y;x6a=pzu_(0&WDrCi#0oAcf`t<(1G(mv=7QXpU&Iiamzh0>SyEMaiiQo-UPniMc33P&Jvw*+}YO%1}i;p_xCpB)=#zJ(U4e z2BQhNWEN+m3Hhex<`-3>3A&^fCl_TFl;jtIY=x8w0f{Ba8DMTyW`Rd)PC;rB)NfIl z1<3viN=*bO6jFz&@zT0EHS4vHKej2l>w1*d`ojmGLsXFOW?T-sx3G*xwI&=q*4!3$)p!0 z7GzX11Xt$frj`_CCL?l`Cqw}vM|!$s78m3fCnn{jGJs;5!P7Y>KQ9%`hZ^pjpOcfC z3`(EH44xo0sYPIEPf#WXCm)z7q(FqF5qKtN&;u30;COS&$xqG(Ro4u@i4~c-rMZqd z1sRFR0-z?KPikIzNd`kuX`Um9aAI&T$}cT&&M(a?fiS@u{7Q3^Qj7f4JWD{yGc!N0 z7-nd2D#*e4MaAHPsyHJ*zr?AsB(<0!C^0W3KNq607#b~lL8W;mnYpQY!Kp==i8+~7 z;Fw`R;d$nz8U00p2d*V=U)zLWEEqGfYdlA=7AD31C$+{nwkw` zhl5LXkOVXmK+J&r;!IHdGk}bPbKG)Di!&HNn*ED1(=+qHOorgp5~xmyQD71j`V3$z zopbVwQ^8EIm~Ucss&8UJF@tAbCa4_AtV#tl!Rds-H7^Ci0Hrig>yyE$I5-tlc!HYc zZkahb&M*qTvC(sK^12RC09gttR)b55N|Q@Ui&8-eycnK=V5P0AzZ(PCRiNs&s5FnkDG?Gtka8Z>t8gtU z$}eK@NOCSpO)N~^8{1Hsf8i=p?Srrg$$)2G9*7ZwUD70n(g2W-;y+j zk`jiT91DihysEU4#3Y8C%-qZphNQ&eRL7#C#7c&O)S_I5+{`?m)VyM_FeLRd6ob27 zu6Zd8$)!a_sd**fh=sC2l}9Q=aY=qrD#ZVw9u$P@oS&PNnU|UZ5&;!Nr6ov8U;?O$ zK&47@MnF+&8AEc05kpBpelbIlUr4@tK0{Fmh?8l=kY&VB#gK`TwNNt}EK4~j=7Dkq zgL7gYIOQ`yGXp%=1iOa#ItF_)IQzId27y`bL9UJ=u0iph&i=t63_h;G!EjEnucMDo ze27PoYp@4{i)%oL2aFRK>>m^YDm6eQj%SoBLuOub5x75E%;1)p2P(%>8Ne+4P0jxGa%(BP-zb8prz)eFa&3Ux{$&7MI{Vj#pQ_w41plF zF@tYnW*&$IEuAxqQ^9GR!6iQ^wJf!$I5Q~+(NBaF&TgeSIqoH)430TD`N@eTsW3ml z^A9L%gW8TIsR(BUB<5u%Gk7F{${dipATd+S;F085T%4Jn2NEl0@J&rIW=I0n7XGCr zkc`1lSelqpl$ck-P*qS;#83<-!KpdVH^hx0wDM`&OC}GG0`>+@(#}$==vH+;o1LsU=@`Wem#GIV`a!{EC)(9#c7*fC$ zcWO#J14_*1IsU^@RAEaHu;N%$W%8(2jw{R{>4o*!?0hJ%% zvI1Q2l$NAIMk$hulEDQ(#IR)0$OS}IdQN^)Vh*Tq096v8wh-7-Q1zIZSDG4BnwJM^ zNP;R2bg{g|+|+o6BM^Z2vqAY5zP_1yHL%f(-t7p!@?e8_I=B!VO^njm>}w zm&_uDw9FjnXiGdp3T)&FGW-(HkeHKMmKx6hZ(xE=g!2$4dP0Jm!Lv9FG!o!i0q$0S z${?r+#6TqR;DVgYlEBjZ5>UkDLpv#+#h!V|Ii)G7DGZ*)t`$%w$UB)isUVk@q!z_9 zfU6px%;FMIDVbAR3~DRJGo*r)L)oD82(dAq!6mUI71Ut_CoQDngKMun2?!vlC_?%uHXX z8K6cLs5Go(aLzBNWB|E4xF9i)!KEm_05tFwl%HP$?MIiSg8GSwr~wrlpau$96w>_z zGqY1GixH~8l?k}iL5M-PAa8-Iz0zVt`3w#;aIXoh2pmQrg^-RBs+ey%35U4$n%8;3t#*hgb@CLQ|Qj5UtFmQN7TL8($pmup?F}U%b z!hkR+71UHpO-uo~584I=B}gQuTYf%hqz%%n00*RVVjj554H~b>Of6<8NGvWc&o4@0 z0FRR9!&5{&SakqQ78GxA4m4=Np#<(PWP%$!aCzu}7{ret7cnG(M-Af{QlNvH@nBCv zQW3;nSa3?Arlp0Z-47aDaB(Wql9+ZiEQp-|vK>Y~_101fCi^VQ%g`pK*c#I<$(&KfTGm2 z%nGnBBrZr6R78PZGh577`WE-gxh*N?6hnZ+f=44%bKnR$stl?>U)k&%cR5v8DDN?`y| z5MO`>OF(`D(O{9H{QMGd2p1%lfI2#$h)66b$iWhxC5c6zd7!2fsP&s!40T=#14_K6 zGJs5j#wa|-a6|(r+&xnmKor<9;NbR5fehq;MUaBrB{eOvG^Yfdv7v2gs1TAO_tX+3 z9w?fT)w`#nXon0eHnP(hpd5%1pnQ>+3a!*YQ$CLgRh>{oG;pfpmcQAQ!{reM5ahJj49qCW7RGVUocCjzPh$ zFkYCy56A@};E-Ve83tv7Mtz<0^T1;a`FYTE51L#7r5i&_a|2K!07oMzae!xBK*~Jic_KGL~v>exI+&uUW-Aa1fT&m zn0PU0YNt5WKe;3^2R2e30vh#(^t_x(Gjmc>iy(@?K5zU#R8ii&^2i31I z4oCvzeIzLaHw99wLCZ8K4_tbArhr746yryQz3;DB(Yb5Qz@t`UX&eNT2PQ*1nOM-CKhFbg4Hjz0-_k)wFH-G z@CFa4E)2;>sK`hx_Q)&&jZde7Y6Eb224?xErGW;Yic%9(pa~Ds5{K1FU}G7;N?~q7 zcMqhphA0H3ZO>vb+rJ<+k0GG61mOs9dkriHZG+{ffon9dU68bwSX`W%o0L-taSLPw z5G)OLF}N;-NHL(Q1UCpuiYmdDf*cW)SPs<<<$-4qL2T!o)WjlCPC=4~i-B`0qW=V{ zw~$wEfG0+R63d}(0JSsVT9L$jQbE1}EA~kZ&H#<5f|UBCdghftML{_XY#I85UlH8l zMTzBLM<=5>7|v(N%qvMP%1g|FyMZAQ-iJi%t$}9Gp&kx`nhVzj6^HW~(A@-CD*%oH z2-7#QIGdpyynF{rfo1|A0-$N1)D(u`oc!{j)PmGRkdMI>XaEE>M-1vyj5y_&=B0p|>mXI0#eS)&pt&Y++Y_9JKx)9P6o?SSKk-l>2A3ojmB2Wzc`5M> zNtq?Zo_UaXk4N;n!R|n~3hV|n%bZ+;L*kwNeFK7AgF%e|2CzVIfUBzugNv)1W2g_R zw4XnUY8O{GAIA_^7Y5JZ_+Zx%7fkG}yz_&mGM6^z(#r{5-)E5h1P&P_>|G zi4a!?r_kU?C=;d=#)WA{;k&v(xz0ZR!Eg>JD8Z}dz-3iPehFx?0fG(crht@q!e=f( ztw8u%nqW|)Eg3X-35u2+a3?)4KPo3P3DRKmFM@W*!996~5|HsABMTtwYZy`?Yj7YA zfLRWvL8_1}b#ZkHb$15^PH>2SkgE%1GME808SLpC9}?v18qDAl=?7(j;>9&29vrZ+ z`0#c0jrVa4bM;~Hb&QDjbqsO#VDR898n?{66i`{2T3iAi{|C7VG`s;V zNT35rpmk4hnVkG`hRnR;_zZAUo}mCVahMC5I{@ck1~AhnH4iKS&!&)>B#4UQlA>Zz zW@pIB&(BT-^#?%HosjiFxrr6=$r*{6d7wez_?*P5N`}15~f*C0oqc)w6z z22ctCGn_m_d|ds&%pli*c;k381_*6v0A?5(#v2-2Fu3}=#Ro_FI{EuBIQhi;2f4Tg zfr>B_$Shte11O7SCi{T8fyFQm)H4t%7i1|Hs8miSXn98tc%fQKW^oCakp$((CzYl# zDT%7ZaL%8D71 za^jOgYgvjJauX|{-b~4Wv{`~HbCdFOAWc5k+=7xyNO6`}l9>!K3*7KVVuHiN9n`D? z84gPw&WSn6PCnpiNpK$(tO~3ZY9Ay4f~IA`A(fO_0$E-IRt;%VfSI5c1t_yQ!4x>= zWTxjqsym2_!POC1Em)gxuoJj+_ACa6EqJm9RPTZ3U>M-WAf#Pfo&8;0<3Rq+7$yTLnLx#gA*PTKst}9^DtJ-N_Xu@!^L6xtDS&c8rh-dTs4HN?pqzlN z6eNbM7Sa=Ea06Fut}YDD0Y0vN!C)#Pguyugq#i_pM(;tbVMsZamztWAngR~OqSOLt z+!Uo2fRkA%WVs!vEXgePNi2qpYcb^IL+UO_?uHHpL5s5#_(IQ|%#xhcJaD{2R)Ih@ zK{(*X5rhdXa~U8!=M3;lb_fTyeiRy^prSZ4FCC;eGao!G2}&73skw=npov~cAq{Vd zASpvr;sY*SK!g*R>Er_rDlie`8W7A-lv?1MnFpf4Ap=RbnV@w=VE=&mpb!G{l5)Un zM{+VtK*a-uomZO6kOCr-azG>q7o`?J^A>0w3@A)NbNQgE7E-)1lz`UNrlh9%AS_Br zO@mwGo>~Ic4;x)anl}ZHl7mADCg}-kI+rEpfZO00f(6he{4iDV@Zo=$2-q-a&j(Zt zz=obcqfVgu4u=#dLO`8J@Gw1iT|G!Kst8C8xR(U$aDkMd2!K?;m+FFK;T(`mP%3z- z4XoGgp9dWc2YVH#B$7_Yl9Hm#q|%bqVyt?xNkhB~T7nF<48(Ly0f#%hQwo&=ji`aW z18P^Kf|u@rh7LdrdO@8Tgz@0fIp}mVG#f#NSK}F~G7CV)#4{9wSFplDzcQX7AGY)v zynF$)_8GPqGoGOcN65fs5O%|T9?y^rUaAEy>|yp~rWVIDq=L4CfM`&U8X8xiS?iLb z#ANVL3p|qJL4*I`h1K!!>9ly*h%9>QK}`(cfPxwh8v??NS!k?caXu*Ff>yNnftKnp zIOdcmRu+RtYCypUHXO`@d8`s9Q~{bn04H*%#A3v}2RIF(ihvSMNKt04C#W>c%u5Gp zgv|S3ib5k3OQwkacNKHZ5nGLej&;(t;lmR;2<(rt2>Qu=99rup+b#!r!cZ!6`2BSL>rY<-n z$luRB-qp`JC^8_#)87xK1Dv54eDaeMb0BpmC|!aFDSZ5$K_kjw1)w1mLjF0ieAHpkf3%Vh$Gr zRgmankZFaI5ZF2;G`?#^322#HS!z*9NIs-xjBbK&aY}wMgJW)HdLjd8)G;i#7?f!$ z7{Yv=bBh@qOA?DRgF_hngN+z`6O%LZO7e>{7@{CE%nZ&2xu9|bwEN93guyo~m?5k< zmBBGNzbG##vpAU{EG@Bw!4b6AE)TSqq^y|1Db+uiAtW&`B{i49KiI^;fWbdF0$e_O zBo@P#_<0tCQ(!7&UJk(ng^Fh}a+U^#391N44On+RcsLt8_W&-1F$6&>L8J1JLLR~b ziA6!`WXKFA$O04rkP7HvGe{1~1c|~beo&%A)L>w{aY%u5p%yA25zk^5|6p)w4_XT7 zl3$Eu7)TzmAqi|Y5*H-voR|k{R72KzGq~j!B}2DDc@~3n23Q2LAOV!(p+ydK_Yg!0 zI66?$IHt5qeld6k1QZ4^HpqHdoep*yoCA^pO|yUo5>g?H9zYt=gutqxi$GyX0j4A~ zKMz_>AZtX3g7m_3D%f%a54y|{AplYg+Mxv6RSPu^yu%hG4jOCANoDXX#;_SNa{(G* z&I4EXkg6=T0y2J$7W2^Q9cX<48%TlrA1WD=4|Y~^2}24rL~|kg)WE|F49WSqV3(zV z_oYEwi;$F=51H{ugU2wag;!Znf|TyTYe_*NiO52znFS+Hpd@u@+QyN1k&`KWiyUYP z6H@ZSnZod-E?8=Ug+DaBK;8fc6{si%Em8%C3pBRCNfG8wwCn=gj|Ylq7#kGPZkZL} z4SA3?m>^kH5s(_tz72RM0-UN)ML=pmi;+;(po)Oz2$5RQX~@>bGl1rXp{@cg2SX~` z!0XZweu)QJkIaSYVnB5@s{2q~0_xg>2T;Jlg~AIhNrtxL!E%sp5Qqtq0I76L2JPGi zi7=pYK?=Z50GApeiRqp$prIsiEP<9XfOb4WL_t9eVS$1TtNq1IzkaFMrl+3hD$Zj^UD?nN?1VJj1TnbWy#0AMBdGg%IM&cbp-~Q+umaaN;HUre^1r`I3bL4@R7NnMd1sF0xiRRI_DC#)tX2ob6f~|u;-1B>xk;%h zDXA&YUH~}AKx2;O$O6#n64sUg>4Z2I!~*-ksS=Vkz$54I4bGsL21|qT8Jqzg*n~O) z3U&&TA3;R`5*K8(XEAu4Jt*aXcYuI-piT6-xtS$Uj$=}O5sV$2S_1Qf zV@e84K}rfJ>fxOh$S}N*Dhi04NWX9ihxn(AF&oI~AN=A#B&socz3W zs8OIUFWC3clnqt_Z5qI>g~|ow7eieODxmU83qU~!uU8@Gg@7}aduj=iFx(iJ93-T` z)8vTmG&uc&3`7WllMiU}9w7u)1u+n;AMA8cMuduiV->WZHZw0B8iwwvC6LK~XtaV$ zVCdi!$Z&`e;LR-vBN>8H^FfPFAZ9=#20T|8RGJ47EQZY7fH|O8hOVE5mv*2s5gs{E z4k$vPOmG~4l2i#~BLsLC9=sP1QUr1sXbc#l2*j&|))tPSZA6)%9ju^}N;32Fpk9Mi zrBGSK5Di=w)HH>0K&z{qA?KsO*SLctAE6H#?TDqppm9)eV;Hie9%58H1Ed-3p9U#M zK|`3}vIjh}nOW?Y3d^tY45i=$4T@n5a7G2UkTXiayA>ev;OrXDkO(;l1T=+G$0 zJde$a{@ux}vcBCN=Pq;!yj7?8>Xa2q##sY z2*}N#6C6NnP~iw_#)4IW3GP*J}A<$F@c-WgEA8Iosgc3oE zQb3JCSWtti6p;P#44`FpNTz}sUC6e?Gr;`-b3fee=x#)F49Llz#Sj}IOAo=m4N5Er znFQ)7f(G|NjgFKk&TXLK(h+T8jwSvEi3R2 zSJ1jMhQuP!CT4Kc1=i{SI}fxSDKj@UzqAB2(+yhJ1DO_vv}XeH!Nd9~;GHF)hABuL zC@?{VA-I1L4=zC>~LgX3JK--QX z?0Co?WC#bTQh^p8;35S)>Vb6>4x$0O6sQb@RdokgGEU8&ozR>I!fR6iq0z z7`o2~vgte?zU~cVY-$m>+=48XL>a^Zmk*#GFZf_Aq{W9IZJBxLe)%Pc^oI~b3|BzU zJOD{CIOV5Qf*Dw>0Hr+8WCC=<1t?=9aY0iR5E(2}5<#gsi4~wZ_@c~Qh$2Yf!kY8o zn1HMs1SJ>8ycB3j5B4;uqDd|-f_M}@6bc!_%FNG$Y;{U5ErN~!fezP#j*Aq4*294H zL8CkwTIzuI)58l35C<}12|t7bTvO&31g932WhSSBmurM&g13Of``ED6$go3Cz`MZ9 zLB}&>f|hE86qOd2q^5wj+NKsE#^@NFeS*PF^323M&^~O)3?$5~pwu+bks+X|3rFY@ zQP9L;Q7(ADd14N9G!Wqim@1qSAw`KPskwfPcV@g1Wl^t_36OqCKW?ev0eoARF7I(lh4Cpu}*dPi6OjihKX#v72 zv={_=Au}hn2ssK1GIPKI2~Lh+7LsG2=dXbDC6;6+W#(j-AO%1stR0gNKabC`D7_Rk z%H&s?lY`iQ4PLwps!SL>^Gb}37;FNHGRqQ6QbEN&c+L-OuS;r4VrEXUUA39BxwD(I zfvK*snVF%kiJ7B;uBC;eldhYynVW^7xuvnCv3V^xcY{0w+ufOh@OFGW=opI3Wbp7k zC@X_jV}tCsH8L=X?zm>C!tm?S0X8iLNU0gWqpfDaiehHOiQ3A$yb=A=N5 z7DC$52sRvX7EMx4D#8JophIauTj)Wn@^c|arZHsZ@XIfOmr01=1RWHTna7aFkXM=uUWEag;$-kmEXe?!vcmvcpOKeZ4)QPf z1QBp)4Jq#tWKm7taZs8s;o)&XfrpcGcj5L}v63^{=e zk^~cTKqqE_R;q!!0RCyvPiamL zm<`>84@#t<#0*N<;Nd4wDu*y~q1*U#p_hDsEPnL_duh9;HnhVm}AH#{Ag#ijvzx;BL<-w&%;AJDA3J$ahlpzSbftaBfbnFM7RBD8l9t~1b zbqzuL*FjAv&^Z^NfhhRc6Cw*HXMhwz)=`3YmP0!wU^b*r1lhs}=?sB78U>)d4c;sQ znf(ACVwRbVFcWfG3InL!4Q|{s6s0GDHpdsGCwYc}_OOH2?G{0IdV}NAIX^Esu>@nM zH)w|qL@g+ULNb%Hiy82QfdN_=7@C;q8iMT0hc*vjol@{fDERP0=mA3v;6**qbKjst z0VxO%Aw?@JS5<=J8g$BrC-~e_(B|6I6i|W%B~}m*I;NIiR2iIFkXQsdgc6i*7@%uQ zKuY0;f!gWd^aDh8s!xUxPeHS-xrrs<<=Ux5uoRb+#o(Hk0sSG)YEEiyG3X!|m|2LW-;h=E zkeaWUAvq&6C#9GHZ_$O}Sd(M}%s@{z&^5vnbB0D3QI~9>ixDNs2D%tgl5B{@HbcxP zPBzpv1~;-`o&#;=grx9d=sHN)l1y+mf|NCg>Auoa+l3=@k>z~vh(heMAo1{KAiG8Z%#l#*KEpXQiX30i@PC;-4!4#GLm z!U1e<5!xa|h(RDDL-O-MqZWwz0lf4DUOZq_ zG|dNUQ9)Q>MbP35Dgr5^^xVOxcfpRkbcS>w!DT9_kb-J~3WJMoxE!b)hjaX0eL*P| zygCY09%km}L06@uAl6Xif|urj^(4Z&lf?`!iIv5kd641`bdDQz%?kr4@ zumn203f}DnON*d^wj4;YiC}_MgLd(x7J0fblpqciP6Ku6zzro(k3S@zAu$)U?E};@ zg0w8*6KtSCLeQbV(B8UlDyUFL#C&FYUVc%kb7C>1=m#akBG51fEOtN(?x6EoC8@=C=>i>32d6Q}fGD(K2@Y1zlGI#qs~gOK zEto+p@+mD&MOq*M9y+Q7Cw5Q^2Rf&i4+;aQp`acTNDA7fg`bTG$<}Z#Xkm9^W?nI< zkq16pFEb~V0en&*=(s+}%EnaC_ASWr15lv}I#L!~vVz-xxsWqv!xD=!K{E;9Z~^tq z%uJwLP$5ko(C{ZiGGy8V()NUiGb9%!Ln5kzp%Uu!6!6j?&;Wc1k%d07?d+z(LncEBLncE$ zLmqpP__7fgy<@l|g}_m?4#+gn_}GuzA4@sSK$M*$fH{c~BFI8A=%n z!1fd|lrW?+q%bf95@${cgAYS0LmopqLkU9$eiJ1R zeaoA~P|A?Tkj9Y8P{hC>?*uxel%aq@fgyzNhA1Nmc)<>0yd4ok~o(n zGZZl-qlO?->hcGtcu3eF=N1yvJyPnzZ6Z-AKN#UF{3el*_KEUu5HxIwO0h)w7iJ>< zv=2&oX|VExJDCAgO67sd5@UaGo`94r`V0seP-+F0WFQ)pYKy?-Q93Bq8zVvwBnwgn ziCffE42oS)83wxjhCvlud6vhJ%8(AueVO3Y%U}&F5kR>SIro9`7AQqlFhEjs2}3@( zR7A?r>ZuGB;JbG~`KcI97UVK$p0#y``yP8Ko5PUG0LqsN;PMXS0|jty2bByAhS>ap zR|hZ1ts!7DOBfhDeHk*rrh|Nx&H%ClR37DmOAk;v1QQ3j0c2MJxa0@jBb3Mhii2cu zNms3-eTl> zjkg#aYM@-6%D^BFiVKiDNC(8#pjwMT-3h6T1;rF79zgyF#a1yxF1S3+VPKF4m45jQ z>F_ep1Dv{27(gLe#K6D_N{^s;WROLzdq81_6dU~6450Pz?gf7szEE zq|K1VkOPf}A_fLgjkR#Zu?15>-BigX|*4Zjfmt zl#%|#nv1C0@s?{uyAxp^Q6+CAvF>yNmtdfjg0KOvilcpum7qnQQs5}OBaQhULvrE9YoiU~pX9uW62HleeDmOr(0WyIkd!mW62hqBNx{@2z`T_Ogau^sqk#)jKE=c+T<+l=W zD-cvJf${_>jh2E-c8JSBWhayxR|ZgTs)(VIfq_|{ zfx#Bm_AWpf(Seu(s_j8-Q&1fQs%Js9AgGND(yaixqn%xy0ptQkaYV1&jUkZ%)ba<_ zQ4Ge&JW$+&+zLx0kdY#co)tI3ECzi98+%I`6zWKEqz^J1x%`BrFNkkIH4LQ01?d8( ze|?bqAn^nWL6F}NEfi49L3p6PW)Wx{DjJdokoyjL46xjX+(OrdmYc-8h0&If+d-)e zr%&RsxeSprvAYd9m*5X6#)j>rS%4gIkYFuG8cqW>5J8C*RE&TU7^sp5C8%l!1BO}# zb!a0J)Ex&6j7!L|&Bs1ShDc07`BQoO$5!?^Ff`UPvnr zRJSNFFfc2?TW27h{Q;O)zh&yd0p!jQ?33myN!EaO1tfZCX# zuvTF30=EDa7!09pNJ9oo26IsBo6`?mW~ai(=8?-8240XmV3~zM9ae6G$}vzJBl{MV zm!W-gZcyfPWJm#(Ue1s(##N6J)k5by2DMYpCG(n@% zpgJ1Vh5^-Npb%DI0QFzpzy%X52Qo;b_AWsBKrswzJ2IG}_M||$5mb9-Gl1L=s)-)pGDu04P{swGF6Yna9AW z3h8#CW^9b6hd*ke3d+bJUx11=P~?J&1P~k4#RRzmzQE@@fS%FhM~A@)jgTGe|>dP+bA)3nK?8gLpVNmO*1Eppl(4hEfJl50ya_>u8X@ z6L`D<6orVRGUHSM3{a^ z1QdYV)*zpNTDYL`dr)Z%3NKJe4GJ>`eK)Y%K@pR|puwOC9yQ2;k3WHWM4(Y?kbl7H z~td7bv7)E&;_c$W};FaAN?e1C<*PJ_D~JgDZFztpwEO)`ye} zpxHc-FF|=9G-3csYM|s*2A)-gjku;TFhJGA;u%{x0`UQKOxF}NXMj9s2XTc0gD-eS zHUnH+DS+LG@C$>!Cpcaqa~wI)Q96(tk?R~#c!27vw-G( zK+RWBFAo%Bpp*s6JD|cBRChq)8PvN2_2C(eQHwoLt^jQjK%UPBxdoKM;CjqKJ_dyt zDAl5uRmighpwNT3Ck52sjYkhZ59mA$XhboOAq1R1QyD;U3Q9+iA{I2F3z?+`m6#x( zgK9xg6#xn|l=LqTau+DQf%>bt;J5*)hqyhJfk7HJx(A8@P|gMAR8U{Fl7Yb(Qw$VZ zu$mTBl7Q^XgN}!SM;e%87#Q49D;H4b1{AKK5)PEEQsKEDdp{c99%YSTh+$yR1*H>E zxd191LFIG-cr+c<1_tE_P-_*^!v>G0TBEB5`3Y1yg4BR)hScJqlmK!U%DkMSAG9S5 z@)f9z2DKGIBle)w4hmrgLy$i}m?+<*vUhJ1uCKyd_0b)Y#9P`U=yF$mj{ z-3AJINUI*zC7|>M3O$f-LGA^GEJ!Vqed);NK_d=ENbXWc&HEt#gX&aB$eS^kGMF+LGng_k zScZY;M?vixm=9rTCm&jegZLo#fpRR84gR3A8I%%1VG0TwgGy;ojSkX-XmBz_Qeqxven&Ey6E+{iU=EpShNTEth=Af16!R6}z8`4j z0dEP}P|&}%VJ7=!Ap6b1%MP`ZJc1Z$Ur@*ikUs*(XT8VV8xjii8l0m_{alNszm zIx)*FPzj5=S_)ETqQ;m41A{dvCxX%t$PSpA6b8_!I4s6NWe%wJQ(yp%BZ6A>kRAe~ zBy2_wlG8z{4>FU*;Evor0F~d6RD|A70F{NH7B{Gb1K9{lZw}zzpcO*|LoEYC!%UF# zKwbqUcUTsHcn;L0NCY>kK|ulud`K}3ayTe(i@=kxpzI4Na6t_LPy+$A8Ub}NK_1eB zj?$qg6;Pn3gBS3Df*n+>gLn+i$k7Y(2xt%n_;; z0kH>H_(GBa$Q7XClA$yV-2VmfA>of%VSxODoP8l71*)nbRR}1=L9q|YLa=bfme@7G ziKdo8lYyaOdI) #r~eGJx9Dpf(D~09czHSA7r3VW2cv1zvTESz}Y;0fv0)1_va7 zKv99H&lDJt0>T*-t)OxaF&7V+fd?fnP@gUxJh}_Yndl`GNLLAi9s@%|FD)Dmigj4S z4$_eaHK0K0AP=0fl73<{}Y22djo)QCV&Cy*FUWzYvtLV|n_ic3%&fSQ<~ zcm~;)$Dj*e-pCk8et3hH27;<(Q0fD@3tEMmgSw{3SsPZ_LTWaU|3L8s8bAQCLA4=x z*wq-;009+qiO^{PP=f?iCWB%Si(RSsTo36ug2D-RMGk8`A=`-&n<0&wJ#tJ|-fo6(8 zk*m)T%;3fl0Uk94Wf)L42PKqZcw-2ZO+lFeRPTc#2)642)O-Q8Z$YMjq8^mRko!oW zHZ7tr$*7FI07M?IWDo|K4@v-)46ua7V2a!vL=87Yq6Q^(NJ|6~9t_f;5lT=s0xC2? zA%bQb_r}W2cifbTXzUtPNTT`z*?ug&t#U^O$l4l6p#-rHG+quGPX^h6nQ<`v zj_S8^@c2DwqzTkZLLNa)2JiU+Wp##9dfE#sU>J(&X)CCSlMG(7iimeme1TFttUyC< zQbA)^AJj8MpJf51Tu@OC={JLVb)eJ-swNoRK_kZ?5m4a>N}sT*ACziAdXU%cfQmPe zPEb69`uCs$8)Ql<14AgbSwm2+DgduHLd*n#VjJCku$e%R*`RS{Q0EL(NHUm%e1n<> zP^$o#YeAs`s^%aK6$X3c+yIL|eehg2#17ExCrlhm)#!=MHz1w);Q1@ico1sY2k9k) zDl|}-fEpm6@+y^q(H>S-z~T&~22|;x`U(`E#Tb{rAm&0kp`cO=R33rSc@YCcDyZZ_ZX6-2MQ_Yt zD`!A4jz01LO7o!fX21X)eE`p{AlrgoD}i=YfV$<7+<>V67@U#EKhWKStwDq79)?iR z`U}upB5203n4uiJzYdfS6Tu_?pmk!15hFyS5V;Els`Egp5L8!z=4W#m7{Dt8K_v=m zrwKLJz)}NdSDQf*J>)_20iaP{nEM!PA!|@TljNYf4rUgSYd|eQ>--_}BapTPCTHl2kWW$5J;-EG&O**nkX!-Mo5H{#3n}Yh!%o!Di|2JLE#I{ z$-b}_DJVyP)`-G}0zvf>C>}vE14_jpdDspFP^$x*JOeMXTN(5rWe<880IJS0hG5Z85k5H=@O3$@JKPD!~n$)WE~DD zG(l+|)b0b-h9KJ@sR21fGvva?)zHHPd(8_gkr1YVav#LCpu7tT7nt9%lrx2(6+OtK zccA!3j8lPH^&qn#^L&t22*k|@TR^k#gom#nx-=LVm^I;{h+d|F(ix}|sK>yNirk(+ z4+%)>0i}3Q+Z0ll)Pnaaf_9vMOab*iKr=0%@CKC~kT?Y88RYVq!4Z`Ek!v1My$f4k ziMrbq;s(&j9wZk)VuQgId4H+`gEn;kG$>7javmuBK zcR&WzAY~D9-UYQ2L7@lAk>C|G^0>Rvpc!-qW@`opZUqJ#23-a_&?*Ua)U`gK)CLL@ zkefi=Zb+S<&A`B_&!Er1zz^{$tR!QwgycKiYv;=uK;=Ftq)}bUU=5ln299Y8Y7m)Z`?Z zEpVH$`cHmirKLFo$M&k2FiDdKo$L%uj6%FZyc`V75Sm$mfsu)ggJnS*BLfQ)BLf4A zI0FL%3j>H?1QBc?!U#lw1X+UI7#LVY7#J9s*Yy}-z6c`!#*c6x;`Gj0q zm_TZoK?Ey^U}s=pU{zpb6yjx8U|<5NWMWoe-~utY*c6z!xCA}f6_^=iSvfdBVyx^6 z%p4#NvjPK1fP;fsfq@w$!@c!NtG|vJqq(8v`>dD=RBAn=CUkn=Bi%1_KAkXR@p; zAOACeEcpMQnN60Hm4S(qla*P4fscuek6D9(4`ebQ7ZJL!~!nj z02Ofn>t$l(;{%(J0*A+*@Qxw*@QAU6qp(L1S16_xfEC#`M9`1Ocn(O!AOu5f|1N@ zf{`p541$r6WG2fB3PvGbP;_!a6Pzq7KLa~B>B+JR`3T0!@Ch(*pzyg^7#R8Z*ccdP zS!F??$jYI>3}SL{a4E2YlZGrS2de^utWYA00)s3ohXRw3B1i$N23SmkL6()JTb_Y| zg##4N0t^fc9H4Z{E7ZursQ^y)jo`G##l@|_D&z}tolu|*3!6|Q2Me1}!yRTeAswiW zh8IvB4KG0HN)aUgf`v`6VGS3^q=r304M+I+K&A*m*bsvncCdj`e8UcKm^U2ZgK*D4 zs2l7Ij3DK_91Khlnq7f~k%Nze52Tz=sNo2R7HT-c#KOSH$Op3X42ZbF!oUQ|ni>oY zU=t32vN4lT1Bhl-U}TbIWn}=7poAgI$^o(L1hWEz3>(P8Bj8w-VN+ma5^6ZYs=y%B zZ~|h{2|hMZa5fxaV_;&GW#t3MUc(8n%_mqjKnht>Kw&urMDTzJ1qRSIe?|jFLq;P; zV@4B3Q${mJbH;SW3Pwjp7e-e`PeyM>A4XqBKgM9jFdj&k71Xd-VBkaMC@^p|Oq&5J zZ5Y@Ypn<@^%ms=Q4hCkSR1kxUft5oj6&&-N46Gb{P!@M?m3u07QUU7uXaSK{3e=revW?kAQVFg7P@XI8cl# zf^w=N3qu1ayVo-?uq!Ze2sJ$6VBrJ>iVTR50}=J$LXU}&g9&7YV8aJc>S6)e_l1QG zRLK6S1H~i*BLgTgePCe_02M}zj6#hptO`s_OiZi_3?N+!j7;D(`Gc8FNP|@aEXLr# zz`!C0GDH|;l^}=^0uc-#F*c!wKO71y;PMode%Lrz7#KM?I2BkJg&KZvaDdBfSvHs- z|9~>CEC&lW$N)B>h9@95J^;Cv2Sf-!Qp*!ipf!RxAm1{x3Hg9r2`<0{V?ibe#xk=B z#)7hbEXcz`jUu43EdeAYlmOPO0ufgMd8|iKGn-HXNL&XLg9)HS-KYWzP>>^-g?#zIg(V{ssGwyOYIFf*MG(cr!otYF zz{p^nKc-gK}H#{B!fduu+fBtF^z$Ng$YD3g9uI#!3QGvL4*K^U`l6T zU{L@OiXeh91C)k9^#+?@qXmlt$fyPo0jhji7&t)bLxF*TMHeI{0V4E3gcyhj@MdOV z3Gim;U&6<0bmsY%nA&k3X~00v$HX= zv4M&%P&L9J*q8z_JO!jW1*|#+RHZdWuz_+ps{*4CFQ{-6YK&mxVqgJLAaRf;5F1pN zgHksWqW}k}%+3X;8Bp6mu(1MUWDP`R57F>xs{GcgG^RtPn=a4Ily2{pP1HcsIL)mV*3gc>0=Nh7o@S^%kl z8x5F1uHh4GGyu^;ja&G@^-<#%kPtU0uS1yN_7*!Rj5$FBH=6<@hft#nMDYSpLy!lQ z;~K$CE>K~`A=J14V!#3+UI8vHUYI;8e)(tze0s|+r z0s}X@0t*)h7pO_a2=Wi70u#t8p+*-DQ1i1C6x1LFFBdDDtWYDUHBt!*L{M4WxC6vm z!lnVrh2X+UMyRm_9OfVfxPBFEoB|5?8K5AQkpYDOAINM_+XUo)i2Jq(HM&4pE>MOpvb2`sf*t&GkLx8|6jM4&OOsJPwmY`k?RMxh|lvrX)PAE{hh8? z`rR7INvU?cbB>yPpXi+*Va=q+RkdP?!58+)`m-|FKKx0!CRcHF9pkG0CS%ET$t%8# zj&kYB{IajwUDCcetjeDyY*kvis871*Ms{{)Aqfs4UJxzAA;b%cjW3*_C~Y_^*l>|a zmV=p{k%NVuiGzcUorRg1nVEx~4MZ_BGs!ZuGB9y)aLBPs$jUNv$b#4$U?9s1YJP*6 z92_F-f?z(B3zA{w;9+286lyrj0m2;Y>@1-6IV%r47eW!pB|kvTCK*3=Cy@CFDL6}3 zmIKs-U;_!TfdK~_2bd=daw7)^2S^16veQ8ICRharhcG)oNFxNx3MzmYlI$WN3fwJ0 z_y;7!$`0x{u(Pvru(EP+@Ue5tGIMY+gT$CQIH1}%IGDgXLF%EHnVk{b2oY>#Wnl;P zCfJ!dIl(3KA5fTwFbO$;=m;hu2R3#lArB!F5ETHST!d`I*m-67m^k=^T!ma^`S?Ht zhb$jBJMjrNiZZh^f=UKvP-lma0~C@>vV0t%_8|wTyCIay%qhUg#33ukAjiPW#mLOT zz$nxxE7+*W0cs$f6>5}alI7!JXJeLS777J5!JF_e& zhb${IJ0m9xJEJTp{5V)y*%@Vp5>R z(jTX+3_ClMP{RaSRt|O+PEJrygN047iG`aT)EfagOqP|Kfk~**7J^vW8HF0ofXN#w zj12N150_-5DmWG=XJ&$LQv;o2u24_}I!Uyol7T^tkwFlo2z(n2A|Svf9AQ;p;$sG7 z89q=yjzO@|m6d@}sF079fkCJ-kX?ZpRIzi2u=Dcq@i7Tyf(qJ3aF>RIkC}l1)Qu8q zj0E)nWm);y7?}C^`1oYl`I-1Y-3+0|NFiQ6Synz-p@t(ILcE|b0oP!OeC!M?AfqHm`&PH5nj0}n(W1;8VLe#**5usR}kwFPb8N{Vn><0&jj0`h7BgDHhGBV&{ zk%qGz9N=yPA1gZ(pI{^>JF_e#h?E%_WI-l_q7!shDu$tq3=EtKY@lHT4sg*2sszD> zIv?1xC)n6oxR^LNSlO9`Qo-dT7aKbZDCM!RGYUqsfzmaoZ_N%h0i+PrlVf1!laZ0( zVdnsu2TFk8JS)q}1sbkk6iVe2Wap4&6>2yE>Jf2q2sLcsV`gXM0+k63CpcKynfW+4 zIN8}j7D4j~NRWvMq{3oYJQ!5M}Lh(lHeR7uLnfXovC5fWT5r?GN~vkRk|1u>C> z9aJoYfQvnFc?aeP2$_Is7a(B2sOSDYJ9`X&LU(f)aU|kpY(u&ztIJh zkqe=%4?f5!1)pG}E4c6~6l`=Aa%E>{0p$%>76t}cW>BRJsjm1yNkJA;UV`!=6C(#R zn*tLDNQj+@Lnu{_kwFraGN4xrL9VGrBuNcM24y7a;F6;JymaWTO_}+52!*iR06sGr zat)JHVsR=spTUbrSTPDZWfpenPks@q8hBm-oim&WJ*64bC~ZatHIT!=c@KI3EhNKW zs#RoUkO8TM9JdQ`9IB*RVI{msKn@Ko1{yFjXoI{6zUK@Y9H4`KVV=b>SeKDO1Ec|}7NX82Gd;5; zF$ZjZX;CV|8TyP2S|HWPp$$KA9IPC4ArwMAxG)an0GIWp;GRk)n5;#rGV+kj2UVKf z;NeG34t6$95a56@I6<9lNM>RHSIL60{Op`UjRoLBg#%QN@vyUk+R;oxnSzZ0JnSqW zj!~ilHg)z6Vj1o1)0vx&dvp6gUpZt zwUqflWf!kd!xF(p13q?kAzm&nAzm(!`*=CnS-3zQC@yw(RwgbkPEJ;KW-d-nK6W;U zJQv8aJK!FusRp|+7Z($#8wu)`aS1gp080urE)cQ=b%0bsO*9Y&2mT!{HFkL}c6M%V zZZ1w)RwgcPE^bg7;RJ^Q2Pc;-E2wKF%L?u>@(L*mHui!7zEr4T0yGpXVWknMQUu=; zgHbCoFz~Rmfn3nI05qV^#?H(k#LESuI6z5(iA&Ivl>szR&Bo3Q8vS8oU}ogw19glU z`2-uM3O3HCS&c(sT397I_jT%-~ zP&{#Qv9o|%Z?dc$ptdE4EGW47KrKfOW{6Q7Fr&EGS-H4mWk8UXol&sSK%AY63)F)J zg<%0GHbL=WDWu8@ni^qX1@*-kxEUGP4D>8a^-LKUj2IboL1(6eZ;DeeGB7aIH8L53<{v(FfeD77!85Z5Eu=C(GVC7fzc2c4S^950*s*9Uv@2GB`zplL!R32siOLj!1;4pg>*#e{)@A&eoIA)Xa>!5^%0FU$LXp!xhz1_p*BjI0bG8Z_%^50(YZL^6Pu9zb~z$_2av z0CZAB5d&V4?s(Lpm)@O)|91VF=-E2 zjR6A;nlL1R!hj)!L5_iu0d+N0F#`jGBlz5K(8?{)3Myv?W#~#h;BJXHs zU~pg%fSUE*aL`RUMhtr3 z5MW@iVBkiw4|Q!O$Q}a*Jq8N~QwBXSHeoPj04?NVV2EIlVPFK`0R&lv2wLfwgV=k; zfXkoQ-L1y}x-S9Lc5h(NV_*c|(gRv?o&ydc&@L6wo+Z#Ge^3~KVhmMGfx!qIyM_$9 zP?k9Z=tQeb@P<+a25*KU@EL2Mb1;g)C(?Q`n^3OYv~61K1$0^)&UlY#6owqW34U}OjYpKS#? zR|2#v1v!l>Lk}B(q$$uD9-y6V3=AfqMMG%%&{GU@dI5!#12}y-g6|0dg(2vqtx5(3 z27LPT7!c_UWX32S4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@RKnsBjObno9^#bN-;-lQr p5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S``30szB(M`i#3 literal 0 HcmV?d00001 diff --git a/CUETools.Processor/Processor.cs b/CUETools.Processor/Processor.cs index 01d7e6a..e5b8fbc 100644 --- a/CUETools.Processor/Processor.cs +++ b/CUETools.Processor/Processor.cs @@ -42,6 +42,7 @@ using Freedb; using UnRarDotNet; using CUETools.Codecs.FLAC; #endif +using ICSharpCode.SharpZipLib.Zip; namespace CUETools.Processor { @@ -487,6 +488,7 @@ namespace CUETools.Processor private const int _arOffsetRange = 5 * 588 - 1; private HDCDDotNet.HDCDDotNet hdcdDecoder; private bool _outputLossyWAV = false; + private OutputAudioFormat _outputFormat = OutputAudioFormat.WAV; private CUEConfig _config; private string _cddbDiscIdTag; private bool _isCD; @@ -574,7 +576,7 @@ namespace CUETools.Processor //Catalog = release.GetEvents().Count > 0 ? release.GetEvents()[0].Barcode : ""; for (int i = 1; i <= _toc.AudioTracks; i++) { - MusicBrainz.Track track = release.GetTracks()[(int)_toc[i].Number - 1]; + MusicBrainz.Track track = release.GetTracks()[(int)_toc[i].Number - 1]; // !!!!!! - _toc.FirstAudio Tracks[i - 1].Title = track.GetTitle(); Tracks[i - 1].Artist = track.GetArtist(); } @@ -693,8 +695,10 @@ namespace CUETools.Processor TrackInfo trackInfo = null; int timeRelativeToFileStart, absoluteFileStartTime = 0; int fileTimeLengthSamples = 0, fileTimeLengthFrames = 0, i; + bool fileIsBinary = false; int trackNumber = 0; - bool seenFirstFileIndex = false, seenDataTrack = false; + bool isAudioTrack = true; + bool seenFirstFileIndex = false; List indexes = new List(); IndexInfo indexInfo; NameValueCollection _trackTags = null; @@ -727,23 +731,48 @@ namespace CUETools.Processor } } } + else if (Path.GetExtension(pathIn).ToLower() == ".zip" || Path.GetExtension(pathIn).ToLower() == ".rar") + { + _archiveContents = new List(); + _isArchive = true; + _archivePath = pathIn; + + if (Path.GetExtension(pathIn).ToLower() == ".rar") + { #if !MONO - else if (Path.GetExtension(pathIn).ToLower() == ".rar") - { - Unrar _unrar = new Unrar(); - _unrar.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); + using (Unrar _unrar = new Unrar()) + { + _unrar.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); + _unrar.Open(pathIn, Unrar.OpenMode.List); + while (_unrar.ReadHeader()) + { + if (!_unrar.CurrentFile.IsDirectory) + _archiveContents.Add(_unrar.CurrentFile.FileName); + _unrar.Skip(); + } + _unrar.Close(); + } +#else + throw new Exception("rar archives not supported on MONO."); +#endif + } + if (Path.GetExtension(pathIn).ToLower() == ".zip") + { + using (ZipFile _unzip = new ZipFile(pathIn)) + { + foreach (ZipEntry e in _unzip) + { + if (e.IsFile) + _archiveContents.Add(e.Name); + } + _unzip.Close(); + } + } + string cueName = null, cueText = null, logName = null; List cueNames = new List(); List logNames = new List(); - _unrar.Open(pathIn, Unrar.OpenMode.List); - _archiveContents = new List(); - while (_unrar.ReadHeader()) - { - if (!_unrar.CurrentFile.IsDirectory) - _archiveContents.Add(_unrar.CurrentFile.FileName); - _unrar.Skip(); - } - _unrar.Close(); + foreach (string s in _archiveContents) { if (Path.GetExtension(s).ToLower() == ".cue") @@ -751,7 +780,6 @@ namespace CUETools.Processor if (Path.GetExtension(s).ToLower() == ".log") logNames.Add(s); } - if (cueNames.Count == 0) throw new Exception("Input archive doesn't contain a cue sheet."); if (cueNames.Count == 1) @@ -780,12 +808,11 @@ namespace CUETools.Processor if (cueName != null) { - RarStream rarStream = new RarStream(pathIn, cueName); - rarStream.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); - StreamReader cueReader = new StreamReader(rarStream, CUESheet.Encoding); + Stream archiveStream = OpenArchive(cueName, false); + StreamReader cueReader = new StreamReader(archiveStream, CUESheet.Encoding); cueText = cueReader.ReadToEnd(); cueReader.Close(); - rarStream.Close(); + archiveStream.Close(); if (cueText == "") throw new Exception("Empty cue sheet."); } @@ -793,21 +820,17 @@ namespace CUETools.Processor throw new Exception("Input archive doesn't contain a cue sheet."); if (logName != null) { - RarStream rarStream = new RarStream(pathIn, logName); - rarStream.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); - StreamReader logReader = new StreamReader(rarStream, CUESheet.Encoding); + Stream archiveStream = OpenArchive(logName, false); + StreamReader logReader = new StreamReader(archiveStream, CUESheet.Encoding); _eacLog = logReader.ReadToEnd(); logReader.Close(); - rarStream.Close(); + archiveStream.Close(); } _archiveCUEpath = Path.GetDirectoryName(cueName); if (_config.autoCorrectFilenames) cueText = CorrectAudioFilenames(_archiveCUEpath, cueText, false, _archiveContents); sr = new StringReader(cueText); - _isArchive = true; - _archivePath = pathIn; } -#endif else if (Path.GetExtension(pathIn).ToLower() == ".cue") { if (_config.autoCorrectFilenames) @@ -866,13 +889,11 @@ namespace CUETools.Processor if (command == "FILE") { fileType = line.Params[2].ToUpper(); - if ((fileType == "BINARY") || (fileType == "MOTOROLA")) { - seenDataTrack = true; - } - else if (seenDataTrack) { - throw new Exception("Audio tracks cannot appear after data tracks."); - } - else { + if ((fileType == "BINARY") || (fileType == "MOTOROLA")) + fileIsBinary = true; + else + { + fileIsBinary = false; if (!_hasEmbeddedCUESheet) { if (_isArchive) @@ -903,59 +924,66 @@ namespace CUETools.Processor seenFirstFileIndex = false; } } - else if (command == "TRACK") { - if (line.Params[2].ToUpper() != "AUDIO") { - seenDataTrack = true; - } - else if (seenDataTrack) { - throw new Exception("Audio tracks cannot appear after data tracks."); - } - else { - trackNumber = int.Parse(line.Params[1]); - if (trackNumber != _tracks.Count + 1) { - throw new Exception("Invalid track number."); - } + else if (command == "TRACK") + { + isAudioTrack = line.Params[2].ToUpper() == "AUDIO"; + trackNumber = int.Parse(line.Params[1]); + if (trackNumber != _toc.TrackCount + 1) + throw new Exception("Invalid track number."); + _toc.AddTrack(new CDTrack((uint)trackNumber, 0, 0, isAudioTrack, false)); + if (isAudioTrack) + { trackInfo = new TrackInfo(); _tracks.Add(trackInfo); - _toc.AddTrack(new CDTrack((uint)trackNumber, 0, 0, true, false)); } } - else if (seenDataTrack) { - // Ignore lines belonging to data tracks - } - else if (command == "INDEX") { + else if (command == "INDEX") + { timeRelativeToFileStart = CDImageLayout.TimeFromString(line.Params[2]); if (!seenFirstFileIndex) { if (timeRelativeToFileStart != 0) - { throw new Exception("First index must start at file beginning."); - } - if (trackNumber > 0 && _trackTags != null && _trackTags.Count != 0) - _tracks[trackNumber-1]._trackTags = _trackTags; seenFirstFileIndex = true; - sourceInfo.Path = pathAudio; - sourceInfo.Offset = 0; - sourceInfo.Length = (uint)fileTimeLengthSamples; - _sources.Add(sourceInfo); - if ((fileTimeLengthSamples % 588) != 0) + if (isAudioTrack) { - sourceInfo.Path = null; + if (_tracks.Count > 0 && _trackTags != null && _trackTags.Count != 0) + _tracks[_tracks.Count - 1]._trackTags = _trackTags; + sourceInfo.Path = pathAudio; sourceInfo.Offset = 0; - sourceInfo.Length = (uint)((fileTimeLengthFrames * 588) - fileTimeLengthSamples); + sourceInfo.Length = (uint)fileTimeLengthSamples; _sources.Add(sourceInfo); - _paddedToFrame = true; + if ((fileTimeLengthSamples % 588) != 0) + { + sourceInfo.Path = null; + sourceInfo.Offset = 0; + sourceInfo.Length = (uint)((fileTimeLengthFrames * 588) - fileTimeLengthSamples); + _sources.Add(sourceInfo); + _paddedToFrame = true; + } } } + else if (fileIsBinary) + { + fileTimeLengthFrames = timeRelativeToFileStart + 150; + sourceInfo.Path = null; + sourceInfo.Offset = 0; + sourceInfo.Length = 150 * 588; + _sources.Add(sourceInfo); + } indexInfo.Track = trackNumber; indexInfo.Index = Int32.Parse(line.Params[1]); indexInfo.Time = absoluteFileStartTime + timeRelativeToFileStart; indexes.Add(indexInfo); } - else if (command == "PREGAP") { - if (seenFirstFileIndex) { + else if (!isAudioTrack) + { + // Ignore lines belonging to data tracks + } + else if (command == "PREGAP") + { + if (seenFirstFileIndex) throw new Exception("Pregap must occur at the beginning of a file."); - } int pregapLength = CDImageLayout.TimeFromString(line.Params[1]); indexInfo.Track = trackNumber; indexInfo.Index = 0; @@ -1009,6 +1037,24 @@ namespace CUETools.Processor } else { + if (line.Params.Count > 2 && !line.IsQuoted[1] && + (line.Params[0].ToUpper() == "TITLE" || line.Params[0].ToUpper() == "ARTIST" || + (line.Params[0].ToUpper() == "REM" && line.Params[1].ToUpper() == "GENRE" && line.Params.Count > 3 && !line.IsQuoted[2]))) + { + CUELine modline = new CUELine(); + int nParams = line.Params[0].ToUpper() == "REM" ? 2 : 1; + for (int iParam = 0; iParam < nParams; iParam++) + { + modline.Params.Add(line.Params[iParam]); + modline.IsQuoted.Add(false); + } + string s = line.Params[nParams]; + for (int iParam = nParams + 1; iParam < line.Params.Count; iParam++) + s += " " + line.Params[iParam]; + modline.Params.Add(s); + modline.IsQuoted.Add(true); + line = modline; + } _attributes.Add(line); } } @@ -1017,8 +1063,16 @@ namespace CUETools.Processor sr.Close(); } - if (trackNumber == 0) { + if (_tracks.Count == 0) throw new Exception("File must contain at least one audio track."); + + // Add dummy index 01 for data track + if (!_toc[_toc.TrackCount].IsAudio && indexes[indexes.Count - 1].Index == 0) + { + indexInfo.Track = trackNumber; + indexInfo.Index = 1; + indexInfo.Time = absoluteFileStartTime + fileTimeLengthFrames; + indexes.Add(indexInfo); } // Add dummy track for calculation purposes @@ -1041,10 +1095,10 @@ namespace CUETools.Processor } // Calculate the length of each track - for (int iTrack = 1; iTrack <= TrackCount; iTrack++) + for (int iTrack = 1; iTrack <= _toc.TrackCount; iTrack++) { _toc[iTrack].Start = _toc[iTrack][1].Start; - _toc[iTrack].Length = (iTrack == TrackCount ? (uint)indexes[indexes.Count - 1].Time - _toc[iTrack].Start : _toc[iTrack + 1][1].Start - _toc[iTrack].Start); + _toc[iTrack].Length = (iTrack == _toc.TrackCount ? (uint)indexes[indexes.Count - 1].Time - _toc[iTrack].Start : _toc[iTrack + 1][1].Start - _toc[iTrack].Start); } // Store the audio filenames, generating generic names if necessary @@ -1100,53 +1154,124 @@ namespace CUETools.Processor if (_accurateRipId == null) _accurateRipId = GetCommonTag("ACCURATERIPID"); - if (_accurateRipId == null && _dataTrackLength == null && _eacLog != null) + if (_accurateRipId == null) { - sr = new StringReader(_eacLog); - bool isEACLog = false; - CDImageLayout tocFromLog = new CDImageLayout(); - while ((lineStr = sr.ReadLine()) != null) + if (_dataTrackLength != null) { - if (isEACLog) - { - string[] n = lineStr.Split('|'); - uint trNo, trStart, trEnd; - if (n.Length == 5 && uint.TryParse(n[0], out trNo) && uint.TryParse(n[3], out trStart) && uint.TryParse(n[4], out trEnd)) - tocFromLog.AddTrack(new CDTrack(trNo, trStart, trEnd + 1 - trStart, - tocFromLog.TrackCount < _toc.TrackCount || trStart != tocFromLog[tocFromLog.TrackCount].End + 1U + 152U * 75U, false)); - } else - if (lineStr.StartsWith("TOC of the extracted CD") - || lineStr.StartsWith("Exact Audio Copy") - || lineStr.StartsWith("CUERipper")) - isEACLog = true; + // TODO: check if we have a data track of unknown length already, and just change it's length! + CDImageLayout toc2 = new CDImageLayout(_toc); + toc2.AddTrack(new CDTrack((uint)_toc.TrackCount, _toc.Length + 152U * 75U, _dataTrackLength.Value, false, false)); + _accurateRipId = AccurateRipVerify.CalculateAccurateRipId(toc2); } - if (tocFromLog.TrackCount == _toc.TrackCount + 1 && !tocFromLog[tocFromLog.TrackCount].IsAudio) - _accurateRipId = AccurateRipVerify.CalculateAccurateRipId(tocFromLog); - } - - if (_accurateRipId == null && _dataTrackLength != null) - { - CDImageLayout toc2 = new CDImageLayout(_toc); - toc2.AddTrack(new CDTrack((uint)_toc.TrackCount, _toc.Length + 152U * 75U, _dataTrackLength.Value, false, false)); - _accurateRipId = AccurateRipVerify.CalculateAccurateRipId(toc2); - } - - if (_dataTrackLength == null && _cddbDiscIdTag != null) - { - uint cddbDiscIdNum; - if (uint.TryParse(_cddbDiscIdTag, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out cddbDiscIdNum) && (cddbDiscIdNum & 0xff) == TrackCount + 1) + else { - uint lengthFromTag = ((cddbDiscIdNum >> 8) & 0xffff); - _minDataTrackLength = ((lengthFromTag + _toc[1].Start / 75) - 152) * 75 - _toc.Length; + bool dtlFound = false; + if (_eacLog != null) + { + sr = new StringReader(_eacLog); + bool isEACLog = false; + CDImageLayout tocFromLog = new CDImageLayout(); + while ((lineStr = sr.ReadLine()) != null) + { + if (isEACLog) + { + string[] n = lineStr.Split('|'); + uint trNo, trStart, trEnd; + if (n.Length == 5 && uint.TryParse(n[0], out trNo) && uint.TryParse(n[3], out trStart) && uint.TryParse(n[4], out trEnd) && trNo == tocFromLog.TrackCount + 1) + { + bool isAudio = true; + if (tocFromLog.TrackCount >= _toc.TrackCount && + trStart == tocFromLog[tocFromLog.TrackCount].End + 1U + 152U * 75U + ) + isAudio = false; + if (tocFromLog.TrackCount < _toc.TrackCount && + !_toc[tocFromLog.TrackCount + 1].IsAudio + ) + isAudio = false; + tocFromLog.AddTrack(new CDTrack(trNo, trStart, trEnd + 1 - trStart, isAudio, false)); + } + } + else + if (lineStr.StartsWith("TOC of the extracted CD") + || lineStr.StartsWith("Exact Audio Copy") + || lineStr.StartsWith("CUERipper")) + isEACLog = true; + } + if (tocFromLog.TrackCount == _toc.TrackCount + 1 && !tocFromLog[tocFromLog.TrackCount].IsAudio) + { + //_accurateRipId = AccurateRipVerify.CalculateAccurateRipId(tocFromLog); + _toc.AddTrack(new CDTrack((uint)tocFromLog.TrackCount, tocFromLog[tocFromLog.TrackCount].Start, tocFromLog[tocFromLog.TrackCount].Length, false, false)); + dtlFound = true; + } + else if (tocFromLog.TrackCount == _toc.TrackCount) + { + if (!tocFromLog[1].IsAudio) + { + for (i = 2; i <= _toc.TrackCount; i++) + { + _toc[i].Start += tocFromLog[1].Length - _toc[1].Length; + for (int j = 0; j <= _toc[i].LastIndex; j++) + _toc[i][j].Start += tocFromLog[1].Length - _toc[1].Length; + } + _toc[1].Length = tocFromLog[1].Length; + dtlFound = true; + } + else if (!tocFromLog[tocFromLog.TrackCount].IsAudio) + { + _toc[_toc.TrackCount].Start = tocFromLog[_toc.TrackCount].Start; + _toc[_toc.TrackCount].Length = tocFromLog[_toc.TrackCount].Length; + _toc[_toc.TrackCount][0].Start = tocFromLog[_toc.TrackCount].Start; + _toc[_toc.TrackCount][1].Start = tocFromLog[_toc.TrackCount].Start; + dtlFound = true; + } + } + } + if (!dtlFound && _cddbDiscIdTag != null) + { + uint cddbDiscIdNum; + if (uint.TryParse(_cddbDiscIdTag, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out cddbDiscIdNum) && (cddbDiscIdNum & 0xff) == _toc.TrackCount + 1) + { + uint lengthFromTag = ((cddbDiscIdNum >> 8) & 0xffff); + _minDataTrackLength = ((lengthFromTag + _toc[1].Start / 75) - 152) * 75 - _toc.Length; + } + } } } _accurateRipIdActual = AccurateRipVerify.CalculateAccurateRipId(_toc); + if (_accurateRipId == null) _accurateRipId = _accurateRipIdActual; _arVerify = new AccurateRipVerify(_toc); + if (_eacLog != null) + { + sr = new StringReader(_eacLog); + bool isEACLog = false; + int trNo = 1; + while ((lineStr = sr.ReadLine()) != null) + { + if (isEACLog && trNo <= TrackCount) + { + string[] s = { "Copy CRC ", "CRC êîïèè" }; + string[] n = lineStr.Split(s, StringSplitOptions.None); + uint crc; + if (n.Length == 2 && uint.TryParse(n[1], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out crc)) + _arVerify.CRCLOG(trNo++, crc); + } + else + if (lineStr.StartsWith("Exact Audio Copy")) + isEACLog = true; + } + if (trNo == 2) + { + _arVerify.CRCLOG(0, _arVerify.CRCLOG(1)); + if (TrackCount > 1) + _arVerify.CRCLOG(1, 0); + } + } + //if (!_dataTrackLength.HasValue && _cddbDiscIdTag != null) //{ // uint cddbDiscIdNum = UInt32.Parse(_cddbDiscIdTag, NumberStyles.HexNumber); @@ -1166,6 +1291,37 @@ namespace CUETools.Processor } } + private Stream OpenArchive(string fileName, bool showProgress) + { +#if !MONO + if (Path.GetExtension(_archivePath).ToLower() == ".rar") + { + RarStream rarStream = new RarStream(_archivePath, fileName); + rarStream.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); + if (showProgress) + rarStream.ExtractionProgress += new ExtractionProgressHandler(unrar_ExtractionProgress); + return rarStream; + } +#endif + if (Path.GetExtension(_archivePath).ToLower() == ".zip") + { + ZipInputStream zipStream = new ZipInputStream(File.OpenRead(_archivePath)); + ZipEntry theEntry = null; + while ((theEntry = zipStream.GetNextEntry()) != null) + if (theEntry.Name == fileName) + break; + if (theEntry == null) + throw new Exception("Archive entry not found."); + if (theEntry.IsCrypted) + { + unrar_PasswordRequired(this, new PasswordRequiredEventArgs()); + zipStream.Password = _archivePassword; + } + return zipStream; + } + throw new Exception("Unknown archive type."); + } + private void ShowProgress(string status, double percentTrack, double percentDisk, string input, string output) { if (this.CUEToolsProgress == null) @@ -1271,7 +1427,7 @@ namespace CUETools.Processor private static string LocateFile(string dir, string file, List contents) { List dirList, fileList; - string altDir, path; + string altDir; dirList = new List(); fileList = new List(); @@ -1289,9 +1445,12 @@ namespace CUETools.Processor for (int iDir = 0; iDir < dirList.Count; iDir++) { for (int iFile = 0; iFile < fileList.Count; iFile++) { - path = Path.Combine(dirList[iDir], fileList[iFile]); + string path = Path.Combine(dirList[iDir], fileList[iFile]); if ( (contents == null && File.Exists(path)) - || (contents != null && contents.Contains (path))) + || (contents != null && contents.Contains(path))) + return path; + path = dirList[iDir] + '/' + fileList[iFile]; + if (contents != null && contents.Contains(path)) return path; } } @@ -1302,6 +1461,7 @@ namespace CUETools.Processor public void GenerateFilenames(OutputAudioFormat format, bool outputLossyWAV, string outputPath) { _outputLossyWAV = outputLossyWAV; + _outputFormat = format; _cuePath = outputPath; string extension = General.FormatExtension(format); @@ -1396,15 +1556,9 @@ namespace CUETools.Processor IAudioSource audioSource; ShowProgress("Analyzing input file...", 0.0, 0.0, path, null); -#if !MONO if (_isArchive) - { - RarStream IO = new RarStream(_archivePath, path); - IO.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); - IO.ExtractionProgress += new ExtractionProgressHandler(unrar_ExtractionProgress); - audioSource = AudioReadWrite.GetAudioSource(path, IO); - } else -#endif + audioSource = AudioReadWrite.GetAudioSource(path, OpenArchive(path, true)); + else audioSource = AudioReadWrite.GetAudioSource(path, null); if ((audioSource.BitsPerSample != 16) || @@ -1523,8 +1677,8 @@ namespace CUETools.Processor public string TOCContents() { StringWriter sw = new StringWriter(); - for (int iTrack = 0; iTrack < TrackCount; iTrack++) - sw.WriteLine("\t{0}", _toc[iTrack+1].Start + 150); + for (int iTrack = 1; iTrack <= _toc.TrackCount; iTrack++) + sw.WriteLine("\t{0}", _toc[iTrack].Start + 150); sw.Close(); return sw.ToString(); } @@ -1556,7 +1710,7 @@ namespace CUETools.Processor if ((style == CUEStyle.GapsPrepended) || (style == CUEStyle.GapsLeftOut) || ((style == CUEStyle.GapsAppended) && - ((_toc[iTrack+1].Pregap == 0) || ((iTrack == 0) && !htoaToFile)))) + ((_toc[_toc.FirstAudio + iTrack].Pregap == 0) || ((iTrack == 0) && !htoaToFile)))) { WriteLine(sw, 0, String.Format("FILE \"{0}\" WAVE", _trackFilenames[iTrack])); timeRelativeToFileStart = 0; @@ -1566,16 +1720,16 @@ namespace CUETools.Processor for (i = 0; i < _tracks[iTrack].Attributes.Count; i++) WriteLine(sw, 2, _tracks[iTrack].Attributes[i]); - if (_toc[iTrack + 1].Pregap != 0) + if (_toc[_toc.FirstAudio + iTrack].Pregap != 0) { if (((style == CUEStyle.GapsLeftOut) || ((style == CUEStyle.GapsAppended) && (iTrack == 0) && !htoaToFile) || ((style == CUEStyle.SingleFile || style == CUEStyle.SingleFileWithCUE) && (iTrack == 0) && _usePregapForFirstTrackInSingleFile))) - WriteLine(sw, 2, "PREGAP " + CDImageLayout.TimeToString(_toc[iTrack + 1].Pregap)); + WriteLine(sw, 2, "PREGAP " + CDImageLayout.TimeToString(_toc[_toc.FirstAudio + iTrack].Pregap)); else { WriteLine(sw, 2, String.Format("INDEX 00 {0}", CDImageLayout.TimeToString(timeRelativeToFileStart))); - timeRelativeToFileStart += _toc[iTrack + 1].Pregap; + timeRelativeToFileStart += _toc[_toc.FirstAudio + iTrack].Pregap; if (style == CUEStyle.GapsAppended) { WriteLine(sw, 0, String.Format("FILE \"{0}\" WAVE", _trackFilenames[iTrack])); @@ -1583,10 +1737,10 @@ namespace CUETools.Processor } } } - for (iIndex = 1; iIndex <= _toc[iTrack+1].LastIndex; iIndex++) + for (iIndex = 1; iIndex <= _toc[_toc.FirstAudio + iTrack].LastIndex; iIndex++) { WriteLine(sw, 2, String.Format( "INDEX {0:00} {1}", iIndex, CDImageLayout.TimeToString(timeRelativeToFileStart))); - timeRelativeToFileStart += _toc.IndexLength(iTrack + 1, iIndex); + timeRelativeToFileStart += _toc.IndexLength(_toc.FirstAudio + iTrack, iIndex); } } } @@ -1779,7 +1933,8 @@ namespace CUETools.Processor break; } ShowProgress((string)"Contacting AccurateRip database...", 0, (dtl - minDTL) / 75.0, null, null); - lock (this) { + lock (this) + { if (_stop) throw new StopException(); if (_pause) @@ -1795,61 +1950,60 @@ namespace CUETools.Processor { _accurateRipId = _accurateRipIdActual; } - } else + } + else _arVerify.ContactAccurateRip(_accurateRipId); - if (_arVerify.AccResult != HttpStatusCode.OK) + if (_accurateRipMode == AccurateRipMode.VerifyThenConvert) { - if (_accurateRipMode == AccurateRipMode.Verify || _config.noUnverifiedOutput) + if (_arVerify.AccResult != HttpStatusCode.OK && !_isCD) { - if ((_accurateRipMode != AccurateRipMode.Verify && _config.writeArLogOnConvert) || - (_accurateRipMode == AccurateRipMode.Verify && _config.writeArLogOnVerify)) + if (_config.noUnverifiedOutput) { - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - StreamWriter sw = new StreamWriter(Path.ChangeExtension(_cuePath, ".accurip"), - false, CUESheet.Encoding); - GenerateAccurateRipLog(sw); - sw.Close(); + if (_config.writeArLogOnConvert) + { + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + StreamWriter sw = new StreamWriter(Path.ChangeExtension(_cuePath, ".accurip"), + false, CUESheet.Encoding); + GenerateAccurateRipLog(sw); + sw.Close(); + } + if (_config.createTOC) + { + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + WriteText(Path.ChangeExtension(_cuePath, ".toc"), TOCContents()); + } + return; } - if (_config.createTOC) - { - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - WriteText(Path.ChangeExtension(_cuePath, ".toc"), TOCContents()); - } - return; } - if (_accurateRipMode == AccurateRipMode.VerifyThenConvert && _isCD) + else { _writeOffset = 0; WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, true); + if (!_isCD) + { + uint tracksMatch; + int bestOffset; + + if (_config.noUnverifiedOutput) + { + FindBestOffset(_config.encodeWhenConfidence, false, out tracksMatch, out bestOffset); + if (tracksMatch * 100 < _config.encodeWhenPercent * TrackCount || (_config.encodeWhenZeroOffset && bestOffset != 0)) + SkipOutput = true; + } + + if (!SkipOutput && _config.fixOffset) + { + FindBestOffset(_config.fixWhenConfidence, false, out tracksMatch, out bestOffset); + if (tracksMatch * 100 >= _config.fixWhenPercent * TrackCount) + _writeOffset = bestOffset; + } + } _arVerify.CreateBackup(_writeOffset); } } - else if (_accurateRipMode == AccurateRipMode.VerifyThenConvert) - { - _writeOffset = 0; - WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, true); - - uint tracksMatch; - int bestOffset; - - if (_config.noUnverifiedOutput) - { - FindBestOffset(_config.encodeWhenConfidence, false, out tracksMatch, out bestOffset); - if (tracksMatch * 100 < _config.encodeWhenPercent * TrackCount || (_config.encodeWhenZeroOffset && bestOffset != 0)) - SkipOutput = true; - } - - if (!SkipOutput && _config.fixOffset) - { - FindBestOffset(_config.fixWhenConfidence, false, out tracksMatch, out bestOffset); - if (tracksMatch * 100 >= _config.fixWhenPercent * TrackCount) - _writeOffset = bestOffset; - } - _arVerify.CreateBackup(_writeOffset); - } } if (!SkipOutput) @@ -1861,7 +2015,8 @@ namespace CUETools.Processor } if (_isCD) destLengths = CalculateAudioFileLengths(style); // need to recalc, might have changed after scanning the CD - WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, _accurateRipMode == AccurateRipMode.Verify); + if (_outputFormat != OutputAudioFormat.NoAudio || _accurateRipMode == AccurateRipMode.Verify) + WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, _accurateRipMode == AccurateRipMode.Verify); if (_accurateRipMode != AccurateRipMode.Verify) { string logContents = LOGContents(); @@ -1928,7 +2083,8 @@ namespace CUETools.Processor } } - if (_accurateRipMode != AccurateRipMode.None) + if (_accurateRipMode == AccurateRipMode.Verify || + (_accurateRipMode != AccurateRipMode.None && _outputFormat != OutputAudioFormat.NoAudio)) { ShowProgress((string)"Generating AccurateRip report...", 0, 0, null, null); if (_accurateRipMode == AccurateRipMode.Verify && _config.writeArTagsOnVerify && _writeOffset == 0 && !_isArchive && !_isCD) @@ -2184,14 +2340,14 @@ namespace CUETools.Processor if (style == CUEStyle.SingleFile || style == CUEStyle.SingleFileWithCUE) { iDest++; - audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], noOutput); + audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], hdcdDecoder != null && hdcdDecoder.Decoding ? hdcdDecoder.BitsPerSample : 16, noOutput); if (!noOutput) SetAlbumTags(audioDest, bestOffset, style == CUEStyle.SingleFileWithCUE); } uint currentOffset = 0, previousOffset = 0; uint trackLength = _toc.Pregap * 588; - uint diskLength = 588 * (_toc[_toc.TrackCount].IsAudio ? _toc[_toc.TrackCount].End + 1 : _toc[_toc.TrackCount - 1].End + 1); + uint diskLength = 588 * _toc.AudioLength; uint diskOffset = 0; if (_accurateRipMode != AccurateRipMode.None) @@ -2199,7 +2355,9 @@ namespace CUETools.Processor ShowProgress(String.Format("{2} track {0:00} ({1:00}%)...", 0, 0, noOutput ? "Verifying" : "Writing"), 0, 0.0, null, null); +#if !DEBUG try +#endif { for (iTrack = 0; iTrack < TrackCount; iTrack++) { @@ -2212,20 +2370,20 @@ namespace CUETools.Processor hdcdDecoder.AudioDest = null; if (audioDest != null) audioDest.Close(); - audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], noOutput); + audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], hdcdDecoder != null && hdcdDecoder.Decoding ? hdcdDecoder.BitsPerSample : 16, noOutput); if (!noOutput) SetTrackTags(audioDest, iTrack, bestOffset); } - for (iIndex = 0; iIndex <= _toc[iTrack + 1].LastIndex; iIndex++) + for (iIndex = 0; iIndex <= _toc[_toc.FirstAudio + iTrack].LastIndex; iIndex++) { - uint samplesRemIndex = _toc.IndexLength(iTrack + 1, iIndex) * 588; + uint samplesRemIndex = _toc.IndexLength(_toc.FirstAudio + iTrack, iIndex) * 588; if (iIndex == 1) { previousOffset = currentOffset; currentOffset = 0; - trackLength = _toc[iTrack + 1].Length * 588; + trackLength = _toc[_toc.FirstAudio + iTrack].Length * 588; } if ((style == CUEStyle.GapsAppended) && (iIndex == 1)) @@ -2235,7 +2393,7 @@ namespace CUETools.Processor if (audioDest != null) audioDest.Close(); iDest++; - audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], noOutput); + audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], hdcdDecoder != null && hdcdDecoder.Decoding ? hdcdDecoder.BitsPerSample : 16, noOutput); if (!noOutput) SetTrackTags(audioDest, iTrack, bestOffset); } @@ -2246,7 +2404,7 @@ namespace CUETools.Processor if (htoaToFile) { iDest++; - audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], noOutput); + audioDest = GetAudioDest(destPaths[iDest], destLengths[iDest], hdcdDecoder != null && hdcdDecoder.Decoding ? hdcdDecoder.BitsPerSample : 16, noOutput); } } else if ((style == CUEStyle.GapsLeftOut) && (iIndex == 0)) @@ -2331,6 +2489,7 @@ namespace CUETools.Processor } } } +#if !DEBUG catch (Exception ex) { if (hdcdDecoder != null) @@ -2344,6 +2503,7 @@ namespace CUETools.Processor audioDest = null; throw ex; } +#endif #if !MONO //if (_isCD && audioSource != null && audioSource is CDDriveReader) @@ -2353,17 +2513,16 @@ namespace CUETools.Processor _toc = (CDImageLayout)_ripper.TOC.Clone(); if (_toc.Catalog != null) Catalog = _toc.Catalog; - for (iTrack = 1; iTrack <= _toc.TrackCount; iTrack++) - if (_toc[iTrack].IsAudio) + for (iTrack = 0; iTrack < _toc.AudioTracks; iTrack++) { - if (_toc[iTrack].ISRC != null) - General.SetCUELine(_tracks[iTrack - 1].Attributes, "ISRC", _toc[iTrack].ISRC, false); - //if (_toc[iTrack].DCP || _toc[iTrack].PreEmphasis) + if (_toc[_toc.FirstAudio + iTrack].ISRC != null) + General.SetCUELine(_tracks[iTrack].Attributes, "ISRC", _toc[_toc.FirstAudio + iTrack].ISRC, false); + //if (_toc[_toc.FirstAudio + iTrack].DCP || _toc[_toc.FirstAudio + iTrack].PreEmphasis) //cueWriter.WriteLine(" FLAGS{0}{1}", audioSource.TOC[track].PreEmphasis ? " PRE" : "", audioSource.TOC[track].DCP ? " DCP" : ""); - if (_toc[iTrack].DCP) - General.SetCUELine(_tracks[iTrack - 1].Attributes, "FLAGS", "DCP", false); - if (_toc[iTrack].PreEmphasis) - General.SetCUELine(_tracks[iTrack - 1].Attributes, "FLAGS", "PRE", false); + if (_toc[_toc.FirstAudio + iTrack].DCP) + General.SetCUELine(_tracks[iTrack].Attributes, "FLAGS", "DCP", false); + if (_toc[_toc.FirstAudio + iTrack].PreEmphasis) + General.SetCUELine(_tracks[iTrack].Attributes, "FLAGS", "PRE", false); } } #endif @@ -2435,17 +2594,18 @@ namespace CUETools.Processor foundAll = false; for (i = 0; i < audioExts.Length; i++) { - foundAll = true; List newFiles = new List(); for (int j = 0; j < origFiles.Count; j++) { string newFilename = Path.ChangeExtension(Path.GetFileName(origFiles[j]), audioExts[i].Substring(1)); - foundAll &= LocateFile(dir, newFilename, files) != null; - newFiles.Add (newFilename); + string locatedFilename = LocateFile(dir, newFilename, files); + if (locatedFilename != null) + newFiles.Add(locatedFilename); } - if (foundAll) + if (newFiles.Count == origFiles.Count) { audioFiles = newFiles.ToArray(); + foundAll = true; break; } } @@ -2506,7 +2666,8 @@ namespace CUETools.Processor if (style == CUEStyle.GapsPrepended || style == CUEStyle.GapsLeftOut) iFile++; - for (iIndex = 0; iIndex <= _toc[iTrack+1].LastIndex; iIndex++) { + for (iIndex = 0; iIndex <= _toc[_toc.FirstAudio + iTrack].LastIndex; iIndex++) + { if (style == CUEStyle.GapsAppended && (iIndex == 1 || (iIndex == 0 && iTrack == 0 && htoaToFile))) iFile++; @@ -2516,7 +2677,7 @@ namespace CUETools.Processor discardOutput = (style == CUEStyle.GapsLeftOut && iIndex == 0); if (!discardOutput) - fileLengths[iFile] += (int)_toc.IndexLength(iTrack + 1, iIndex) * 588; + fileLengths[iFile] += (int)_toc.IndexLength(_toc.FirstAudio + iTrack, iIndex) * 588; } } @@ -2555,11 +2716,11 @@ namespace CUETools.Processor } } - private IAudioDest GetAudioDest(string path, int finalSampleCount, bool noOutput) + private IAudioDest GetAudioDest(string path, int finalSampleCount, int bps, bool noOutput) { if (noOutput) - return new DummyWriter(path, (_config.detectHDCD && _config.decodeHDCD) ? 24 : 16, 2, 44100); - return AudioReadWrite.GetAudioDest(path, finalSampleCount, _config); + return new DummyWriter(path, bps, 2, 44100); + return AudioReadWrite.GetAudioDest(path, finalSampleCount, bps, 44100, _config); } private IAudioSource GetAudioSource(int sourceIndex) { @@ -2577,14 +2738,10 @@ namespace CUETools.Processor //audioSource = _ripper; audioSource = new AudioPipe(_ripper, 3); } else - if (_isArchive) - { - RarStream IO = new RarStream(_archivePath, sourceInfo.Path); - IO.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); - audioSource = AudioReadWrite.GetAudioSource(sourceInfo.Path, IO); - } - else #endif + if (_isArchive) + audioSource = AudioReadWrite.GetAudioSource(sourceInfo.Path, OpenArchive(sourceInfo.Path, false)); + else audioSource = AudioReadWrite.GetAudioSource(sourceInfo.Path, null); } @@ -2865,9 +3022,9 @@ namespace CUETools.Processor int last = _params.Count - 1; for (int i = 0; i <= last; i++) { - if (_quoted[i]) sb.Append('"'); - sb.Append(_params[i]); - if (_quoted[i]) sb.Append('"'); + if (_quoted[i] || _params[i].Contains(" ")) sb.Append('"'); + sb.Append(_params[i].Replace('"', '\'')); + if (_quoted[i] || _params[i].Contains(" ")) sb.Append('"'); if (i < last) sb.Append(' '); } diff --git a/CUETools.Processor/frmProperties.Designer.cs b/CUETools.Processor/frmProperties.Designer.cs new file mode 100644 index 0000000..70fc69e --- /dev/null +++ b/CUETools.Processor/frmProperties.Designer.cs @@ -0,0 +1,152 @@ +namespace CUETools.Processor +{ + partial class frmProperties + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmProperties)); + this.textArtist = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textTitle = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.textYear = new System.Windows.Forms.TextBox(); + this.textGenre = new System.Windows.Forms.TextBox(); + this.textCatalog = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // textArtist + // + resources.ApplyResources(this.textArtist, "textArtist"); + this.textArtist.Name = "textArtist"; + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textTitle + // + resources.ApplyResources(this.textTitle, "textTitle"); + this.textTitle.Name = "textTitle"; + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + resources.ApplyResources(this.button2, "button2"); + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // textYear + // + resources.ApplyResources(this.textYear, "textYear"); + this.textYear.Name = "textYear"; + // + // textGenre + // + resources.ApplyResources(this.textGenre, "textGenre"); + this.textGenre.Name = "textGenre"; + // + // textCatalog + // + resources.ApplyResources(this.textCatalog, "textCatalog"); + this.textCatalog.Name = "textCatalog"; + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.Name = "label4"; + // + // label5 + // + resources.ApplyResources(this.label5, "label5"); + this.label5.Name = "label5"; + // + // frmProperties + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.Controls.Add(this.label5); + this.Controls.Add(this.label4); + this.Controls.Add(this.textCatalog); + this.Controls.Add(this.textGenre); + this.Controls.Add(this.textYear); + this.Controls.Add(this.label3); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.label2); + this.Controls.Add(this.textTitle); + this.Controls.Add(this.label1); + this.Controls.Add(this.textArtist); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Name = "frmProperties"; + this.Load += new System.EventHandler(this.frmProperties_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textArtist; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textTitle; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textYear; + private System.Windows.Forms.TextBox textGenre; + private System.Windows.Forms.TextBox textCatalog; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + } +} \ No newline at end of file diff --git a/CUETools.Processor/frmProperties.cs b/CUETools.Processor/frmProperties.cs new file mode 100644 index 0000000..f6fca03 --- /dev/null +++ b/CUETools.Processor/frmProperties.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using CUETools.Processor; + +namespace CUETools.Processor +{ + public partial class frmProperties : Form + { + public frmProperties() + { + InitializeComponent(); + } + + private void frmProperties_Load(object sender, EventArgs e) + { + textArtist.Text = _cueSheet.Artist; + textTitle.Text = _cueSheet.Title; + textYear.Text = _cueSheet.Year; + textGenre.Text = _cueSheet.Genre; + textCatalog.Text = _cueSheet.Catalog; + } + + public CUESheet CUE + { + get + { + return _cueSheet; + } + set + { + _cueSheet = value; + } + } + + CUESheet _cueSheet; + + private void button1_Click(object sender, EventArgs e) + { + _cueSheet.Artist = textArtist.Text; + _cueSheet.Title = textTitle.Text; + _cueSheet.Year = textYear.Text; + _cueSheet.Genre = textGenre.Text; + _cueSheet.Catalog = textCatalog.Text; + } + } +} \ No newline at end of file diff --git a/CUETools.Processor/frmProperties.resx b/CUETools.Processor/frmProperties.resx new file mode 100644 index 0000000..5a623d2 --- /dev/null +++ b/CUETools.Processor/frmProperties.resx @@ -0,0 +1,441 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Left, Right + + + + 48, 12 + + + 374, 20 + + + + 0 + + + textArtist + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 11 + + + True + + + 12, 15 + + + 30, 13 + + + 1 + + + Artist + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 10 + + + True + + + NoControl + + + 12, 41 + + + 27, 13 + + + 3 + + + Title + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 8 + + + Top, Left, Right + + + 48, 38 + + + 374, 20 + + + 2 + + + textTitle + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 9 + + + 347, 90 + + + 75, 23 + + + 14 + + + Ok + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + 266, 90 + + + 75, 23 + + + 15 + + + Cancel + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + True + + + 12, 67 + + + 29, 13 + + + 6 + + + Year + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + 48, 64 + + + 67, 20 + + + 7 + + + textYear + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + 163, 64 + + + 100, 20 + + + 8 + + + textGenre + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 318, 64 + + + 104, 20 + + + 9 + + + textCatalog + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + True + + + 121, 67 + + + 36, 13 + + + 10 + + + Genre + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + True + + + 269, 67 + + + 43, 13 + + + 11 + + + Catalog + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 434, 120 + + + CenterParent + + + Release information + + + frmProperties + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/CUETools.Ripper.SCSI/SCSIDrive.cs b/CUETools.Ripper.SCSI/SCSIDrive.cs index fc7dc35..12aab53 100644 --- a/CUETools.Ripper.SCSI/SCSIDrive.cs +++ b/CUETools.Ripper.SCSI/SCSIDrive.cs @@ -269,11 +269,13 @@ namespace CUETools.Ripper.SCSI toc[iTrack + 1].StartSector - toc[iTrack].StartSector - ((toc[iTrack + 1].Control < 4 || iTrack + 1 == toc.Count - 1) ? 0U : 152U * 75U), toc[iTrack].Control < 4, - (toc[iTrack].Control & 1) == 1)); - if (_toc[1].IsAudio) - _toc[1][0].Start = 0; + (toc[iTrack].Control & 1) == 1)); if (_toc.AudioLength > 0) + { + if (_toc[1].IsAudio) + _toc[1][0].Start = 0; Position = 0; + } return true; } @@ -356,7 +358,7 @@ namespace CUETools.Ripper.SCSI if (!updateMap) break; int sec = ff + 75 * (ss + 60 * mm) - 150; // sector + iSector; - if (iTrack > _toc.AudioTracks) + if (iTrack >= _toc.FirstAudio + _toc.AudioTracks) throw new Exception("strange track number encountred"); if (iTrack != _currentTrack) { @@ -546,13 +548,13 @@ namespace CUETools.Ripper.SCSI MemSet(data, size, 0xff); } if (_readCDCommand == ReadCDCommand.ReadCdBEh) - st = m_device.ReadCDAndSubChannel(_mainChannelMode, _subChannelMode, _c2ErrorMode, 1, false, (uint)sector, (uint)Sectors2Read, (IntPtr)((void*)data), _timeout); + st = m_device.ReadCDAndSubChannel(_mainChannelMode, _subChannelMode, _c2ErrorMode, 1, false, (uint)sector + _toc[_toc.FirstAudio][0].Start, (uint)Sectors2Read, (IntPtr)((void*)data), _timeout); else - st = m_device.ReadCDDA(_subChannelMode, (uint)sector, (uint)Sectors2Read, (IntPtr)((void*)data), _timeout); + st = m_device.ReadCDDA(_subChannelMode, (uint)sector + _toc[_toc.FirstAudio][0].Start, (uint)Sectors2Read, (IntPtr)((void*)data), _timeout); } if (st == Device.CommandStatus.Success && _subChannelMode == Device.SubChannelMode.None && subchannel) - st = m_device.ReadSubChannel(2, (uint)sector, (uint)Sectors2Read, ref _subchannelBuffer, _timeout); + st = m_device.ReadSubChannel(2, (uint)sector + _toc[_toc.FirstAudio][0].Start, (uint)Sectors2Read, ref _subchannelBuffer, _timeout); if (st == Device.CommandStatus.Success) { diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index ea85449..e01d77f 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -85,6 +85,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.TTA", "..\C {B3DF599C-1C8F-451D-91E4-DD766210DA1F} = {B3DF599C-1C8F-451D-91E4-DD766210DA1F} EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Converter", "..\CUETools.Converter\CUETools.Converter.csproj", "{115CC5B0-0385-41CD-8A23-6A7EA4C51926}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -411,6 +413,18 @@ Global {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|x64.Build.0 = Release|x64 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|x86.ActiveCfg = Release|Win32 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|x86.Build.0 = Release|Win32 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Any CPU.Build.0 = Debug|Any CPU + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x64.ActiveCfg = Debug|x64 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x64.Build.0 = Debug|x64 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x86.ActiveCfg = Debug|x86 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x86.Build.0 = Debug|x86 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Any CPU.ActiveCfg = Release|Any CPU + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Any CPU.Build.0 = Release|Any CPU + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x64.ActiveCfg = Release|x64 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x64.Build.0 = Release|x64 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x86.ActiveCfg = Release|x86 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -429,6 +443,7 @@ Global {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} {9253A314-1821-42BF-B02F-2BF986B1765D} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} + {115CC5B0-0385-41CD-8A23-6A7EA4C51926} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} {B75FA7AD-968E-4990-B342-1B4B17C850DF} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} diff --git a/CUETools/frmCUETools.Designer.cs b/CUETools/frmCUETools.Designer.cs index c480626..893b4dd 100644 --- a/CUETools/frmCUETools.Designer.cs +++ b/CUETools/frmCUETools.Designer.cs @@ -76,9 +76,9 @@ namespace JDP { this.btnPause = new System.Windows.Forms.Button(); this.btnResume = new System.Windows.Forms.Button(); this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.rbFreedbNever = new System.Windows.Forms.RadioButton(); - this.rbFreedbIf = new System.Windows.Forms.RadioButton(); this.rbFreedbAlways = new System.Windows.Forms.RadioButton(); + this.rbFreedbIf = new System.Windows.Forms.RadioButton(); + this.rbFreedbNever = new System.Windows.Forms.RadioButton(); this.grpCUEPaths.SuspendLayout(); this.grpOutputStyle.SuspendLayout(); this.grpOutputPathGeneration.SuspendLayout(); @@ -90,78 +90,125 @@ namespace JDP { // // btnConvert // + this.btnConvert.AccessibleDescription = null; + this.btnConvert.AccessibleName = null; resources.ApplyResources(this.btnConvert, "btnConvert"); + this.btnConvert.BackgroundImage = null; + this.btnConvert.Font = null; this.btnConvert.Name = "btnConvert"; + this.toolTip1.SetToolTip(this.btnConvert, resources.GetString("btnConvert.ToolTip")); this.btnConvert.UseVisualStyleBackColor = true; this.btnConvert.Click += new System.EventHandler(this.btnConvert_Click); // // grpCUEPaths // + this.grpCUEPaths.AccessibleDescription = null; + this.grpCUEPaths.AccessibleName = null; + resources.ApplyResources(this.grpCUEPaths, "grpCUEPaths"); + this.grpCUEPaths.BackgroundImage = null; this.grpCUEPaths.Controls.Add(this.btnBrowseOutput); this.grpCUEPaths.Controls.Add(this.btnBrowseInput); this.grpCUEPaths.Controls.Add(this.lblOutput); this.grpCUEPaths.Controls.Add(this.lblInput); this.grpCUEPaths.Controls.Add(this.txtOutputPath); this.grpCUEPaths.Controls.Add(this.txtInputPath); - resources.ApplyResources(this.grpCUEPaths, "grpCUEPaths"); + this.grpCUEPaths.Font = null; this.grpCUEPaths.Name = "grpCUEPaths"; this.grpCUEPaths.TabStop = false; + this.toolTip1.SetToolTip(this.grpCUEPaths, resources.GetString("grpCUEPaths.ToolTip")); // // btnBrowseOutput // + this.btnBrowseOutput.AccessibleDescription = null; + this.btnBrowseOutput.AccessibleName = null; resources.ApplyResources(this.btnBrowseOutput, "btnBrowseOutput"); + this.btnBrowseOutput.BackgroundImage = null; + this.btnBrowseOutput.Font = null; this.btnBrowseOutput.Name = "btnBrowseOutput"; + this.toolTip1.SetToolTip(this.btnBrowseOutput, resources.GetString("btnBrowseOutput.ToolTip")); this.btnBrowseOutput.UseVisualStyleBackColor = true; this.btnBrowseOutput.Click += new System.EventHandler(this.btnBrowseOutput_Click); // // btnBrowseInput // + this.btnBrowseInput.AccessibleDescription = null; + this.btnBrowseInput.AccessibleName = null; resources.ApplyResources(this.btnBrowseInput, "btnBrowseInput"); + this.btnBrowseInput.BackgroundImage = null; + this.btnBrowseInput.Font = null; this.btnBrowseInput.Name = "btnBrowseInput"; + this.toolTip1.SetToolTip(this.btnBrowseInput, resources.GetString("btnBrowseInput.ToolTip")); this.btnBrowseInput.UseVisualStyleBackColor = true; this.btnBrowseInput.Click += new System.EventHandler(this.btnBrowseInput_Click); // // lblOutput // + this.lblOutput.AccessibleDescription = null; + this.lblOutput.AccessibleName = null; resources.ApplyResources(this.lblOutput, "lblOutput"); + this.lblOutput.Font = null; this.lblOutput.Name = "lblOutput"; + this.toolTip1.SetToolTip(this.lblOutput, resources.GetString("lblOutput.ToolTip")); // // lblInput // + this.lblInput.AccessibleDescription = null; + this.lblInput.AccessibleName = null; resources.ApplyResources(this.lblInput, "lblInput"); + this.lblInput.Font = null; this.lblInput.Name = "lblInput"; + this.toolTip1.SetToolTip(this.lblInput, resources.GetString("lblInput.ToolTip")); // // txtOutputPath // + this.txtOutputPath.AccessibleDescription = null; + this.txtOutputPath.AccessibleName = null; this.txtOutputPath.AllowDrop = true; resources.ApplyResources(this.txtOutputPath, "txtOutputPath"); + this.txtOutputPath.BackgroundImage = null; + this.txtOutputPath.Font = null; this.txtOutputPath.Name = "txtOutputPath"; + this.toolTip1.SetToolTip(this.txtOutputPath, resources.GetString("txtOutputPath.ToolTip")); this.txtOutputPath.DragDrop += new System.Windows.Forms.DragEventHandler(this.PathTextBox_DragDrop); this.txtOutputPath.DragEnter += new System.Windows.Forms.DragEventHandler(this.PathTextBox_DragEnter); // // txtInputPath // + this.txtInputPath.AccessibleDescription = null; + this.txtInputPath.AccessibleName = null; this.txtInputPath.AllowDrop = true; resources.ApplyResources(this.txtInputPath, "txtInputPath"); + this.txtInputPath.BackgroundImage = null; + this.txtInputPath.Font = null; this.txtInputPath.Name = "txtInputPath"; + this.toolTip1.SetToolTip(this.txtInputPath, resources.GetString("txtInputPath.ToolTip")); this.txtInputPath.TextChanged += new System.EventHandler(this.txtInputPath_TextChanged); this.txtInputPath.DragDrop += new System.Windows.Forms.DragEventHandler(this.PathTextBox_DragDrop); this.txtInputPath.DragEnter += new System.Windows.Forms.DragEventHandler(this.PathTextBox_DragEnter); // // grpOutputStyle // + this.grpOutputStyle.AccessibleDescription = null; + this.grpOutputStyle.AccessibleName = null; + resources.ApplyResources(this.grpOutputStyle, "grpOutputStyle"); + this.grpOutputStyle.BackgroundImage = null; this.grpOutputStyle.Controls.Add(this.rbEmbedCUE); this.grpOutputStyle.Controls.Add(this.rbGapsLeftOut); this.grpOutputStyle.Controls.Add(this.rbGapsPrepended); this.grpOutputStyle.Controls.Add(this.rbGapsAppended); this.grpOutputStyle.Controls.Add(this.rbSingleFile); - resources.ApplyResources(this.grpOutputStyle, "grpOutputStyle"); + this.grpOutputStyle.Font = null; this.grpOutputStyle.Name = "grpOutputStyle"; this.grpOutputStyle.TabStop = false; + this.toolTip1.SetToolTip(this.grpOutputStyle, resources.GetString("grpOutputStyle.ToolTip")); // // rbEmbedCUE // + this.rbEmbedCUE.AccessibleDescription = null; + this.rbEmbedCUE.AccessibleName = null; resources.ApplyResources(this.rbEmbedCUE, "rbEmbedCUE"); + this.rbEmbedCUE.BackgroundImage = null; + this.rbEmbedCUE.Font = null; this.rbEmbedCUE.Name = "rbEmbedCUE"; this.rbEmbedCUE.TabStop = true; this.toolTip1.SetToolTip(this.rbEmbedCUE, resources.GetString("rbEmbedCUE.ToolTip")); @@ -170,29 +217,45 @@ namespace JDP { // // rbGapsLeftOut // + this.rbGapsLeftOut.AccessibleDescription = null; + this.rbGapsLeftOut.AccessibleName = null; resources.ApplyResources(this.rbGapsLeftOut, "rbGapsLeftOut"); + this.rbGapsLeftOut.BackgroundImage = null; + this.rbGapsLeftOut.Font = null; this.rbGapsLeftOut.Name = "rbGapsLeftOut"; this.toolTip1.SetToolTip(this.rbGapsLeftOut, resources.GetString("rbGapsLeftOut.ToolTip")); this.rbGapsLeftOut.UseVisualStyleBackColor = true; // // rbGapsPrepended // + this.rbGapsPrepended.AccessibleDescription = null; + this.rbGapsPrepended.AccessibleName = null; resources.ApplyResources(this.rbGapsPrepended, "rbGapsPrepended"); + this.rbGapsPrepended.BackgroundImage = null; + this.rbGapsPrepended.Font = null; this.rbGapsPrepended.Name = "rbGapsPrepended"; this.toolTip1.SetToolTip(this.rbGapsPrepended, resources.GetString("rbGapsPrepended.ToolTip")); this.rbGapsPrepended.UseVisualStyleBackColor = true; // // rbGapsAppended // + this.rbGapsAppended.AccessibleDescription = null; + this.rbGapsAppended.AccessibleName = null; resources.ApplyResources(this.rbGapsAppended, "rbGapsAppended"); + this.rbGapsAppended.BackgroundImage = null; + this.rbGapsAppended.Font = null; this.rbGapsAppended.Name = "rbGapsAppended"; this.toolTip1.SetToolTip(this.rbGapsAppended, resources.GetString("rbGapsAppended.ToolTip")); this.rbGapsAppended.UseVisualStyleBackColor = true; // // rbSingleFile // + this.rbSingleFile.AccessibleDescription = null; + this.rbSingleFile.AccessibleName = null; resources.ApplyResources(this.rbSingleFile, "rbSingleFile"); + this.rbSingleFile.BackgroundImage = null; this.rbSingleFile.Checked = true; + this.rbSingleFile.Font = null; this.rbSingleFile.Name = "rbSingleFile"; this.rbSingleFile.TabStop = true; this.toolTip1.SetToolTip(this.rbSingleFile, resources.GetString("rbSingleFile.ToolTip")); @@ -200,13 +263,22 @@ namespace JDP { // // btnAbout // + this.btnAbout.AccessibleDescription = null; + this.btnAbout.AccessibleName = null; resources.ApplyResources(this.btnAbout, "btnAbout"); + this.btnAbout.BackgroundImage = null; + this.btnAbout.Font = null; this.btnAbout.Name = "btnAbout"; + this.toolTip1.SetToolTip(this.btnAbout, resources.GetString("btnAbout.ToolTip")); this.btnAbout.UseVisualStyleBackColor = true; this.btnAbout.Click += new System.EventHandler(this.btnAbout_Click); // // grpOutputPathGeneration // + this.grpOutputPathGeneration.AccessibleDescription = null; + this.grpOutputPathGeneration.AccessibleName = null; + resources.ApplyResources(this.grpOutputPathGeneration, "grpOutputPathGeneration"); + this.grpOutputPathGeneration.BackgroundImage = null; this.grpOutputPathGeneration.Controls.Add(this.txtCustomFormat); this.grpOutputPathGeneration.Controls.Add(this.rbCustomFormat); this.grpOutputPathGeneration.Controls.Add(this.txtCreateSubdirectory); @@ -214,60 +286,100 @@ namespace JDP { this.grpOutputPathGeneration.Controls.Add(this.rbCreateSubdirectory); this.grpOutputPathGeneration.Controls.Add(this.rbAppendFilename); this.grpOutputPathGeneration.Controls.Add(this.txtAppendFilename); - resources.ApplyResources(this.grpOutputPathGeneration, "grpOutputPathGeneration"); + this.grpOutputPathGeneration.Font = null; this.grpOutputPathGeneration.Name = "grpOutputPathGeneration"; this.grpOutputPathGeneration.TabStop = false; + this.toolTip1.SetToolTip(this.grpOutputPathGeneration, resources.GetString("grpOutputPathGeneration.ToolTip")); // // txtCustomFormat // + this.txtCustomFormat.AccessibleDescription = null; + this.txtCustomFormat.AccessibleName = null; resources.ApplyResources(this.txtCustomFormat, "txtCustomFormat"); + this.txtCustomFormat.BackgroundImage = null; + this.txtCustomFormat.Font = null; this.txtCustomFormat.Name = "txtCustomFormat"; + this.toolTip1.SetToolTip(this.txtCustomFormat, resources.GetString("txtCustomFormat.ToolTip")); this.txtCustomFormat.TextChanged += new System.EventHandler(this.txtCustomFormat_TextChanged); // // rbCustomFormat // + this.rbCustomFormat.AccessibleDescription = null; + this.rbCustomFormat.AccessibleName = null; resources.ApplyResources(this.rbCustomFormat, "rbCustomFormat"); + this.rbCustomFormat.BackgroundImage = null; + this.rbCustomFormat.Font = null; this.rbCustomFormat.Name = "rbCustomFormat"; this.rbCustomFormat.TabStop = true; + this.toolTip1.SetToolTip(this.rbCustomFormat, resources.GetString("rbCustomFormat.ToolTip")); this.rbCustomFormat.UseVisualStyleBackColor = true; this.rbCustomFormat.CheckedChanged += new System.EventHandler(this.rbCustomFormat_CheckedChanged); // // txtCreateSubdirectory // + this.txtCreateSubdirectory.AccessibleDescription = null; + this.txtCreateSubdirectory.AccessibleName = null; resources.ApplyResources(this.txtCreateSubdirectory, "txtCreateSubdirectory"); + this.txtCreateSubdirectory.BackgroundImage = null; + this.txtCreateSubdirectory.Font = null; this.txtCreateSubdirectory.Name = "txtCreateSubdirectory"; + this.toolTip1.SetToolTip(this.txtCreateSubdirectory, resources.GetString("txtCreateSubdirectory.ToolTip")); this.txtCreateSubdirectory.TextChanged += new System.EventHandler(this.txtCreateSubdirectory_TextChanged); // // rbDontGenerate // + this.rbDontGenerate.AccessibleDescription = null; + this.rbDontGenerate.AccessibleName = null; resources.ApplyResources(this.rbDontGenerate, "rbDontGenerate"); + this.rbDontGenerate.BackgroundImage = null; + this.rbDontGenerate.Font = null; this.rbDontGenerate.Name = "rbDontGenerate"; + this.toolTip1.SetToolTip(this.rbDontGenerate, resources.GetString("rbDontGenerate.ToolTip")); this.rbDontGenerate.UseVisualStyleBackColor = true; // // rbCreateSubdirectory // + this.rbCreateSubdirectory.AccessibleDescription = null; + this.rbCreateSubdirectory.AccessibleName = null; resources.ApplyResources(this.rbCreateSubdirectory, "rbCreateSubdirectory"); + this.rbCreateSubdirectory.BackgroundImage = null; this.rbCreateSubdirectory.Checked = true; + this.rbCreateSubdirectory.Font = null; this.rbCreateSubdirectory.Name = "rbCreateSubdirectory"; this.rbCreateSubdirectory.TabStop = true; + this.toolTip1.SetToolTip(this.rbCreateSubdirectory, resources.GetString("rbCreateSubdirectory.ToolTip")); this.rbCreateSubdirectory.UseVisualStyleBackColor = true; this.rbCreateSubdirectory.CheckedChanged += new System.EventHandler(this.rbCreateSubdirectory_CheckedChanged); // // rbAppendFilename // + this.rbAppendFilename.AccessibleDescription = null; + this.rbAppendFilename.AccessibleName = null; resources.ApplyResources(this.rbAppendFilename, "rbAppendFilename"); + this.rbAppendFilename.BackgroundImage = null; + this.rbAppendFilename.Font = null; this.rbAppendFilename.Name = "rbAppendFilename"; + this.toolTip1.SetToolTip(this.rbAppendFilename, resources.GetString("rbAppendFilename.ToolTip")); this.rbAppendFilename.UseVisualStyleBackColor = true; this.rbAppendFilename.CheckedChanged += new System.EventHandler(this.rbAppendFilename_CheckedChanged); // // txtAppendFilename // + this.txtAppendFilename.AccessibleDescription = null; + this.txtAppendFilename.AccessibleName = null; resources.ApplyResources(this.txtAppendFilename, "txtAppendFilename"); + this.txtAppendFilename.BackgroundImage = null; + this.txtAppendFilename.Font = null; this.txtAppendFilename.Name = "txtAppendFilename"; + this.toolTip1.SetToolTip(this.txtAppendFilename, resources.GetString("txtAppendFilename.ToolTip")); this.txtAppendFilename.TextChanged += new System.EventHandler(this.txtAppendFilename_TextChanged); // // grpAudioOutput // + this.grpAudioOutput.AccessibleDescription = null; + this.grpAudioOutput.AccessibleName = null; + resources.ApplyResources(this.grpAudioOutput, "grpAudioOutput"); + this.grpAudioOutput.BackgroundImage = null; this.grpAudioOutput.Controls.Add(this.rbTTA); this.grpAudioOutput.Controls.Add(this.chkLossyWAV); this.grpAudioOutput.Controls.Add(this.rbAPE); @@ -275,21 +387,31 @@ namespace JDP { this.grpAudioOutput.Controls.Add(this.rbWavPack); this.grpAudioOutput.Controls.Add(this.rbWAV); this.grpAudioOutput.Controls.Add(this.rbFLAC); - resources.ApplyResources(this.grpAudioOutput, "grpAudioOutput"); + this.grpAudioOutput.Font = null; this.grpAudioOutput.Name = "grpAudioOutput"; this.grpAudioOutput.TabStop = false; + this.toolTip1.SetToolTip(this.grpAudioOutput, resources.GetString("grpAudioOutput.ToolTip")); // // rbTTA // + this.rbTTA.AccessibleDescription = null; + this.rbTTA.AccessibleName = null; resources.ApplyResources(this.rbTTA, "rbTTA"); + this.rbTTA.BackgroundImage = null; + this.rbTTA.Font = null; this.rbTTA.Name = "rbTTA"; this.rbTTA.TabStop = true; + this.toolTip1.SetToolTip(this.rbTTA, resources.GetString("rbTTA.ToolTip")); this.rbTTA.UseVisualStyleBackColor = true; this.rbTTA.CheckedChanged += new System.EventHandler(this.rbTTA_CheckedChanged); // // chkLossyWAV // + this.chkLossyWAV.AccessibleDescription = null; + this.chkLossyWAV.AccessibleName = null; resources.ApplyResources(this.chkLossyWAV, "chkLossyWAV"); + this.chkLossyWAV.BackgroundImage = null; + this.chkLossyWAV.Font = null; this.chkLossyWAV.Name = "chkLossyWAV"; this.toolTip1.SetToolTip(this.chkLossyWAV, resources.GetString("chkLossyWAV.ToolTip")); this.chkLossyWAV.UseVisualStyleBackColor = true; @@ -297,15 +419,24 @@ namespace JDP { // // rbAPE // + this.rbAPE.AccessibleDescription = null; + this.rbAPE.AccessibleName = null; resources.ApplyResources(this.rbAPE, "rbAPE"); + this.rbAPE.BackgroundImage = null; + this.rbAPE.Font = null; this.rbAPE.Name = "rbAPE"; this.rbAPE.TabStop = true; + this.toolTip1.SetToolTip(this.rbAPE, resources.GetString("rbAPE.ToolTip")); this.rbAPE.UseVisualStyleBackColor = true; this.rbAPE.CheckedChanged += new System.EventHandler(this.rbAPE_CheckedChanged); // // rbNoAudio // + this.rbNoAudio.AccessibleDescription = null; + this.rbNoAudio.AccessibleName = null; resources.ApplyResources(this.rbNoAudio, "rbNoAudio"); + this.rbNoAudio.BackgroundImage = null; + this.rbNoAudio.Font = null; this.rbNoAudio.Name = "rbNoAudio"; this.toolTip1.SetToolTip(this.rbNoAudio, resources.GetString("rbNoAudio.ToolTip")); this.rbNoAudio.UseVisualStyleBackColor = true; @@ -313,85 +444,137 @@ namespace JDP { // // rbWavPack // + this.rbWavPack.AccessibleDescription = null; + this.rbWavPack.AccessibleName = null; resources.ApplyResources(this.rbWavPack, "rbWavPack"); + this.rbWavPack.BackgroundImage = null; + this.rbWavPack.Font = null; this.rbWavPack.Name = "rbWavPack"; + this.toolTip1.SetToolTip(this.rbWavPack, resources.GetString("rbWavPack.ToolTip")); this.rbWavPack.UseVisualStyleBackColor = true; this.rbWavPack.CheckedChanged += new System.EventHandler(this.rbWavPack_CheckedChanged); // // rbWAV // + this.rbWAV.AccessibleDescription = null; + this.rbWAV.AccessibleName = null; resources.ApplyResources(this.rbWAV, "rbWAV"); + this.rbWAV.BackgroundImage = null; this.rbWAV.Checked = true; + this.rbWAV.Font = null; this.rbWAV.Name = "rbWAV"; this.rbWAV.TabStop = true; + this.toolTip1.SetToolTip(this.rbWAV, resources.GetString("rbWAV.ToolTip")); this.rbWAV.UseVisualStyleBackColor = true; this.rbWAV.CheckedChanged += new System.EventHandler(this.rbWAV_CheckedChanged); // // rbFLAC // + this.rbFLAC.AccessibleDescription = null; + this.rbFLAC.AccessibleName = null; resources.ApplyResources(this.rbFLAC, "rbFLAC"); + this.rbFLAC.BackgroundImage = null; + this.rbFLAC.Font = null; this.rbFLAC.Name = "rbFLAC"; + this.toolTip1.SetToolTip(this.rbFLAC, resources.GetString("rbFLAC.ToolTip")); this.rbFLAC.UseVisualStyleBackColor = true; this.rbFLAC.CheckedChanged += new System.EventHandler(this.rbFLAC_CheckedChanged); // // btnBatch // + this.btnBatch.AccessibleDescription = null; + this.btnBatch.AccessibleName = null; resources.ApplyResources(this.btnBatch, "btnBatch"); + this.btnBatch.BackgroundImage = null; + this.btnBatch.Font = null; this.btnBatch.Name = "btnBatch"; + this.toolTip1.SetToolTip(this.btnBatch, resources.GetString("btnBatch.ToolTip")); this.btnBatch.UseVisualStyleBackColor = true; this.btnBatch.Click += new System.EventHandler(this.btnBatch_Click); // // btnFilenameCorrector // + this.btnFilenameCorrector.AccessibleDescription = null; + this.btnFilenameCorrector.AccessibleName = null; resources.ApplyResources(this.btnFilenameCorrector, "btnFilenameCorrector"); + this.btnFilenameCorrector.BackgroundImage = null; + this.btnFilenameCorrector.Font = null; this.btnFilenameCorrector.Name = "btnFilenameCorrector"; + this.toolTip1.SetToolTip(this.btnFilenameCorrector, resources.GetString("btnFilenameCorrector.ToolTip")); this.btnFilenameCorrector.UseVisualStyleBackColor = true; this.btnFilenameCorrector.Click += new System.EventHandler(this.btnFilenameCorrector_Click); // // btnSettings // + this.btnSettings.AccessibleDescription = null; + this.btnSettings.AccessibleName = null; resources.ApplyResources(this.btnSettings, "btnSettings"); + this.btnSettings.BackgroundImage = null; + this.btnSettings.Font = null; this.btnSettings.Name = "btnSettings"; + this.toolTip1.SetToolTip(this.btnSettings, resources.GetString("btnSettings.ToolTip")); this.btnSettings.UseVisualStyleBackColor = true; this.btnSettings.Click += new System.EventHandler(this.btnSettings_Click); // // grpAccurateRip // + this.grpAccurateRip.AccessibleDescription = null; + this.grpAccurateRip.AccessibleName = null; + resources.ApplyResources(this.grpAccurateRip, "grpAccurateRip"); + this.grpAccurateRip.BackgroundImage = null; this.grpAccurateRip.Controls.Add(this.rbArAndEncode); this.grpAccurateRip.Controls.Add(this.label1); this.grpAccurateRip.Controls.Add(this.txtDataTrackLength); this.grpAccurateRip.Controls.Add(this.rbArApplyOffset); this.grpAccurateRip.Controls.Add(this.rbArVerify); this.grpAccurateRip.Controls.Add(this.rbArNone); - resources.ApplyResources(this.grpAccurateRip, "grpAccurateRip"); + this.grpAccurateRip.Font = null; this.grpAccurateRip.Name = "grpAccurateRip"; this.grpAccurateRip.TabStop = false; + this.toolTip1.SetToolTip(this.grpAccurateRip, resources.GetString("grpAccurateRip.ToolTip")); // // rbArAndEncode // + this.rbArAndEncode.AccessibleDescription = null; + this.rbArAndEncode.AccessibleName = null; resources.ApplyResources(this.rbArAndEncode, "rbArAndEncode"); + this.rbArAndEncode.BackgroundImage = null; + this.rbArAndEncode.Font = null; this.rbArAndEncode.Name = "rbArAndEncode"; this.rbArAndEncode.TabStop = true; + this.toolTip1.SetToolTip(this.rbArAndEncode, resources.GetString("rbArAndEncode.ToolTip")); this.rbArAndEncode.UseVisualStyleBackColor = true; // // label1 // + this.label1.AccessibleDescription = null; + this.label1.AccessibleName = null; resources.ApplyResources(this.label1, "label1"); + this.label1.Font = null; this.label1.Name = "label1"; + this.toolTip1.SetToolTip(this.label1, resources.GetString("label1.ToolTip")); // // txtDataTrackLength // + this.txtDataTrackLength.AccessibleDescription = null; + this.txtDataTrackLength.AccessibleName = null; + resources.ApplyResources(this.txtDataTrackLength, "txtDataTrackLength"); + this.txtDataTrackLength.BackgroundImage = null; this.txtDataTrackLength.Culture = new System.Globalization.CultureInfo(""); this.txtDataTrackLength.CutCopyMaskFormat = System.Windows.Forms.MaskFormat.IncludePromptAndLiterals; + this.txtDataTrackLength.Font = null; this.txtDataTrackLength.InsertKeyMode = System.Windows.Forms.InsertKeyMode.Overwrite; - resources.ApplyResources(this.txtDataTrackLength, "txtDataTrackLength"); this.txtDataTrackLength.Name = "txtDataTrackLength"; this.txtDataTrackLength.TextMaskFormat = System.Windows.Forms.MaskFormat.IncludePromptAndLiterals; this.toolTip1.SetToolTip(this.txtDataTrackLength, resources.GetString("txtDataTrackLength.ToolTip")); // // rbArApplyOffset // + this.rbArApplyOffset.AccessibleDescription = null; + this.rbArApplyOffset.AccessibleName = null; resources.ApplyResources(this.rbArApplyOffset, "rbArApplyOffset"); + this.rbArApplyOffset.BackgroundImage = null; + this.rbArApplyOffset.Font = null; this.rbArApplyOffset.Name = "rbArApplyOffset"; this.toolTip1.SetToolTip(this.rbArApplyOffset, resources.GetString("rbArApplyOffset.ToolTip")); this.rbArApplyOffset.UseVisualStyleBackColor = true; @@ -399,7 +582,11 @@ namespace JDP { // // rbArVerify // + this.rbArVerify.AccessibleDescription = null; + this.rbArVerify.AccessibleName = null; resources.ApplyResources(this.rbArVerify, "rbArVerify"); + this.rbArVerify.BackgroundImage = null; + this.rbArVerify.Font = null; this.rbArVerify.Name = "rbArVerify"; this.toolTip1.SetToolTip(this.rbArVerify, resources.GetString("rbArVerify.ToolTip")); this.rbArVerify.UseVisualStyleBackColor = true; @@ -407,8 +594,12 @@ namespace JDP { // // rbArNone // + this.rbArNone.AccessibleDescription = null; + this.rbArNone.AccessibleName = null; resources.ApplyResources(this.rbArNone, "rbArNone"); + this.rbArNone.BackgroundImage = null; this.rbArNone.Checked = true; + this.rbArNone.Font = null; this.rbArNone.Name = "rbArNone"; this.rbArNone.TabStop = true; this.toolTip1.SetToolTip(this.rbArNone, resources.GetString("rbArNone.ToolTip")); @@ -416,32 +607,44 @@ namespace JDP { // // statusStrip1 // + this.statusStrip1.AccessibleDescription = null; + this.statusStrip1.AccessibleName = null; + resources.ApplyResources(this.statusStrip1, "statusStrip1"); + this.statusStrip1.BackgroundImage = null; + this.statusStrip1.Font = null; this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripStatusLabel1, this.toolStripProgressBar1, this.toolStripProgressBar2}); - resources.ApplyResources(this.statusStrip1, "statusStrip1"); this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.SizingGrip = false; + this.toolTip1.SetToolTip(this.statusStrip1, resources.GetString("statusStrip1.ToolTip")); // // toolStripStatusLabel1 // - this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; + this.toolStripStatusLabel1.AccessibleDescription = null; + this.toolStripStatusLabel1.AccessibleName = null; resources.ApplyResources(this.toolStripStatusLabel1, "toolStripStatusLabel1"); + this.toolStripStatusLabel1.BackgroundImage = null; + this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; this.toolStripStatusLabel1.Spring = true; // // toolStripProgressBar1 // + this.toolStripProgressBar1.AccessibleDescription = null; + this.toolStripProgressBar1.AccessibleName = null; + resources.ApplyResources(this.toolStripProgressBar1, "toolStripProgressBar1"); this.toolStripProgressBar1.AutoToolTip = true; this.toolStripProgressBar1.Name = "toolStripProgressBar1"; - resources.ApplyResources(this.toolStripProgressBar1, "toolStripProgressBar1"); this.toolStripProgressBar1.Style = System.Windows.Forms.ProgressBarStyle.Continuous; // // toolStripProgressBar2 // + this.toolStripProgressBar2.AccessibleDescription = null; + this.toolStripProgressBar2.AccessibleName = null; + resources.ApplyResources(this.toolStripProgressBar2, "toolStripProgressBar2"); this.toolStripProgressBar2.AutoToolTip = true; this.toolStripProgressBar2.Name = "toolStripProgressBar2"; - resources.ApplyResources(this.toolStripProgressBar2, "toolStripProgressBar2"); this.toolStripProgressBar2.Style = System.Windows.Forms.ProgressBarStyle.Continuous; // // toolTip1 @@ -452,66 +655,109 @@ namespace JDP { // // btnCUECreator // + this.btnCUECreator.AccessibleDescription = null; + this.btnCUECreator.AccessibleName = null; resources.ApplyResources(this.btnCUECreator, "btnCUECreator"); + this.btnCUECreator.BackgroundImage = null; + this.btnCUECreator.Font = null; this.btnCUECreator.Name = "btnCUECreator"; + this.toolTip1.SetToolTip(this.btnCUECreator, resources.GetString("btnCUECreator.ToolTip")); this.btnCUECreator.UseVisualStyleBackColor = true; this.btnCUECreator.Click += new System.EventHandler(this.btnCUECreator_Click); // // btnStop // + this.btnStop.AccessibleDescription = null; + this.btnStop.AccessibleName = null; resources.ApplyResources(this.btnStop, "btnStop"); + this.btnStop.BackgroundImage = null; + this.btnStop.Font = null; this.btnStop.Name = "btnStop"; + this.toolTip1.SetToolTip(this.btnStop, resources.GetString("btnStop.ToolTip")); this.btnStop.UseVisualStyleBackColor = true; this.btnStop.Click += new System.EventHandler(this.btnStop_Click); // // btnPause // + this.btnPause.AccessibleDescription = null; + this.btnPause.AccessibleName = null; resources.ApplyResources(this.btnPause, "btnPause"); + this.btnPause.BackgroundImage = null; + this.btnPause.Font = null; this.btnPause.Name = "btnPause"; + this.toolTip1.SetToolTip(this.btnPause, resources.GetString("btnPause.ToolTip")); this.btnPause.UseVisualStyleBackColor = true; this.btnPause.Click += new System.EventHandler(this.btnPause_Click); // // btnResume // + this.btnResume.AccessibleDescription = null; + this.btnResume.AccessibleName = null; resources.ApplyResources(this.btnResume, "btnResume"); + this.btnResume.BackgroundImage = null; + this.btnResume.Font = null; this.btnResume.Name = "btnResume"; + this.toolTip1.SetToolTip(this.btnResume, resources.GetString("btnResume.ToolTip")); this.btnResume.UseVisualStyleBackColor = true; this.btnResume.Click += new System.EventHandler(this.btnPause_Click); // // groupBox1 // + this.groupBox1.AccessibleDescription = null; + this.groupBox1.AccessibleName = null; + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.BackgroundImage = null; this.groupBox1.Controls.Add(this.rbFreedbAlways); this.groupBox1.Controls.Add(this.rbFreedbIf); this.groupBox1.Controls.Add(this.rbFreedbNever); - resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Font = null; this.groupBox1.Name = "groupBox1"; this.groupBox1.TabStop = false; - // - // rbFreedbNever - // - resources.ApplyResources(this.rbFreedbNever, "rbFreedbNever"); - this.rbFreedbNever.Name = "rbFreedbNever"; - this.rbFreedbNever.TabStop = true; - this.rbFreedbNever.UseVisualStyleBackColor = true; - // - // rbFreedbIf - // - resources.ApplyResources(this.rbFreedbIf, "rbFreedbIf"); - this.rbFreedbIf.Name = "rbFreedbIf"; - this.rbFreedbIf.TabStop = true; - this.rbFreedbIf.UseVisualStyleBackColor = true; + this.toolTip1.SetToolTip(this.groupBox1, resources.GetString("groupBox1.ToolTip")); // // rbFreedbAlways // + this.rbFreedbAlways.AccessibleDescription = null; + this.rbFreedbAlways.AccessibleName = null; resources.ApplyResources(this.rbFreedbAlways, "rbFreedbAlways"); + this.rbFreedbAlways.BackgroundImage = null; + this.rbFreedbAlways.Font = null; this.rbFreedbAlways.Name = "rbFreedbAlways"; this.rbFreedbAlways.TabStop = true; + this.toolTip1.SetToolTip(this.rbFreedbAlways, resources.GetString("rbFreedbAlways.ToolTip")); this.rbFreedbAlways.UseVisualStyleBackColor = true; // + // rbFreedbIf + // + this.rbFreedbIf.AccessibleDescription = null; + this.rbFreedbIf.AccessibleName = null; + resources.ApplyResources(this.rbFreedbIf, "rbFreedbIf"); + this.rbFreedbIf.BackgroundImage = null; + this.rbFreedbIf.Font = null; + this.rbFreedbIf.Name = "rbFreedbIf"; + this.rbFreedbIf.TabStop = true; + this.toolTip1.SetToolTip(this.rbFreedbIf, resources.GetString("rbFreedbIf.ToolTip")); + this.rbFreedbIf.UseVisualStyleBackColor = true; + // + // rbFreedbNever + // + this.rbFreedbNever.AccessibleDescription = null; + this.rbFreedbNever.AccessibleName = null; + resources.ApplyResources(this.rbFreedbNever, "rbFreedbNever"); + this.rbFreedbNever.BackgroundImage = null; + this.rbFreedbNever.Font = null; + this.rbFreedbNever.Name = "rbFreedbNever"; + this.rbFreedbNever.TabStop = true; + this.toolTip1.SetToolTip(this.rbFreedbNever, resources.GetString("rbFreedbNever.ToolTip")); + this.rbFreedbNever.UseVisualStyleBackColor = true; + // // frmCUETools // + this.AccessibleDescription = null; + this.AccessibleName = null; resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = null; this.Controls.Add(this.groupBox1); this.Controls.Add(this.btnResume); this.Controls.Add(this.btnPause); @@ -529,8 +775,10 @@ namespace JDP { this.Controls.Add(this.grpCUEPaths); this.Controls.Add(this.btnConvert); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = null; this.MaximizeBox = false; this.Name = "frmCUETools"; + this.toolTip1.SetToolTip(this, resources.GetString("$this.ToolTip")); this.Load += new System.EventHandler(this.frmCUETools_Load); this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmCUETools_FormClosed); this.grpCUEPaths.ResumeLayout(false); diff --git a/CUETools/frmCUETools.cs b/CUETools/frmCUETools.cs index 5356245..2c633bd 100644 --- a/CUETools/frmCUETools.cs +++ b/CUETools/frmCUETools.cs @@ -417,7 +417,8 @@ namespace JDP { CenterSubForm(reportForm); reportForm.ShowDialog(this); } - else if (cueSheet.AccurateRip != AccurateRipMode.None) + else if (cueSheet.AccurateRip == AccurateRipMode.Verify || + (cueSheet.AccurateRip != AccurateRipMode.None && outputFormat != OutputAudioFormat.NoAudio)) { frmReport reportForm = new frmReport(); StringWriter sw = new StringWriter(); @@ -488,6 +489,7 @@ namespace JDP { grpAudioOutput.Enabled = !running && !rbArVerify.Checked; grpAccurateRip.Enabled = !running; grpOutputStyle.Enabled = !running && !rbArVerify.Checked; + groupBox1.Enabled = !running && !rbArVerify.Checked; txtDataTrackLength.Enabled = !running && !rbArNone.Checked; btnAbout.Enabled = !running; btnSettings.Enabled = !running; diff --git a/CUETools/frmCUETools.de-DE.resx b/CUETools/frmCUETools.de-DE.resx index 08eaf73..1be9683 100644 --- a/CUETools/frmCUETools.de-DE.resx +++ b/CUETools/frmCUETools.de-DE.resx @@ -145,22 +145,22 @@ + + 49, 13 + E&ingabe: - - - 62, 48 382, 21 - + @@ -169,6 +169,9 @@ 382, 21 + + + CUE-Pfade @@ -448,15 +451,33 @@ + + 55, 17 + Immer + + + + + 80, 17 + Wenn nötig + + + + + 40, 17 + Nie + + + FreeDB-Abfrage diff --git a/CUETools/frmCUETools.resx b/CUETools/frmCUETools.resx index 9ebf314..fec317e 100644 --- a/CUETools/frmCUETools.resx +++ b/CUETools/frmCUETools.resx @@ -117,1411 +117,1531 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 412, 339 + + - - 131, 23 + + + + + + 54, 21 + + + + + + 00:00:00 + + + 226, 21 + + + 226, 21 - - 5 + + 14 - - &Go + + toolTip1 - - btnConvert + + 59, 17 - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 4 - - $this - - - 15 - - - 452, 49 - - - 71, 23 - - - 5 - - - Browse... - - - btnBrowseOutput - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpCUEPaths + + rbGapsLeftOut 0 - - 452, 20 + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 71, 23 + + + NoControl - - 2 - - - Browse... - - - btnBrowseInput - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpCUEPaths - - + 1 - - True + + btnPause - - 8, 52 - - - 45, 13 - - + 3 - - &Output: - - - lblOutput + + grpOutputPathGeneration System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - grpCUEPaths + + 9 - - 2 + + 66, 23 - - True + + Gaps Left Out - - 8, 24 + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 37, 13 + + grpOutputStyle - + + %1:-2\New\%-1\%F.cue + + + groupBox1 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + grpOutputPathGeneration + + + 4 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 77, 138 + + + 10 + + 0 - - &Input: + + 0 + + + 398, 115 + + + grpAccurateRip + + + 2 + + + CenterScreen + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 552, 400 + + + 0 + + + btnAbout + + + 5 + + + rbEmbedCUE + + + + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 lblInput - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + btnResume - - grpCUEPaths + + 1 + + + LossyWAV + + + 3 + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + btnBrowseInput + + + True + + + 15 + + + txtCreateSubdirectory + + + 5 + + + + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 6 3 - - 59, 48 + + rbWavPack + + + chkLossyWAV + + + Browse... + + + False + + + Create a pair of files - .lossy.wav(flac,etc) and .lwcdf.wav(flac,etc). Lossy file contains (lossy) compressed music, but together with the lwcdf (correction) file the original audio can be reconstructed. + + + 0 + + + btnConvert + + + 452, 49 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + $this + + + Batch... + + + 3 + + + Verify, &then encode + + + 15 + + + rbArVerify + + + 1 + + + Create single file with embedded CUE sheet. + + + + + + 535, 84 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 11 + + + rbAPE + + + Append to filename: + + + $this + + + rbGapsPrepended + + + + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + rbGapsAppended + + + grpAccurateRip + + + 244, 211 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 2 + + + 552, 22 + + + NoControl + + + Encode and verify + + + frmCUETools + + + 3 + + + grpOutputPathGeneration + + + True + + + True + + + NoControl + + + $this + + + &Pause + + + &None + + + 7 + + + 122, 17 + + + True + + + 3 + + + btnBrowseOutput + + + + + + 4 + + + 6 + + + Advanced Settings... + + + 8, 24 + + + 412, 277 + + + 4 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + + + + 1 + + + rbDontGenerate 385, 21 + + True + + + grpAudioOutput + + + + + + 0 + + + 66, 23 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + btnFilenameCorrector + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 71, 23 + + + CUE Paths + + + If needed + + + 131, 23 + + + True + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + $this + + + grpAudioOutput + + + 3 + + + $this + + + grpCUEPaths + + + 10, 51 + + + &WAV + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 412, 184 + + + btnStop + + + + + + 5 + + + 10, 102 + + + True + + + 131, 23 + + + True + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + + 452, 20 + + + btnSettings + + + + + + $this + + + NoControl + 4 + + + + + System.Windows.Forms.MaskedTextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + CUE Sheet Creator... + + + 50, 17 + + + 2 + + + grpAccurateRip + + + &Stop + + + Wav&Pack + + + 123, 17 + + + NoControl + + + 2 + + + &Manual + + + 8, 4 + + + + + + grpOutputStyle + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + rbSingleFile + + + + + + Create multiple files with gaps left out + + + 5 + + + System.Windows.Forms.StatusStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + Tahoma, 8.25pt + + + &Output: + + + 8, 52 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + grpOutputPathGeneration + + + 10, 66 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 92, 164 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + 5 + + + Track progress + + + True + + + 5 + + + APE + + + Filename Corrector... + + + 104, 17 + + + grpOutputPathGeneration + + + 10, 34 + + + Not used for normal music CDs. Enhanced CDs with data tracks cannot be found in database unless you know the length of the data track. You can often find it in EAC log. If EAC log is found next to the CUE sheet, it will be parsed automaticly and you won't have to enter anything here. + + + 0 + + + 162, 164 + + + + + + False + + + 69, 17 + + + True + + + grpOutputPathGeneration + + + 1 + + + grpAudioOutput + + + 1 + + + 13 + + + $this + + + About + + + lblOutput + + + grpOutputStyle + + + &Go + + + txtInputPath + + + 44, 17 + + + 412, 339 + + + Freedb lookup + + + Always + + + 0, 378 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + AccurateRip + + + 412, 215 + + + grpOutputStyle + + + btnCUECreator + + + 44, 17 + + + 8, 211 + + + 10, 71 + + + rbFreedbAlways + + + &Single File + CUE + + + 10, 89 + + + 5 + + + 131, 86 + + + + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + C&reate subdirectory: + + + Browse... + + + + + + 2 + + + 4 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 166, 18 + + + 0 + + + 412, 339 + + + 125, 17 + + + grpAudioOutput + + + txtCustomFormat + + + 412, 308 + + + $this + + + 45, 13 + + + 66, 23 + + + 1 + + + grpOutputPathGeneration + + + statusStrip1 + + + 412, 92 + + + + + + + + + System.Windows.Forms.ToolStripProgressBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 120, 17 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + rbWAV + + + Create single file + CUE sheet + + + + + + 10, 20 + + + 92, 17 + + + 6 + + + 1 + + + 131, 23 + + + 8, 92 + + + Disk progress + + + TTA + + + True + + + grpAccurateRip + + + True + + + &FLAC + + + Output Path + + + + + + True + + + + + + 0 + + + 106, 17 + + + 72, 17 + + + 59, 22 + + + + + + $this + + + 0 + + + grpAudioOutput + + + rbFreedbIf + + + True + + + Create multiple files with gaps appended + + + New + + + + + + 6 + + + 5 + + + + + + 54, 17 + + + 140, 16 + + + + + + $this + txtOutputPath + + 6 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 166, 39 + + + txtAppendFilename + + + True + + + 477, 339 + + + Contact the AccurateRip databse for validation and compare the image against database + + + 11, 87 + + + System.Windows.Forms.ToolStripProgressBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 140, 16 + + + System.Windows.Forms.ToolTip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + + + + 4 + + + 6, 53 + + + 1 + + + grpOutputStyle + + + True + + + 6, 13 + + + grpAccurateRip + + + 10, 68 + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 grpCUEPaths - - 4 - - - 59, 22 - - - 385, 21 - - - 1 - - - txtInputPath - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpCUEPaths - - - 5 - - - 8, 4 - - - 535, 84 - - - 0 - - - CUE Paths - - - grpCUEPaths - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 14 - - - True - - - - NoControl - - - 11, 19 - - - 75, 17 - - - 0 - - - &Embedded - - - 153, 8 - - - Create single file with embedded CUE sheet. - - - rbEmbedCUE - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputStyle - - - 0 - - - True - - - 11, 87 - - - 92, 17 - - - 4 - - - Gaps Left Out - - - Create multiple files with gaps left out - - - rbGapsLeftOut - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputStyle - - - 1 - - - True - - - 11, 70 - - - 104, 17 - - - 3 - - - Gaps Prepended - - - Create multiple files with gaps prepended - - - rbGapsPrepended - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputStyle - - - 2 - - - True - - - 11, 53 - - - 101, 17 - - - 2 - - - Gaps &Appended - - - Create multiple files with gaps appended - - - rbGapsAppended - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputStyle - - - 3 - - - True - - - 11, 36 - - - 106, 17 - - - 1 - - - &Single File + CUE - - - Create single file + CUE sheet - - - rbSingleFile - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputStyle - - - 4 - - - 108, 211 - - - 128, 164 - - - 3 - - - CUE Style - - - grpOutputStyle - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 13 - - - 412, 184 - - - 131, 23 - - - 10 - - - About - - - btnAbout - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 12 - - - 166, 60 - - - 226, 21 - - - 5 - - - %1:-2\New\%-1\%F.cue - - - txtCustomFormat - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputPathGeneration - - - 0 - - - True - - - 10, 66 - - - 119, 17 - - - 4 - - - Use custom format: - - - rbCustomFormat - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputPathGeneration - - - 1 - - - 166, 18 - - - 226, 21 - - - 1 - - - New - - - txtCreateSubdirectory - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputPathGeneration - - - 2 - - - True - - - 10, 89 - - - 59, 17 - - - 6 - - - &Manual - - - rbDontGenerate - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputPathGeneration - - - 3 - - - True - - - 10, 20 - - - 125, 17 - - - 0 - - - C&reate subdirectory: - - - rbCreateSubdirectory - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputPathGeneration - - - 4 - - - True - - - 10, 43 - - - 122, 17 - - - 2 - - - Append to filename: - - - rbAppendFilename - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputPathGeneration - - - 5 - - - 166, 39 - - - 226, 21 - - - 3 - - - -New - - - txtAppendFilename - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpOutputPathGeneration - - - 6 - - - 8, 92 - - - 398, 115 - - - 1 - - - Output Path - - - grpOutputPathGeneration - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 11 - - - True - - - 10, 68 - - - 44, 17 - - - 6 - - - TTA - - - rbTTA - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAudioOutput - - - 0 + + 7, 141 True + + 0 + + + -New + + + + + + 122, 17 + 6, 141 - - 76, 17 - - - 5 - - - LossyWAV - - - Create a pair of files - .lossy.wav(flac,etc) and .lwcdf.wav(flac,etc). Lossy file contains (lossy) compressed music, but together with the lwcdf (correction) file the original audio can be reconstructed. - - - chkLossyWAV - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAudioOutput - - - 1 - - - True - - - 10, 51 - - - 44, 17 - - - 2 - - - APE - - - rbAPE - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAudioOutput - - - 2 - - - True - - - 10, 102 - - - 50, 17 - - - 4 - - - &None - - - Don't create any audio files, only CUE sheet - - - rbNoAudio - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAudioOutput - - - 3 - - - True - - - 10, 34 - - - 69, 17 - - - 1 - - - Wav&Pack - - - rbWavPack - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAudioOutput - - - 4 - - - True - - - 10, 85 - - - 48, 17 - - - 3 - - - &WAV - - - rbWAV - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAudioOutput - - - 5 - - - True - - - 10, 17 - - - 50, 17 - - - 0 - - - &FLAC - - - rbFLAC - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAudioOutput - - - 6 - - - 8, 211 - - - 92, 164 - - - 2 - - - Audio Output - - - grpAudioOutput - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 10 - - - 412, 308 - - - 131, 23 - - - 6 - - - Batch... - - - btnBatch - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 9 - - - 412, 277 - - - 131, 23 - - - 7 - - - Filename Corrector... - - - btnFilenameCorrector - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 8 - - - 412, 215 - - - 131, 23 - - - 9 - - - Advanced Settings... - - - btnSettings - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 7 - - - True - - - 10, 37 - - - 112, 17 - - - 5 - - - Encode and verify - - - rbArAndEncode - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAccurateRip - - - 0 - - - True - - - 7, 141 - - - 61, 13 - - - 3 - - - Data track: + + 11, 19 label1 - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + rbTTA - - grpAccurateRip + + 10, 43 - - 1 - - - 77, 138 - - - 00:00:00 - - - 0 - - - 54, 21 - - - 4 - - - Not used for normal music CDs. Enhanced CDs with data tracks cannot be found in database unless you know the length of the data track. You can often find it in EAC log. If EAC log is found next to the CUE sheet, it will be parsed automaticly and you won't have to enter anything here. - - - txtDataTrackLength - - - System.Windows.Forms.MaskedTextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAccurateRip - - - 2 - - - True - - - 10, 20 - - - 120, 17 - - - 0 - - - Verify, &then encode - - - On the first pass, verify and try to find an offset correction which makes the rip accurate according to the AccurateRip database. On the second pass, convert, possibly applying offset correction. - - - rbArApplyOffset - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAccurateRip - - - 3 - - - True - - - 10, 71 - - - 122, 17 - - - 2 - - - &Verify, don't encode - - - Contact the AccurateRip databse for validation and compare the image against database - - - rbArVerify - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAccurateRip - - - 4 - - - True + + 7 10, 54 - - 123, 17 - - - 1 - - - &Don't verify, encode - - - Don't contact the AccurateRip database for validation - - - rbArNone - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - grpAccurateRip - - - 5 - - - 244, 211 - - - 162, 164 - - - 4 - - - AccurateRip - - - grpAccurateRip - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 6 - - - 0, 378 - 253, 17 - - MiddleLeft - - - 140, 16 - - - Track progress - - - 140, 16 - - - Disk progress - - - 0, 378 - - - 552, 22 - - - 11 - - - statusStrip1 - - - statusStrip1 - - - System.Windows.Forms.StatusStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 5 - - - NoControl - - - 412, 246 - - - 131, 23 - - - 8 - - - CUE Sheet Creator... - - - btnCUECreator - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 4 - - - NoControl - - - 412, 339 - - - 66, 23 - - - 12 - - - &Stop - - - False - - - btnStop - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - - - NoControl - - - 477, 339 - - - 66, 23 - - - 13 - - - &Pause - - - False - - - btnPause - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 - - - NoControl - - - 477, 339 - - - 66, 23 - - - 14 + + Data track: &Resume - - False + + 76, 17 - - btnResume + + 8 - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Don't create any audio files, only CUE sheet - - $this + + - + + grpAudioOutput + + 1 - - True + + - - 6, 53 - - - 59, 17 - - + 2 - - Always + + 13 - - rbFreedbAlways + + grpAccurateRip - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 226, 21 - - groupBox1 + + rbCustomFormat - - 0 + + 61, 13 - - True + + grpAccurateRip - - 6, 36 - - - 72, 17 - - - 1 - - - If needed - - - rbFreedbIf - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox1 - - - 1 - - - True - - - 6, 19 - - - 54, 17 - - - 0 - - - Never + + Audio Output rbFreedbNever - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 128, 164 - - groupBox1 + + rbAppendFilename - + + Create multiple files with gaps prepended + + 2 - - 412, 92 + + Use custom format: - - 131, 86 + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 15 + + 37, 13 - - Freedb lookup + + 3 - - groupBox1 + + 3 + + + statusStrip1 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + On the first pass, verify and try to find an offset correction which makes the rip accurate according to the AccurateRip database. On the second pass, convert, possibly applying offset correction. + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + &Verify, don't encode + + + 6, 36 + + + 4 + + + 10, 20 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 166, 60 + + + grpOutputStyle + + + CUE Style + + + 131, 23 + + + rbArApplyOffset + + + $this System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + - + + True + + + grpCUEPaths + + + rbArNone + + + 101, 17 + + + 10, 37 + + 0 - - True - - - 6, 13 + + 1 - - 552, 400 + + 11 - - Tahoma, 8.25pt + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - CenterScreen + + 0 + + + grpOutputPathGeneration + + + 8 + + + 11, 53 + + + grpCUEPaths + + + 3 + + + grpAudioOutput CUE Tools - - toolStripStatusLabel1 + + grpCUEPaths - - System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + $this - - toolStripProgressBar1 - - - System.Windows.Forms.ToolStripProgressBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + $this toolStripProgressBar2 - - System.Windows.Forms.ToolStripProgressBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - toolTip1 + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.ToolTip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 5 - - frmCUETools + + True - - System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 385, 21 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &Embedded + + + 6 + + + 2 + + + 10, 17 + + + 4 + + + toolStripProgressBar1 + + + + + + Never + + + 131, 23 + + + 2 + + + 11, 70 + + + True + + + + + + 75, 17 + + + 0 + + + 3 + + + 5 + + + MiddleLeft + + + + + + 48, 17 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Don't contact the AccurateRip database for validation + + + Gaps Prepended + + + &Input: + + + 1 + + + toolStripStatusLabel1 + + + Gaps &Appended + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 10 + + + grpCUEPaths + + + 119, 17 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 131, 23 + + + 11, 36 + + + &Don't verify, encode + + + 412, 246 + + + 71, 23 + + + rbArAndEncode + + + 4 + + + 50, 17 + + + rbNoAudio + + + 4 + + + True + + + btnBatch + + + grpCUEPaths + + + rbFLAC + + + $this + + + 112, 17 + + + grpAudioOutput + + + $this + + + 6, 19 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + 12 + + + 12 + + + 9 + + + 14 + + + rbCreateSubdirectory + + + 477, 339 + + + True + + + 108, 211 + + + 3 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 59, 17 + + + txtDataTrackLength + + + 10, 85 + + + groupBox1 + + + + + + 59, 48 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 153, 8 + + + True + + + 0, 378 + \ No newline at end of file diff --git a/HDCDDotNet/HDCDDotNet.cs b/HDCDDotNet/HDCDDotNet.cs index 4c974c1..4a53436 100644 --- a/HDCDDotNet/HDCDDotNet.cs +++ b/HDCDDotNet/HDCDDotNet.cs @@ -28,19 +28,20 @@ namespace HDCDDotNet public class HDCDDotNet { - public HDCDDotNet (Int16 channels, Int32 sample_rate, Int32 output_bps, bool decode) + public HDCDDotNet (int channels, int sample_rate, int output_bps, bool decode) { _decoder = IntPtr.Zero; #if !MONO _decoder = hdcd_decoder_new(); _channelCount = channels; + _bitsPerSample = output_bps; if (_decoder == IntPtr.Zero) throw new Exception("Failed to initialize HDCD decoder."); bool b = true; - b &= hdcd_decoder_set_num_channels(_decoder, channels); + b &= hdcd_decoder_set_num_channels(_decoder, (short) _channelCount); b &= hdcd_decoder_set_sample_rate(_decoder, sample_rate); b &= hdcd_decoder_set_input_bps(_decoder, 16); - b &= hdcd_decoder_set_output_bps(_decoder, (short) output_bps); + b &= hdcd_decoder_set_output_bps(_decoder, (short)_bitsPerSample); if (!b) throw new Exception("Failed to set up HDCD _decoder parameters."); _decoderCallback = decode ? new hdcd_decoder_write_callback(DecoderCallback) : null; @@ -76,6 +77,14 @@ namespace HDCDDotNet } } + public bool Decoding + { + get + { + return _decoderCallback != null; + } + } + public int Channels { get @@ -84,6 +93,14 @@ namespace HDCDDotNet } } + public int BitsPerSample + { + get + { + return _bitsPerSample; + } + } + public void Reset() { #if !MONO @@ -184,7 +201,7 @@ namespace HDCDDotNet private IntPtr _decoder; private int[,] _inSampleBuffer; private int[,] _outSampleBuffer; - private int _channelCount; + private int _channelCount, _bitsPerSample; hdcd_decoder_write_callback _decoderCallback; IAudioDest _audioDest; GCHandle _gch; diff --git a/LossyWAVSharp/LossyWAVSharp.csproj b/LossyWAVSharp/LossyWAVSharp.csproj index 6dbddbb..d514f50 100644 --- a/LossyWAVSharp/LossyWAVSharp.csproj +++ b/LossyWAVSharp/LossyWAVSharp.csproj @@ -81,14 +81,14 @@ - - {6458A13A-30EF-45A9-9D58-E5031B17BEE2} - CUETools.Codecs - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19} CUETools.Codecs.LossyWAV + + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} + CUETools.Codecs +