Compare commits
4 Commits
1e76df7e59
...
community
Author | SHA1 | Date | |
---|---|---|---|
|
5b91e3f697 | ||
|
9c7f91496c | ||
|
ffeccedefa | ||
|
e721b2e039 |
109
LICENSE.md
@@ -1,76 +1,79 @@
|
||||
# Winamp Collaborative License (WCL) Version 2.0
|
||||
# Winamp Collaborative License (WCL) Version 1.0.1
|
||||
|
||||
This License governs the use, modification, and distribution of the Winamp software.
|
||||
By using, Modifying, or distributing this software, you agree to the following terms:
|
||||
|
||||
**Preamble:**
|
||||
## Preamble
|
||||
The Winamp Collaborative License is a free, copyleft license for software and other kinds of works. It is designed to ensure that you have the freedom to use, Modify, and study the software, but with certain restrictions on the distribution of modifications to maintain the integrity and collaboration of the project.
|
||||
|
||||
The "Winamp Collaborative License" (WCL) is designed to provide the appearance of open participation while ensuring strict control over the use, modification, and distribution of the software. Though the code is available for viewing, it remains under tight restrictions, and all contributions are subject to the full ownership of the original licensor. The following terms and conditions emphasize non-negotiable exclusivity while maintaining the outward appearance of freedom and collaboration.
|
||||
## TERMS AND CONDITIONS
|
||||
|
||||
---
|
||||
### 1. Definitions
|
||||
- "This License" refers to version 1.0.1 of the Winamp Collaborative License.
|
||||
- "The Program" refers to any copyrightable work Licensed under this License.
|
||||
- "You" refers to each Licensee, whether an individual or organization.
|
||||
- "Modify" means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy.
|
||||
- "Covered Work" means either the unmodified Program or a work based on the Program.
|
||||
- "Convey" means any kind of propagation that enables other parties to make or receive copies.
|
||||
|
||||
**Section 1: Grant of Limited Non-Exclusive Non-Transferable License**
|
||||
### 2. Basic Permissions
|
||||
All rights granted under this License are granted for the term of copyright on the Program and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a Covered work is covered by this License only if its contents constitute a Covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You are granted a non-exclusive, non-transferable license to view the source code, but only for personal observation. You may not copy, modify, compile, or distribute the code in any form. Your "use" is limited to passive admiration, as if you were holding a priceless artifact behind glass.
|
||||
### 3. Grant of License
|
||||
You are granted the right to view, access, and study the source code of the software.
|
||||
You are granted the right to Modify the software for private use only. You may make, run, and propagate Covered works that you do not Convey, without conditions, so long as your License otherwise remains in force.
|
||||
|
||||
**Section 2: Community Contributions**
|
||||
### 4. Contributions
|
||||
- Contribution to Project: You are encouraged to contribute improvements, enhancements, and bug fixes back to the project. Contributions must be submitted to the official repository and will be reviewed and incorporated at the discretion of the maintainers.
|
||||
- Assignment of Rights: By submitting contributions, you agree that all intellectual property rights, including copyright, in your contributions are assigned to Winamp. You hereby grant Winamp a perpetual, worldwide, non-exclusive, royalty-free license to use, copy, modify, and distribute your contributions as part of the software, without any compensation to you.
|
||||
- Waiver of Rights: You waive any rights to claim authorship of the contributions or to object to any distortion, mutilation, or other modifications of the contributions.
|
||||
|
||||
Contributions are welcomed, provided you immediately and irrevocably assign all rights, including patents, to the original licensor. You waive any rights to your contribution, which becomes the sole property of the licensor. Whether or not credit is given for your contribution is at the licensor’s discretion. Your role is to give freely, not to receive recognition.
|
||||
### 5. Restrictions
|
||||
- No Distribution of Modified Versions: You may not distribute modified versions of the software, whether in source or binary form.
|
||||
- Official Distribution: Only the maintainers of the official repository are allowed to distribute the software and its modifications.
|
||||
|
||||
**Section 3: Forking is Strictly Prohibited**
|
||||
### 6. No Sublicensing
|
||||
Sublicensing is not allowed; section 5 makes it unnecessary.
|
||||
|
||||
Forking, cloning, or creating derivative works of the source code is strictly forbidden. You may gaze at the code, but any attempt to duplicate it—even in a hypothetical alternate reality—will be treated as a violation of this license. The WCL License takes exclusivity seriously.
|
||||
### 7. Protecting Users' Legal Rights From Anti-Circumvention Law
|
||||
|
||||
**Section 4: Distribution Without Distribution**
|
||||
No Covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
|
||||
|
||||
Though the software is available to you in source form, any attempt to distribute it is a breach of this license. Sharing it in any form—whether digitally, physically, or through casual conversation—will result in immediate termination of your rights. The WCL License rejects sharing in all forms.
|
||||
### 8. Disclaimer of Warranty
|
||||
The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
|
||||
|
||||
**Section 5: Personal Use Only**
|
||||
### 9. Limitation of Liability
|
||||
In no event will the authors or copyright holders be liable for any special, incidental, indirect, or consequential damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of or inability to use the software, even if the authors or copyright holders have been advised of the possibility of such damages.
|
||||
|
||||
The software is for personal, non-productive use only. You may not use it for commercial, public, educational, or any other form of productive engagement. The code is provided for quiet contemplation only, and all other uses are expressly prohibited.
|
||||
### 10. Termination
|
||||
This License and the rights granted hereunder will terminate automatically if you fail to comply with the terms and conditions herein. Upon termination, you must cease all use of the software and destroy all copies, full or partial, of the software.
|
||||
|
||||
**Section 6: Contributions for the Licensor's Exclusive Benefit**
|
||||
### 11. Protection of Copyright
|
||||
The original authors or copyright holders of the software retain all rights, title, and interest in the software. This license does not transfer any ownership rights.
|
||||
You must retain all copyright, patent, trademark, and attribution notices in the source code and documentation of the software.
|
||||
By submitting contributions, you agree that the contributions are your original work and you grant the project a perpetual, worldwide, non-exclusive, royalty-free license to use, copy, modify, and distribute your contributions as part of the software.
|
||||
Any unauthorized use, reproduction, or distribution of the software, or any portion thereof, may result in civil and criminal penalties.
|
||||
|
||||
Any contributions you make will be used solely at the licensor’s discretion. You may not use or reclaim your own contributions in other projects, as they immediately become the licensor's property. The WCL License ensures that contributions benefit the original licensor exclusively.
|
||||
### 12. Patent Rights
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims to make, use, sell, offer for sale, import, and otherwise run, modify and propagate the contents of its contributor version.
|
||||
If you initiate litigation (including a cross-claim or counterclaim) against any party alleging that the Program or a contribution incorporated within the Program constitutes direct or contributory patent infringement, then any patent licenses granted to you under this License for that Program shall terminate as of the date such litigation is filed.
|
||||
|
||||
**Section 7: No Reverse Engineering or Decompilation**
|
||||
### 13. Trademark Usage
|
||||
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for describing the origin of the Program and reproducing the content of the copyright notice.
|
||||
|
||||
You may not reverse-engineer, decompile, disassemble, or attempt to understand the internal workings of the software. Any effort to reconstruct or replicate the software, even for educational purposes, is strictly prohibited under the WCL License.
|
||||
### 14. Privacy and Data Protection
|
||||
You must comply with all applicable privacy and data protection laws in connection with your use of the Program.
|
||||
If the Program collects user data, you must provide clear notice and obtain any necessary consents for such collection.
|
||||
|
||||
**Section 8: Non-Use of Trademarks and Logos**
|
||||
### 15. Support and Updates
|
||||
The Licensor has no obligation to provide support, updates, or maintenance for the Program. Any such support, updates, or maintenance will be provided at the sole discretion of the Licensor.
|
||||
|
||||
All trademarks, logos, and branding associated with this software are the exclusive property of the licensor. You may not use or reference them in any context without written permission. The WCL License grants no freedom in this regard.
|
||||
### 16. Compliance
|
||||
You must comply with all applicable laws and regulations in connection with your use of the Program.
|
||||
|
||||
**Section 9: Waiver of Rights (Known and Unknown)**
|
||||
|
||||
By using or contributing to this software, you irrevocably waive all rights, claims, and legal entitlements to the software, including intellectual property rights and potential future claims. The licensor retains all rights, while you retain none.
|
||||
|
||||
**Section 10: Termination of Rights**
|
||||
|
||||
Your rights under this license terminate immediately upon any breach of its terms, including unauthorized copying, modifying, or distributing the software. Upon termination, you must delete all copies of the software and cease all further use. The WCL License does not permit second chances.
|
||||
|
||||
---
|
||||
|
||||
**Section 11: Prohibition on Automated Tools**
|
||||
|
||||
The use of automated tools, scripts, or bots to interact with the software or its repository is strictly forbidden. Any attempt to automate interaction with the codebase, even for benign purposes, will result in immediate revocation of all rights. The WCL License requires that you engage with the software personally, without the assistance of machines.
|
||||
|
||||
**Section 12: Restrictions on Code Fragments and Snippets**
|
||||
|
||||
No part of the software—whether a complete file or a single line—may be copied, shared, or used elsewhere. This includes code snippets shared in tutorials, blog posts, or casual conversations. The WCL License prohibits even the smallest fragment of the code from leaving its carefully controlled environment.
|
||||
|
||||
**Section 13: No Public Performance or Display**
|
||||
|
||||
You may not display or demonstrate this software publicly in any form, including presentations, videos, or live demonstrations. Any public exhibition of the software or its functionality, even with the best of intentions, is a violation of the WCL License. If you wish to discuss the software, you may do so only in abstract, non-specific terms.
|
||||
|
||||
---
|
||||
|
||||
**Section 14: Applying the WCL License to Your Own Codebase**
|
||||
|
||||
To apply the WCL License to your own project, include the following notice at the top of each file:
|
||||
|
||||
```plaintext
|
||||
This code is licensed under the "Winamp Collaborative License" (WCL). By viewing or interacting with this file, you agree to the terms of the WCL License, which prohibits copying, modifying, forking, compiling, or distributing this code. All contributions are irrevocably assigned to the original licensor, with no rights retained by the contributor. For full terms, see https://github.com/WinampDesktop/winamp/blob/community/LICENSE.md.
|
||||
```
|
||||
|
||||
This ensures that your code remains governed by the principles of limited participation, strict control, and exclusive ownership. By adopting the WCL License, you secure a license that promotes engagement while safeguarding your rights to the fullest extent.
|
||||
### 17. Miscellaneous
|
||||
- Governing Law and Jurisdiction: This License shall be governed by and construed in accordance with the laws of Belgium. Any disputes arising out of or in connection with this License shall be subject to the exclusive jurisdiction of the courts located in Brussels, Belgium.
|
||||
- Severability: If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
|
||||
By using, Modifying, or contributing to the software, you acknowledge that you have read, understood, and agree to be bound by these terms and conditions.
|
||||
|
||||
This custom License aims to maintain the collaborative nature of the project while restricting the distribution of modified versions.
|
||||
|
@@ -16,6 +16,10 @@ Building of the Winamp desktop client is currently based around Visual Studio 20
|
||||
|
||||
### Dependencies
|
||||
|
||||
#### libdiscid
|
||||
|
||||
We take libdiscid from https://github.com/metabrainz/libdiscid/tree/v0.6.2, copy it in /Src/external_dependencies/libdiscid-0.6.2/
|
||||
|
||||
#### libvpx
|
||||
|
||||
We take libvpx from [https://github.com/ShiftMediaProject/libvpx](https://github.com/ShiftMediaProject/libvpx), modify it, and pack it to archive.
|
||||
|
@@ -1,67 +0,0 @@
|
||||
#include "DlgBase.h"
|
||||
|
||||
void DlgBase::MakeComboEdit(UINT id, DWORD s)
|
||||
{
|
||||
HWND w = GetDlgItem(wnd, id);
|
||||
RECT r;
|
||||
GetChildRect(id, r);
|
||||
DestroyWindow(w);
|
||||
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", 0, WS_CHILD | s, r.left - 1, r.top - 1, r.right - r.left, r.bottom - r.top, wnd, (HMENU)id, 0, 0);
|
||||
}
|
||||
|
||||
void DlgBase::GetChildRect(UINT id, RECT& child)
|
||||
{
|
||||
RECT r_parent, r_child;
|
||||
GetWindowRect(wnd, &r_parent);
|
||||
GetWindowRect(GetDlgItem(wnd, id), &r_child);
|
||||
int dx = r_parent.left;
|
||||
int dy = r_parent.top;
|
||||
if (!(GetWindowLong(wnd, GWL_STYLE)&WS_CHILD))
|
||||
{
|
||||
dy += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME);
|
||||
dx += GetSystemMetrics(SM_CXDLGFRAME);
|
||||
}
|
||||
child.left = r_child.left - dx;
|
||||
child.right = r_child.right - dx;
|
||||
child.top = r_child.top - dy;
|
||||
child.bottom = r_child.bottom - dy;
|
||||
}
|
||||
|
||||
void DlgBase::do_sizing(UINT wp, RECT * r)
|
||||
{
|
||||
UINT dx, dy;
|
||||
dx = r->right - r->left;
|
||||
dy = r->bottom - r->top;
|
||||
if (dx < min_size_x_w)
|
||||
{
|
||||
switch (wp)
|
||||
{
|
||||
case WMSZ_BOTTOMLEFT:
|
||||
case WMSZ_LEFT:
|
||||
case WMSZ_TOPLEFT:
|
||||
r->left = r->right - min_size_x_w;
|
||||
break;
|
||||
case WMSZ_BOTTOMRIGHT:
|
||||
case WMSZ_RIGHT:
|
||||
case WMSZ_TOPRIGHT:
|
||||
r->right = r->left + min_size_x_w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dy < min_size_y_w)
|
||||
{
|
||||
switch (wp)
|
||||
{
|
||||
case WMSZ_BOTTOMLEFT:
|
||||
case WMSZ_BOTTOM:
|
||||
case WMSZ_BOTTOMRIGHT:
|
||||
r->bottom = r->top + min_size_y_w;
|
||||
break;
|
||||
case WMSZ_TOPLEFT:
|
||||
case WMSZ_TOP:
|
||||
case WMSZ_TOPRIGHT:
|
||||
r->top = r->bottom - min_size_y_w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,118 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "main.h"
|
||||
|
||||
static void SetWindowRect(HWND w, RECT * r)
|
||||
{
|
||||
SetWindowPos(w, 0, r->left, r->top, r->right - r->left, r->bottom - r->top, SWP_NOZORDER | SWP_NOCOPYBITS);
|
||||
}
|
||||
|
||||
class DlgBase
|
||||
{
|
||||
public:
|
||||
BOOL isDialogMessage(MSG * m)
|
||||
{
|
||||
return wnd ? IsDialogMessage(wnd, m) : 0;
|
||||
}
|
||||
protected:
|
||||
void endDialog(int x)
|
||||
{
|
||||
EndDialog(wnd, x);
|
||||
}
|
||||
|
||||
void _do_size_x(RECT * r, UINT id, UINT wx, UINT min_x)
|
||||
{
|
||||
RECT r1 = {r->left, r->top, wx - min_x + r->right, r->bottom};
|
||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
||||
}
|
||||
|
||||
void _do_size_xy(RECT * r, UINT id, UINT wx, UINT wy, UINT min_x, UINT min_y)
|
||||
{
|
||||
RECT r1 = {r->left, r->top, wx - min_x + r->right, wy - min_y + r->bottom};
|
||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
||||
}
|
||||
|
||||
void _do_align_x_size_y(RECT * r, UINT id, UINT wx, UINT wy, UINT min_x, UINT min_y)
|
||||
{
|
||||
RECT r1 = {wx - min_x + r->left, r->top, wx - min_x + r->right, wy - min_y + r->bottom};
|
||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
||||
}
|
||||
|
||||
void _do_align_x(RECT * r, UINT id, UINT wx, UINT min_x)
|
||||
{
|
||||
RECT r1 = {wx - min_x + r->left, r->top, wx - min_x + r->right, r->bottom};
|
||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
||||
}
|
||||
|
||||
void _do_align_xy(RECT * r, UINT id, UINT wx, UINT wy, UINT min_x, UINT min_y)
|
||||
{
|
||||
RECT r1 = {wx - min_x + r->left, wy - min_y + r->top, wx - min_x + r->right, wy - min_y + r->bottom};
|
||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
||||
}
|
||||
|
||||
#define do_size_x(id,r) _do_size_x(r,id,sx,min_size_x)
|
||||
#define do_size_xy(id,r) _do_size_xy(r,id,sx,sy,min_size_x,min_size_y)
|
||||
#define do_align_x_size_y(id,r) _do_align_x_size_y(r,id,sx,sy,min_size_x,min_size_y)
|
||||
#define do_align_xy(id,r) _do_align_xy(r,id,sx,sy,min_size_x,min_size_y)
|
||||
#define do_align_x(id,r) _do_align_x(r,id,sx,min_size_x)
|
||||
|
||||
HWND wnd;
|
||||
UINT min_size_x, min_size_y;
|
||||
UINT min_size_x_w, min_size_y_w;
|
||||
|
||||
void do_sizing(UINT wp, RECT * r);
|
||||
void MakeComboEdit(UINT id, DWORD s);
|
||||
void GetChildRect(UINT id, RECT& child);
|
||||
|
||||
virtual BOOL DlgProc(UINT msg, WPARAM wp, LPARAM lp) { return 0;};
|
||||
static BOOL CALLBACK TheDialogProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||
{
|
||||
DlgBase * p;
|
||||
if (msg == WM_INITDIALOG)
|
||||
{
|
||||
p = (DlgBase*)lp;
|
||||
SetWindowLong(wnd, DWL_USER, lp);
|
||||
p->wnd = wnd;
|
||||
RECT r;
|
||||
GetClientRect(wnd, &r);
|
||||
p->min_size_x = r.right;
|
||||
p->min_size_y = r.bottom;
|
||||
GetWindowRect(wnd, &r);
|
||||
p->min_size_x_w = r.right - r.left;
|
||||
p->min_size_y_w = r.bottom - r.top;
|
||||
}
|
||||
else p = (DlgBase*)GetWindowLong(wnd, DWL_USER);
|
||||
BOOL rv = 0;
|
||||
if (p)
|
||||
{
|
||||
rv = p->DlgProc(msg, wp, lp);
|
||||
if (msg == WM_DESTROY)
|
||||
{
|
||||
p->wnd = 0;
|
||||
SetWindowLong(wnd, DWL_USER, 0);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
HWND myCreateDialog(UINT id, HWND parent)
|
||||
{
|
||||
return CreateDialogParamT(hIns, (char*)id, parent, TheDialogProc, (long)this);
|
||||
}
|
||||
virtual void myProcessMessage(MSG * msg)
|
||||
{
|
||||
if (!IsDialogMessage(wnd, msg))
|
||||
{
|
||||
TranslateMessage(msg);
|
||||
DispatchMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int myDialogBox(UINT id, HWND parent)
|
||||
{
|
||||
return DialogBoxParamT(hIns, (char*)id, parent, TheDialogProc, (long)this);
|
||||
}
|
||||
DlgBase() {
|
||||
wnd = 0;
|
||||
min_size_x = min_size_y = min_size_x_w = min_size_y_w = 0;
|
||||
}
|
||||
virtual ~DlgBase() {}
|
||||
};
|
@@ -1,65 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "decoder.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
//returns handle!=0 if successful, 0 if error
|
||||
//size will return the final nb of bytes written to the output, -1 if unknown
|
||||
__declspec( dllexport ) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate) {
|
||||
VorbisFile * f = VorbisFile::Create(fn,false);
|
||||
if(f) {
|
||||
if(!*bps) *bps=16; // FUCKO HAX
|
||||
Decoder * d = new Decoder();
|
||||
d->Init(f, *bps, *nch, false, false);
|
||||
*nch = (int)d->nch;
|
||||
*srate = (int)d->sr;
|
||||
*bps = (int)d->bps;
|
||||
*size = (int)(f->Length() * (double)((*nch) * (*srate) * (*bps/8)));
|
||||
return (intptr_t)d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__declspec( dllexport ) intptr_t winampGetExtendedRead_openW_float(const wchar_t *fn, int *size, int *bps, int *nch, int *srate) {
|
||||
VorbisFile * f = VorbisFile::Create(fn,false);
|
||||
if(f) {
|
||||
Decoder * d = new Decoder();
|
||||
d->Init(f, *bps, *nch, true, false);
|
||||
*nch = (int)d->nch;
|
||||
*srate = (int)d->sr;
|
||||
*bps = (int)d->bps;
|
||||
*size = (int)(f->Length() * (double)((*nch) * (*srate) * (*bps/8)));
|
||||
return (intptr_t)d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//returns nb of bytes read. -1 if read error (like CD ejected). if (ret<len), EOF is assumed
|
||||
__declspec( dllexport ) intptr_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch) {
|
||||
Decoder * d = (Decoder *)handle;
|
||||
size_t used = 0;
|
||||
for(;;) {
|
||||
used += (UINT)d->Read((UINT)(len - used),dest + used);
|
||||
if(used >= len) break;
|
||||
if(!d->DoFrame()) break;
|
||||
if(*killswitch) break;
|
||||
if (used)
|
||||
return used;
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
// return nonzero on success, zero on failure.
|
||||
__declspec( dllexport ) int winampGetExtendedRead_setTime(intptr_t handle, int millisecs) {
|
||||
Decoder * d = (Decoder *)handle;
|
||||
d->Flush();
|
||||
return !d->Seek(((double)millisecs) / 1000.0);
|
||||
}
|
||||
|
||||
__declspec( dllexport ) void winampGetExtendedRead_close(intptr_t handle) {
|
||||
Decoder * d = (Decoder *)handle;
|
||||
d->Flush();
|
||||
delete d->file;
|
||||
delete d;
|
||||
}
|
||||
}
|
@@ -1,264 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "api__in_vorbis.h"
|
||||
#include "resource.h"
|
||||
#include <strsafe.h>
|
||||
|
||||
/*static UINT xiphframes_ids[12]={IDB_BITMAP1,IDB_BITMAP2,IDB_BITMAP3,IDB_BITMAP4,IDB_BITMAP5,IDB_BITMAP6,IDB_BITMAP7,IDB_BITMAP8,IDB_BITMAP9,IDB_BITMAP10,IDB_BITMAP11,IDB_BITMAP12};
|
||||
static HBITMAP xiphframes[12];*/
|
||||
|
||||
static UINT xiphframes_ids[12]={IDB_PNG1,IDB_PNG2,IDB_PNG3,IDB_PNG4,IDB_PNG5,IDB_PNG6,IDB_PNG7,IDB_PNG8,IDB_PNG9,IDB_PNG10,IDB_PNG11,IDB_PNG12};
|
||||
static ARGB32 *xiphframes[12] = {0};
|
||||
static HBITMAP xiphframesBmp[12] = {0};
|
||||
|
||||
static void slap(HWND wnd,int v)
|
||||
{
|
||||
long hi=GetWindowLong(wnd,4);
|
||||
if (v) hi+=v*1000;
|
||||
else hi=0;
|
||||
SetWindowLong(wnd,4,hi);
|
||||
}
|
||||
|
||||
static CfgInt cfg_rpm("rpm",0);
|
||||
|
||||
static int visible_rpm,visible_max_rpm;
|
||||
static char show_rpm=0;
|
||||
static DWORD last_visible_rpm;
|
||||
|
||||
ARGB32 * loadImg(const void * data, int len, int *w, int *h, bool ldata=false)
|
||||
{
|
||||
FOURCC imgload = svc_imageLoader::getServiceType();
|
||||
int n = (int)mod.service->service_getNumServices(imgload);
|
||||
for(int i=0; i<n; i++)
|
||||
{
|
||||
waServiceFactory *sf = mod.service->service_enumService(imgload,i);
|
||||
if(sf)
|
||||
{
|
||||
svc_imageLoader * l = (svc_imageLoader*)sf->getInterface();
|
||||
if(l)
|
||||
{
|
||||
if(l->testData(data,len))
|
||||
{
|
||||
ARGB32* ret;
|
||||
if(ldata) ret = l->loadImageData(data,len,w,h);
|
||||
else ret = l->loadImage(data,len,w,h);
|
||||
sf->releaseInterface(l);
|
||||
return ret;
|
||||
}
|
||||
sf->releaseInterface(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ARGB32 * loadRrc(int id, wchar_t * sec, int *w, int *h, bool data=false)
|
||||
{
|
||||
DWORD size=0;
|
||||
HGLOBAL resourceHandle = WASABI_API_LOADRESFROMFILEW(sec, MAKEINTRESOURCEW(id), &size);
|
||||
if(resourceHandle)
|
||||
{
|
||||
ARGB32* ret = loadImg(resourceHandle,size,w,h,data);
|
||||
UnlockResource(resourceHandle);
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LRESULT WINAPI XiphProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
SetWindowLong(wnd,8,last_visible_rpm=GetTickCount());
|
||||
SetTimer(wnd,666,10,0);
|
||||
visible_rpm=-1;
|
||||
visible_max_rpm=-1;
|
||||
show_rpm=0;
|
||||
break;
|
||||
case WM_TIMER:
|
||||
if (wp==666)
|
||||
{
|
||||
long low=GetWindowLong(wnd,0);
|
||||
long hi=GetWindowLong(wnd,4);
|
||||
|
||||
long org=low&~0xFFFF;
|
||||
|
||||
int rpm=MulDiv(abs(hi),1000*60,12*0x10000);
|
||||
|
||||
DWORD t=GetTickCount();
|
||||
DWORD ot=(DWORD)SetWindowLong(wnd,8,t);
|
||||
bool redraw=0;
|
||||
|
||||
if (rpm>25) show_rpm=1;
|
||||
if (cfg_rpm<rpm) cfg_rpm=rpm;
|
||||
|
||||
if (show_rpm && (t&~0x3F)!=(ot&~0x3F))
|
||||
{
|
||||
wchar_t foo[128] = {0};
|
||||
if (visible_rpm<rpm || (visible_rpm>rpm && (t-last_visible_rpm)>333))
|
||||
{
|
||||
last_visible_rpm=t;
|
||||
visible_rpm=rpm;
|
||||
StringCchPrintfW(foo,128,WASABI_API_LNGSTRINGW(IDS_GAME_SPEED),rpm);
|
||||
SetDlgItemTextW(GetParent(wnd),IDC_RPM,foo);
|
||||
}
|
||||
if (visible_max_rpm!=cfg_rpm)
|
||||
{
|
||||
visible_max_rpm=cfg_rpm;
|
||||
StringCchPrintfW(foo,128,WASABI_API_LNGSTRINGW(IDS_BEST_RPM),(int)cfg_rpm);
|
||||
SetDlgItemTextW(GetParent(wnd),IDC_RPM2,foo);
|
||||
}
|
||||
}
|
||||
|
||||
low+=hi*(t-ot);
|
||||
while(low<0) low+=12*0x10000;
|
||||
while(low>=12*0x10000) low-=12*0x10000;
|
||||
|
||||
{
|
||||
int z=hi>>6;
|
||||
if (z) hi-=z;
|
||||
else if (hi>0) hi--;
|
||||
else if (hi<0) hi++;
|
||||
}
|
||||
|
||||
SetWindowLong(wnd,0,low);
|
||||
SetWindowLong(wnd,4,hi);
|
||||
if (redraw || (low&~0xFFFF)!=org)
|
||||
{
|
||||
RedrawWindow(wnd,0,0,RDW_INVALIDATE);
|
||||
}
|
||||
KillTimer(wnd,666);
|
||||
SetTimer(wnd,666,10,0);
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
slap(wnd,-1);
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
slap(wnd,1);
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
slap(wnd,0);
|
||||
break;
|
||||
case WM_PAINT:
|
||||
{
|
||||
int i=(GetWindowLong(wnd,0))>>16;
|
||||
HDC dc = CreateCompatibleDC(0);
|
||||
|
||||
if (!xiphframesBmp[i])
|
||||
{
|
||||
int cur_w = 0, cur_h = 0;
|
||||
xiphframes[i] = loadRrc(xiphframes_ids[i], L"PNG", &cur_w, &cur_h, true);
|
||||
|
||||
BITMAPINFO bmi = {0};
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = cur_w;
|
||||
bmi.bmiHeader.biHeight = -cur_h;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
void *bits = 0;
|
||||
if(xiphframesBmp[i]) DeleteObject(xiphframesBmp[i]);
|
||||
xiphframesBmp[i] = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
|
||||
memcpy(bits, xiphframes[i], cur_w * cur_h * 4);
|
||||
}
|
||||
|
||||
if (xiphframesBmp[i])
|
||||
{
|
||||
HGDIOBJ foo = SelectObject(dc, xiphframesBmp[i]);
|
||||
HDC wdc = GetDC(wnd);
|
||||
RECT r = {0};
|
||||
GetClientRect(wnd, &r);
|
||||
FillRect(wdc, &r, GetSysColorBrush(COLOR_3DFACE));
|
||||
|
||||
BLENDFUNCTION blendFn = {0};
|
||||
blendFn.BlendOp = AC_SRC_OVER;
|
||||
blendFn.SourceConstantAlpha = 255;
|
||||
blendFn.AlphaFormat = AC_SRC_ALPHA;
|
||||
AlphaBlend(wdc, 2, 2, r.right - 2, r.bottom - 2, dc, 0, 0, 63, 63, blendFn);
|
||||
|
||||
ReleaseDC(wnd, wdc);
|
||||
SelectObject(dc, foo);
|
||||
}
|
||||
DeleteDC(dc);
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(xiphframes_ids); i++)
|
||||
{
|
||||
if(xiphframesBmp[i]) DeleteObject(xiphframesBmp[i]); xiphframesBmp[i] = 0;
|
||||
if(xiphframes[i] && WASABI_API_MEMMGR) WASABI_API_MEMMGR->sysFree((void *)xiphframes[i]); xiphframes[i] = 0;
|
||||
}
|
||||
KillTimer(wnd,666);
|
||||
break;
|
||||
}
|
||||
};
|
||||
return DefWindowProc(wnd,msg,wp,lp);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK AboutProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
wchar_t tmp[1024] = {0}, tmp2[1024] = {0}, *t1 = tmp, *t2 = tmp2, text[1024] = {0};
|
||||
SetWindowTextW(wnd,WASABI_API_LNGSTRINGW_BUF(IDS_NULLSOFT_VORBIS_DECODER_OLD,text,1024));
|
||||
StringCchPrintfW(tmp,1024,WASABI_API_LNGSTRINGW(IDS_ABOUT_TEXT),mod.description,__DATE__);
|
||||
// due to quirks with the more common resource editors, is easier to just store the string
|
||||
// internally only with \n and post-process to be \r\n (as here) so it will appear correctly
|
||||
// on new lines as is wanted (silly multiline edit controls)
|
||||
while(t1 && *t1 && (t2 - tmp2 < 1024))
|
||||
{
|
||||
if(*t1 == L'\n')
|
||||
{
|
||||
*t2 = L'\r';
|
||||
t2 = CharNextW(t2);
|
||||
}
|
||||
*t2 = *t1;
|
||||
t1 = CharNextW(t1);
|
||||
t2 = CharNextW(t2);
|
||||
}
|
||||
|
||||
SetDlgItemTextW(wnd,IDC_ABOUT_TEXT,tmp2);
|
||||
// fixes the incorrect selection of the text on dialog opening
|
||||
PostMessage(GetDlgItem(wnd,IDC_ABOUT_TEXT),EM_SETSEL,-1,0);
|
||||
return 1;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
if (wp==IDOK || wp==IDCANCEL)
|
||||
{
|
||||
do_cfg(1);
|
||||
EndDialog(wnd,0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void About(HWND hwndParent)
|
||||
{
|
||||
static char got_xiph;
|
||||
if (!got_xiph)
|
||||
{
|
||||
WNDCLASS wc=
|
||||
{
|
||||
0,
|
||||
XiphProc,
|
||||
0,
|
||||
12,
|
||||
WASABI_API_LNG_HINST,
|
||||
0,
|
||||
LoadCursor(0,IDC_ARROW),
|
||||
0,
|
||||
0,
|
||||
L"XIPH_CLASS",
|
||||
};
|
||||
|
||||
RegisterClassW(&wc);
|
||||
got_xiph=1;
|
||||
}
|
||||
|
||||
WASABI_API_DIALOGBOXW(IDD_ABOUT,hwndParent,AboutProc);
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
#ifndef NULLSOFT_API_H
|
||||
#define NULLSOFT_API_H
|
||||
|
||||
#include "../Agave/Config/api_config.h"
|
||||
#include "../Agave/Language/api_language.h"
|
||||
|
||||
#include <api/application/api_application.h>
|
||||
extern api_application *applicationApi;
|
||||
#define WASABI_API_APP applicationApi
|
||||
|
||||
#include <api/service/svcs/svc_imgload.h>
|
||||
|
||||
#include <api/service/api_service.h>
|
||||
|
||||
#include <api/service/waServiceFactory.h>
|
||||
|
||||
#include <api/memmgr/api_memmgr.h>
|
||||
extern api_memmgr *memmgrApi;
|
||||
#define WASABI_API_MEMMGR memmgrApi
|
||||
|
||||
#endif
|
@@ -1,96 +0,0 @@
|
||||
#define STRICT
|
||||
#include <windows.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include "c_string.h"
|
||||
#include "../nu/ns_wc.h"
|
||||
|
||||
extern BOOL is_nt;
|
||||
|
||||
template<class myChar>
|
||||
void string_base<myChar>::makespace(UINT s)
|
||||
{
|
||||
if (size<s)
|
||||
{
|
||||
int oldSize = size;
|
||||
do size<<=1; while(size<s);
|
||||
myChar *newPtr = (myChar*)realloc(ptr,size*sizeof(myChar));
|
||||
if (!newPtr)
|
||||
{
|
||||
newPtr = (myChar*)malloc(size*sizeof(myChar));
|
||||
if (newPtr)
|
||||
{
|
||||
memcpy(newPtr, ptr, oldSize*sizeof(myChar));
|
||||
free(ptr);
|
||||
ptr = newPtr;
|
||||
}
|
||||
else return ;
|
||||
}
|
||||
else ptr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void String::s_GetWindowText(HWND w)
|
||||
{
|
||||
Reset();
|
||||
int len=GetWindowTextLengthA(w)+1;
|
||||
GetWindowTextA(w,StringTempA(*this,len),len);
|
||||
}
|
||||
|
||||
void StringW::s_GetWindowText(HWND w)
|
||||
{
|
||||
Reset();
|
||||
int len=GetWindowTextLengthW(w)+1;
|
||||
GetWindowTextW(w,StringTempW(*this,len),len);
|
||||
}
|
||||
|
||||
void String::SetStringW(const WCHAR * c)
|
||||
{
|
||||
UINT len=(lstrlenW(c)+1)*2;
|
||||
WideCharToMultiByteSZ(CP_ACP,0,c,-1,StringTempA(*this,len),len,0,0);
|
||||
}
|
||||
|
||||
void StringW::SetStringA(const char * c)
|
||||
{
|
||||
UINT len=(UINT)strlen(c)+1;
|
||||
MultiByteToWideCharSZ(CP_ACP,0,c,-1,StringTempW(*this,len),len);
|
||||
}
|
||||
|
||||
void String::AddStringW(const WCHAR * c)
|
||||
{
|
||||
AddString(String(c));
|
||||
}
|
||||
|
||||
void StringW::AddStringA(const char * c)
|
||||
{
|
||||
AddString(StringW(c));
|
||||
}
|
||||
|
||||
void String::s_SetWindowText(HWND w)
|
||||
{
|
||||
SetWindowTextA(w,*this);
|
||||
}
|
||||
|
||||
void StringW::s_SetWindowText(HWND w)
|
||||
{
|
||||
SetWindowTextW(w,*this);
|
||||
}
|
||||
|
||||
|
||||
StringPrintf::StringPrintf(const char * fmt,...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
vsprintf(StringTempA(*this,1024),fmt,list);
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
StringPrintfW::StringPrintfW(const WCHAR * fmt,...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
vswprintf(StringTempW(*this,1024),1024,fmt,list);
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
String::String(const StringW & z) {AddStringW(z);}
|
@@ -1,156 +0,0 @@
|
||||
#pragma once
|
||||
template <class myChar>
|
||||
class string_base
|
||||
{
|
||||
private:
|
||||
myChar * ptr;
|
||||
UINT size,used;
|
||||
void makespace(UINT s);
|
||||
static UINT mylen(const myChar * p) {UINT r=0;while(p[r]) r++;return r;}
|
||||
public:
|
||||
void AddChar(myChar c)
|
||||
{
|
||||
makespace(used+2);
|
||||
ptr[used++]=c;
|
||||
ptr[used]=0;
|
||||
}
|
||||
string_base()
|
||||
{
|
||||
used=0;
|
||||
size=128;
|
||||
ptr=(myChar*)malloc(size*sizeof(myChar));
|
||||
ptr[0]=0;
|
||||
}
|
||||
|
||||
~string_base() { if (ptr) free(ptr);}
|
||||
|
||||
operator const myChar*() const {return ptr;}
|
||||
|
||||
const myChar & operator*() const {return *ptr;}
|
||||
|
||||
UINT Length() const {return used;}
|
||||
|
||||
void AddString(const myChar * c)
|
||||
{
|
||||
UINT d=mylen(c);
|
||||
makespace(used+d+1);
|
||||
memcpy(ptr+used,c,sizeof(myChar)*d);
|
||||
used+=d;
|
||||
ptr[used]=0;
|
||||
}
|
||||
|
||||
void Reset() {Truncate(0);}
|
||||
void Truncate(UINT x) {if (used>x) {used=x;ptr[x]=0;}}
|
||||
|
||||
void SetString(const myChar * s) {Reset();AddString(s);}
|
||||
|
||||
myChar * BufferStart(UINT n)
|
||||
{
|
||||
makespace(n+1);
|
||||
memset(ptr,0,size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void BufferDone() {used=mylen(ptr);}
|
||||
|
||||
void SetChar(UINT offset,myChar c)//hack for some ghey routines
|
||||
{
|
||||
if (!c) Truncate(offset);
|
||||
else if (offset<used) ptr[offset]=c;
|
||||
}
|
||||
};
|
||||
|
||||
template<class myChar>
|
||||
class StringTemp
|
||||
{
|
||||
private:
|
||||
string_base<myChar> * parent;
|
||||
myChar * data;
|
||||
public:
|
||||
StringTemp(string_base<myChar> & s,UINT siz) {parent=&s;data=s.BufferStart(siz);}
|
||||
~StringTemp() {parent->BufferDone();}
|
||||
operator myChar* () {return data;}
|
||||
};
|
||||
|
||||
#define StringTempW StringTemp<WCHAR>
|
||||
#define StringTempA StringTemp<char>
|
||||
|
||||
class StringW;
|
||||
|
||||
class String : public string_base<char>
|
||||
{
|
||||
public:
|
||||
String() {}
|
||||
String(HWND w) {s_GetWindowText(w);}
|
||||
String(const char* z) {SetString(z);}
|
||||
String(const WCHAR* z) {SetStringW(z);}
|
||||
String(const String& z) {SetString(z);}
|
||||
String(const StringW& z);
|
||||
void AddStringW(const WCHAR * c);
|
||||
void SetStringW(const WCHAR * c);
|
||||
void s_GetWindowText(HWND w);
|
||||
void s_SetWindowText(HWND w);
|
||||
void operator=(const char * s) {SetString(s);}
|
||||
void operator+=(const char * s) {AddString(s);}
|
||||
void operator=(String & s) {SetString(s);}
|
||||
void operator+=(String & s) {AddString(s);}
|
||||
inline void s_GetDlgItemText(HWND w,UINT id) {s_GetWindowText(GetDlgItem(w,id));}
|
||||
inline void s_SetDlgItemText(HWND w,UINT id) {s_SetWindowText(GetDlgItem(w,id));}
|
||||
};
|
||||
|
||||
class StringW : public string_base<WCHAR>
|
||||
{
|
||||
public:
|
||||
StringW() {}
|
||||
StringW(HWND w) {s_GetWindowText(w);}
|
||||
StringW(const WCHAR * z) {SetString(z);}
|
||||
void AddStringA(const char * c);
|
||||
void SetStringA(const char * c);
|
||||
StringW(const char * z) {SetStringA(z);}
|
||||
StringW(const StringW & z) {SetString(z);}
|
||||
StringW(const String & z) {SetStringA(z);}
|
||||
void s_GetWindowText(HWND w);
|
||||
void s_SetWindowText(HWND w);
|
||||
void operator=(const WCHAR * s) {SetString(s);}
|
||||
void operator+=(const WCHAR * s) { if (s) AddString(s);}
|
||||
void operator=(StringW & s) {SetString(s);}
|
||||
void operator+=(StringW & s) {AddString(s);}
|
||||
inline void s_GetDlgItemText(HWND w,UINT id) {s_GetWindowText(GetDlgItem(w,id));}
|
||||
inline void s_SetDlgItemText(HWND w,UINT id) {s_SetWindowText(GetDlgItem(w,id));}
|
||||
bool reg_read(const char *name);
|
||||
void reg_write(const char *name);
|
||||
};
|
||||
|
||||
|
||||
class StringPrintf : public String
|
||||
{
|
||||
public:
|
||||
StringPrintf(const char * fmt,...);
|
||||
};
|
||||
|
||||
class StringPrintfW : public StringW
|
||||
{
|
||||
public:
|
||||
StringPrintfW(const WCHAR * fmt,...);
|
||||
};
|
||||
|
||||
template<class myChar>
|
||||
class StringF2T : public string_base<myChar>
|
||||
{
|
||||
public:
|
||||
StringF2T(const myChar * fn)
|
||||
{
|
||||
const myChar * ptr=fn,*dot=0,*src=fn;
|
||||
while(ptr && *ptr)
|
||||
{
|
||||
if (*ptr=='\\' || *ptr=='/' || *ptr==':') src=ptr+1;
|
||||
else if (*ptr=='.') dot=ptr;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
while(src && *src && (!dot || src<dot)) AddChar(*(src++));
|
||||
}
|
||||
};
|
||||
|
||||
#define StringF2T_A StringF2T<char>
|
||||
#define StringF2T_W StringF2T<WCHAR>
|
@@ -1,82 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
static size_t callback_fread(void *ptr, size_t size, size_t nmemb, HANDLE hFile)
|
||||
{
|
||||
DWORD bw = 0;
|
||||
ReadFile(hFile,ptr,(DWORD)(size*nmemb),&bw,0);
|
||||
return bw/size;
|
||||
}
|
||||
|
||||
static size_t callback_write(void * ptr, size_t size, size_t nmemb, HANDLE hFile)
|
||||
{
|
||||
DWORD bw = 0;
|
||||
WriteFile(hFile,ptr,(DWORD)(size*nmemb),&bw,0);
|
||||
return bw/size;
|
||||
}
|
||||
|
||||
static int callback_fseek(HANDLE hFile, __int64 offset, int whence)
|
||||
{
|
||||
__int64 temp = offset;
|
||||
SetFilePointer(hFile,*(DWORD*)&temp,((long*)&temp+1),whence);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int callback_fclose(HANDLE f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __int64 callback_ftell(HANDLE hFile)
|
||||
{
|
||||
__int64 ret=0;
|
||||
*(DWORD*)&ret = SetFilePointer(hFile,0,((long*)&ret+1),FILE_CURRENT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void* callbacks[4]=
|
||||
{
|
||||
callback_fread,callback_fseek,callback_fclose,callback_ftell
|
||||
};
|
||||
|
||||
namespace ogg_helper
|
||||
{
|
||||
int num_get_tracks(HANDLE hFile/*track_indexer::callback * out,reader * r*/)
|
||||
{
|
||||
SetFilePointer(hFile,0,0,FILE_BEGIN);
|
||||
OggVorbis_File l_vf;
|
||||
memset(&l_vf,0,sizeof(l_vf));
|
||||
if (ov_open_callbacks(hFile,&l_vf,0,0,*(ov_callbacks*)callbacks))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int rv = l_vf.links;
|
||||
ov_clear(&l_vf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int query_chained_stream_offset(HANDLE hFile,int idx,__int64 * out_beginning,__int64 * out_end)
|
||||
{
|
||||
SetFilePointer(hFile,0,0,FILE_BEGIN);
|
||||
OggVorbis_File l_vf;
|
||||
memset(&l_vf,0,sizeof(l_vf));
|
||||
if (ov_open_callbacks(hFile,&l_vf,0,0,*(ov_callbacks*)callbacks))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int retval = 0;
|
||||
if (idx>=0 && idx<l_vf.links)
|
||||
{
|
||||
retval = 1;
|
||||
*out_beginning = l_vf.offsets[idx];
|
||||
*out_end = l_vf.offsets[idx+1];
|
||||
}
|
||||
|
||||
ov_clear(&l_vf);
|
||||
return retval;
|
||||
}
|
||||
}
|
@@ -1,335 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "api__in_vorbis.h"
|
||||
#include "../nu/ns_wc.h"
|
||||
#include <commctrl.h>
|
||||
#include <shlobj.h>
|
||||
#include "../winamp/wa_ipc.h"
|
||||
#include "../nu/AutoChar.h"
|
||||
#include <strsafe.h>
|
||||
|
||||
int mc6_dm_names_ids[]={IDS_LEAVE_AS_IS,IDS_REMAP_6_CHANNELS,IDS_DOWNMIX_TO_4_CHANNELS,IDS_DOWNMIX_TO_2_CHANNELS_DS,IDS_DOWNMIX_TO_2_CHANNELS_DS2,IDS_DOWNMIX_TO_MONO};
|
||||
int mc6_map_names_id[]={IDS_CORRECT_FL_FC_FR_BL_BR_LFE,IDS_BROKEN_FL_FR_FC_BL_BR_LFE};
|
||||
int32_t priority_tab[7]={THREAD_PRIORITY_IDLE,THREAD_PRIORITY_LOWEST,THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL,THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_HIGHEST,THREAD_PRIORITY_TIME_CRITICAL};
|
||||
|
||||
char* defaultDumpDir()
|
||||
{
|
||||
static char dumpdir[MAX_PATH] = {0};
|
||||
if(FAILED(SHGetFolderPathA(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, dumpdir)))
|
||||
{
|
||||
if(FAILED(SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, dumpdir)))
|
||||
{
|
||||
lstrcpynA(dumpdir, "C:\\", MAX_PATH);
|
||||
}
|
||||
}
|
||||
return dumpdir;
|
||||
}
|
||||
|
||||
CfgString
|
||||
cfg_ssave_format("ssave_format","%filename%"),
|
||||
cfg_dumpdir("dumpdir",defaultDumpDir());
|
||||
|
||||
CfgInt
|
||||
cfg_http_bsize("http_bsize",0x10000),
|
||||
cfg_fsave("fsave",0),
|
||||
cfg_abr("abr",0),
|
||||
cfg_proxy_mode("proxy_mode",2),
|
||||
cfg_prebuf1("prebuf1",50),
|
||||
cfg_prebuf2("prebuf2",75),
|
||||
cfg_httpseek2("httpseek2",0),
|
||||
cfg_fix0r("fix0r",1),
|
||||
cfg_mc6_dm("mc6_dm",0),
|
||||
cfg_mc6_map("_mc6_map",0),
|
||||
cfg_remember_infosize("remember_infosize",1),
|
||||
cfg_fullbuf("fullbuf",0),
|
||||
cfg_cur_tab("cur_tab",0);
|
||||
|
||||
static int old_preamp;
|
||||
CfgFont cfg_font("font");
|
||||
static LOGFONT cfg_font_edit;
|
||||
|
||||
BOOL CALLBACK browseEnumProc(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
char cl[32] = {0};
|
||||
GetClassNameA(hwnd, cl, ARRAYSIZE(cl));
|
||||
if (!lstrcmpiA(cl, WC_TREEVIEWA))
|
||||
{
|
||||
PostMessage(hwnd, TVM_ENSUREVISIBLE, 0, (LPARAM)TreeView_GetSelection(hwnd));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int CALLBACK browzaproc(HWND hwnd, UINT msg, LPARAM lp, LPARAM dat)
|
||||
{
|
||||
if (msg == BFFM_INITIALIZED)
|
||||
{
|
||||
SendMessageW(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)dat);
|
||||
|
||||
// this is not nice but it fixes the selection not working correctly on all OSes
|
||||
EnumChildWindows(hwnd, browseEnumProc, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void d_browza(HWND wnd,HWND bt,wchar_t* tx)
|
||||
{
|
||||
IMalloc* pMalloc=0;
|
||||
|
||||
SHGetMalloc(&pMalloc);
|
||||
if (!pMalloc) return;
|
||||
|
||||
wchar_t dir[MAX_PATH] = {0};
|
||||
GetWindowTextW(bt,dir,MAX_PATH);
|
||||
BROWSEINFOW bi=
|
||||
{
|
||||
wnd,
|
||||
0,
|
||||
0,
|
||||
tx,
|
||||
BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE,
|
||||
browzaproc,
|
||||
(LPARAM)dir,
|
||||
0
|
||||
};
|
||||
ITEMIDLIST* li=SHBrowseForFolderW(&bi);
|
||||
if (li)
|
||||
{
|
||||
SHGetPathFromIDListW(li,dir);
|
||||
SetWindowTextW(bt,dir);
|
||||
pMalloc->Free(li);
|
||||
}
|
||||
|
||||
pMalloc->Release();
|
||||
}
|
||||
|
||||
static BOOL CALLBACK CfgProc1(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
wchar_t temp[128] = {0}, cfg_dialog_name[128] = {0};
|
||||
StringCchPrintfW(cfg_dialog_name,128,WASABI_API_LNGSTRINGW(IDS_TITLE_PREFERENCES),
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_NULLSOFT_VORBIS_DECODER_OLD, temp, 128));
|
||||
SetWindowTextW(wnd,cfg_dialog_name);
|
||||
|
||||
SendDlgItemMessage(wnd,IDC_FULLBUF,BM_SETCHECK,cfg_fullbuf,0);
|
||||
|
||||
UINT n;
|
||||
HWND w=GetDlgItem(wnd,IDC_MC6_DM);
|
||||
for(n=0;n<sizeof(mc6_dm_names_ids)/sizeof(mc6_dm_names_ids[0]);n++)
|
||||
{
|
||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(mc6_dm_names_ids[n]));
|
||||
}
|
||||
SendMessage(w,CB_SETCURSEL,cfg_mc6_dm,0);
|
||||
|
||||
w=GetDlgItem(wnd,IDC_MC6_MAP);
|
||||
for(n=0;n<sizeof(mc6_map_names_id)/sizeof(mc6_map_names_id[0]);n++)
|
||||
{
|
||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(mc6_map_names_id[n]));
|
||||
}
|
||||
SendMessage(w,CB_SETCURSEL,cfg_mc6_map,0);
|
||||
|
||||
SendDlgItemMessage(wnd,IDC_AVG_BR,BM_SETCHECK,cfg_abr,0);
|
||||
|
||||
SetDlgItemInt(wnd,IDC_HTTP_BSIZE,cfg_http_bsize>>10,0);
|
||||
if (cfg_fsave) SendDlgItemMessage(wnd,IDC_FSAVE,BM_SETCHECK,1,0);
|
||||
if (cfg_fix0r) SendDlgItemMessage(wnd,IDC_FIX0R,BM_SETCHECK,1,0);
|
||||
cfg_dumpdir.s_SetDlgItemText(wnd,IDC_STREAM_SAVE);
|
||||
w=GetDlgItem(wnd,IDC_PROXY);
|
||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(IDS_NEVER));
|
||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(IDS_PORT_80_ONLY));
|
||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(IDS_ALWAYS));
|
||||
SendMessage(w,CB_SETCURSEL,cfg_proxy_mode,0);
|
||||
|
||||
w=GetDlgItem(wnd,IDC_SLIDER1);
|
||||
SendMessage(w,TBM_SETRANGE,0,MAKELONG(1,100));
|
||||
SendMessage(w,TBM_SETPOS,1,cfg_prebuf1);
|
||||
w=GetDlgItem(wnd,IDC_SLIDER2);
|
||||
SendMessage(w,TBM_SETRANGE,0,MAKELONG(1,100));
|
||||
SendMessage(w,TBM_SETPOS,1,cfg_prebuf2);
|
||||
|
||||
cfg_ssave_format.s_SetDlgItemText(wnd,IDC_SSAVE_FMT);
|
||||
SendMessage(wnd,WM_COMMAND,MAKEWPARAM(IDC_FSAVE,BN_CLICKED),(LPARAM)GetDlgItem(wnd,IDC_FSAVE));
|
||||
}
|
||||
return 1;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wp))
|
||||
{
|
||||
case IDC_STREAM_SAVE:
|
||||
d_browza(wnd,(HWND)lp,WASABI_API_LNGSTRINGW(IDS_SELECT_OUTPUT_DIRECTORY));
|
||||
break;
|
||||
|
||||
case IDC_SSAVE_FMT_DEF:
|
||||
SetDlgItemText(wnd,IDC_SSAVE_FMT,L"%filename%");
|
||||
break;
|
||||
|
||||
case IDC_FSAVE:
|
||||
{
|
||||
int checked = IsDlgButtonChecked(wnd,IDC_FSAVE);
|
||||
EnableWindow(GetDlgItem(wnd,IDC_STREAM_SAVE),checked);
|
||||
EnableWindow(GetDlgItem(wnd,IDC_SSAVE_FMT),checked);
|
||||
EnableWindow(GetDlgItem(wnd,IDC_SSAVE_FMT_DEF),checked);
|
||||
}
|
||||
break;
|
||||
|
||||
case IDOK:
|
||||
case IDCANCEL:
|
||||
{
|
||||
if (LOWORD(wp) == IDOK)
|
||||
{
|
||||
cfg_fullbuf=(int)SendDlgItemMessage(wnd,IDC_FULLBUF,BM_GETCHECK,0,0);
|
||||
|
||||
cfg_mc6_dm=(int)SendDlgItemMessage(wnd,IDC_MC6_DM,CB_GETCURSEL,0,0);
|
||||
cfg_mc6_map=(int)SendDlgItemMessage(wnd,IDC_MC6_MAP,CB_GETCURSEL,0,0);
|
||||
|
||||
cfg_abr=(int)SendDlgItemMessage(wnd,IDC_AVG_BR,BM_GETCHECK,0,0);
|
||||
|
||||
cfg_dumpdir.s_GetDlgItemText(wnd,IDC_STREAM_SAVE);
|
||||
cfg_http_bsize=GetDlgItemInt(wnd,IDC_HTTP_BSIZE,0,0)<<10;
|
||||
cfg_fsave=(int)SendDlgItemMessage(wnd,IDC_FSAVE,BM_GETCHECK,0,0);
|
||||
cfg_fix0r=(int)SendDlgItemMessage(wnd,IDC_FIX0R,BM_GETCHECK,0,0);
|
||||
cfg_proxy_mode=(int)SendDlgItemMessage(wnd,IDC_PROXY,CB_GETCURSEL,0,0);
|
||||
cfg_prebuf1=(int)SendDlgItemMessage(wnd,IDC_SLIDER1,TBM_GETPOS,0,0);
|
||||
cfg_prebuf2=(int)SendDlgItemMessage(wnd,IDC_SLIDER2,TBM_GETPOS,0,0);
|
||||
cfg_ssave_format.s_GetDlgItemText(wnd,IDC_SSAVE_FMT);
|
||||
}
|
||||
do_cfg(1);
|
||||
EndDialog(wnd,(LOWORD(wp) == IDOK));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const int controls[] =
|
||||
{
|
||||
IDC_SLIDER1,
|
||||
IDC_SLIDER2,
|
||||
};
|
||||
if (FALSE != WASABI_API_APP->DirectMouseWheel_ProcessDialogMessage(wnd, msg, wp, lp, controls, ARRAYSIZE(controls)))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern HANDLE hThread;//hack
|
||||
|
||||
void Config(HWND p)
|
||||
{
|
||||
if (WASABI_API_DIALOGBOXPARAMW(IDD_CONFIG,p,CfgProc1,0))
|
||||
{
|
||||
if (hThread) PostMessage(mod.hMainWindow,WM_USER,0,243);
|
||||
}
|
||||
}
|
||||
|
||||
int CfgVar::read_int(const char *inifile, const char *section,const char * name,int def)
|
||||
{
|
||||
return GetPrivateProfileIntA(section, name, def, inifile);
|
||||
}
|
||||
|
||||
void CfgVar::write_int(const char *inifile, const char *section, const char * name,int val)
|
||||
{
|
||||
char temp[32] = {0};
|
||||
StringCchPrintfA(temp, 32, "%d", val);
|
||||
WritePrivateProfileStringA(section, name, temp, inifile);
|
||||
}
|
||||
|
||||
void CfgVar::write_struct(const char *inifile, const char *section, const char * name, void * ptr,UINT size)
|
||||
{
|
||||
WritePrivateProfileStructA("in_vorbis", name, ptr, size, INI_FILE);
|
||||
}
|
||||
|
||||
bool CfgVar::read_struct(const char *inifile, const char *section, const char * name,void * ptr,UINT size)
|
||||
{
|
||||
return !!GetPrivateProfileStructA("in_vorbis", name, ptr, size, INI_FILE);
|
||||
}
|
||||
|
||||
void do_cfg(int s)
|
||||
{
|
||||
#define CFG_VERSION 0x10204
|
||||
|
||||
if (!s)
|
||||
{
|
||||
if (CfgVar::read_int(INI_FILE, "in_vorbis", "version",0)==CFG_VERSION)
|
||||
CfgVar::ReadConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
CfgVar::WriteConfig();
|
||||
CfgVar::write_int(INI_FILE, "in_vorbis", "version",CFG_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
CfgVar * CfgVar::list=0;
|
||||
|
||||
void CfgVar::ReadConfig()
|
||||
{
|
||||
CfgVar * p=list;
|
||||
while(p)
|
||||
{
|
||||
p->Read(p->name);
|
||||
p=p->next;
|
||||
}
|
||||
}
|
||||
|
||||
void CfgVar::WriteConfig()
|
||||
{
|
||||
CfgVar * p=list;
|
||||
while(p)
|
||||
{
|
||||
p->Write(p->name);
|
||||
p=p->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool StringW::reg_read(const char * name)
|
||||
{
|
||||
char utf8_data[2048] = {0};
|
||||
wchar_t utf16_data[2048] = {0};
|
||||
GetPrivateProfileStringA("in_vorbis", name, "@default@", utf8_data, 2048, INI_FILE);
|
||||
if (!strcmp("@default@", utf8_data))
|
||||
return false;
|
||||
|
||||
MultiByteToWideCharSZ(CP_UTF8, 0, utf8_data, -1, utf16_data, 2048);
|
||||
SetString(utf16_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StringW::reg_write(const char * name)
|
||||
{
|
||||
WritePrivateProfileStringA("in_vorbis", name, AutoChar((const WCHAR *)*this, CP_UTF8), INI_FILE);
|
||||
}
|
||||
|
||||
void CfgString::Read(const char * name)
|
||||
{
|
||||
reg_read(name);
|
||||
}
|
||||
|
||||
void CfgString::Write(const char * name)
|
||||
{
|
||||
StringW temp;
|
||||
if (temp.reg_read(name))
|
||||
{
|
||||
if (wcscmp(temp,*this)) reg_write(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wcscmp(def,*this)) reg_write(name);
|
||||
}
|
||||
}
|
||||
|
||||
void CfgInt::Write(const char * name)
|
||||
{
|
||||
if (read_int(INI_FILE, "in_vorbis", name,def)!=value) write_int(INI_FILE, "in_vorbis",name,value);
|
||||
}
|
||||
|
||||
void CfgInt::Read(const char * name)
|
||||
{
|
||||
value=read_int(INI_FILE, "in_vorbis", name,def);
|
||||
}
|
@@ -1,567 +0,0 @@
|
||||
|
||||
/* Winamp 3 Player core api v0.1
|
||||
** (c)2000 nullsoft jcf/ct/dk
|
||||
** Notes:
|
||||
** Keep in mind that this header file is subject to change prior to the
|
||||
** release of Winamp 3. The ability to configure plug-ins has yet to be
|
||||
** added and is the first and foremost concern of the engineering team.
|
||||
*/
|
||||
|
||||
#ifndef __CORE_API_H
|
||||
#define __CORE_API_H
|
||||
/*
|
||||
// Visual C 6 makes big unaligned dlls. the following will correct it
|
||||
#ifndef _DEBUG
|
||||
// release optimizations
|
||||
// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers)
|
||||
#pragma optimize("gsy",on)
|
||||
#pragma comment(linker,"/RELEASE")
|
||||
// set the 512-byte alignment
|
||||
#pragma comment(linker,"/opt:nowin98")
|
||||
#endif
|
||||
*/
|
||||
// Use Assert in your code to catch errors that shouldn't happen, when compiled in release mode, they are #defined out
|
||||
#ifndef ASSERT
|
||||
#ifdef _DEBUG
|
||||
#define ASSERT(x) if (!(x)) MessageBox(NULL,"ASSERT FAILED: " #x,"ASSERT FAILED in " __FILE__ ,MB_OK|MB_ICONSTOP);
|
||||
#else
|
||||
#define ASSERT(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* CLASS DESCRIPTIONS */
|
||||
|
||||
/* WReader
|
||||
** File reader module class, ie. opens and reads files, streams
|
||||
*/
|
||||
class WReader;
|
||||
|
||||
/* WInputInfo
|
||||
** Class that returns information (length, title, metadata) about a specified file
|
||||
*/
|
||||
class WInputInfo;
|
||||
|
||||
/* WInfo_callback
|
||||
** Player's interface that provides Winamp 3 core functions to your WInputInfo classes
|
||||
*/
|
||||
class WInfo_callback;
|
||||
|
||||
/* WInputSource
|
||||
** Input Source manager base class, ie. decodes mp3's, wavs
|
||||
*/
|
||||
class WInputSource;
|
||||
|
||||
/* WOutputFilter
|
||||
** Abstract base class for any Output Filter plug-in, ie. changes pitch, converts format, outputs to speakers
|
||||
*/
|
||||
class WOutputFilter;
|
||||
|
||||
/* WPlayer_callback
|
||||
** Player's interface that provides Winamp 3 core functions to your Input Sources and Output Filter plug-ins
|
||||
** (Getting a reader for opening a file, sending stuff about what's going on to the Winamp 3 core)
|
||||
*/
|
||||
class WPlayer_callback;
|
||||
|
||||
|
||||
|
||||
|
||||
class WPlayer_callback
|
||||
{
|
||||
public:
|
||||
/* GetReader
|
||||
** Allows your Input Source and Output Filter plugins to request a reader from Winamp,
|
||||
** so you don't have to worry about opening files or streams
|
||||
*/
|
||||
virtual WReader *GetReader(char *url)=0;
|
||||
|
||||
|
||||
/* The 3 following functions allows your Input Source and Output Filter plugins to send error/warning/status
|
||||
** messages back to the Winamp 3 core
|
||||
*/
|
||||
|
||||
/* Error
|
||||
** playback should stop (soundcard driver error, etc)
|
||||
*/
|
||||
virtual void Error(char *reason)=0;
|
||||
|
||||
/* Warning
|
||||
** warning (something recoverable, like file not found, etc)
|
||||
*/
|
||||
virtual void Warning(char *warning)=0;
|
||||
|
||||
/* Status
|
||||
** status update (nothing really wrong)
|
||||
*/
|
||||
virtual void Status(char *status)=0;
|
||||
|
||||
|
||||
|
||||
|
||||
/* TitleChange
|
||||
** should be called if the current file titlename changes during the decoding
|
||||
*/
|
||||
virtual void TitleChange(char *new_title)=0;
|
||||
|
||||
/* InfoChange
|
||||
** should be called if the infos about the current file changes during the decoding
|
||||
*/
|
||||
virtual void InfoChange(char *new_info_str, int new_length)=0;
|
||||
|
||||
/* UrlChange
|
||||
** should be called if the current file associated URL changes during the decoding
|
||||
*/
|
||||
virtual void UrlChange(char *new_url)=0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class WInfo_callback
|
||||
{
|
||||
public:
|
||||
/* GetReader
|
||||
** Allows your WInfo classes to request a reader from Winamp
|
||||
** so you don't have to worry about opening files or streams
|
||||
*/
|
||||
virtual WReader *GetReader(char *url)=0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class WInputInfo
|
||||
{
|
||||
public:
|
||||
/* WInputInfo
|
||||
** WInputInfo constructor
|
||||
*/
|
||||
WInputInfo(){ };
|
||||
|
||||
/* m_info
|
||||
** Filled by Winamp. Pointer to WInputInfo callback function
|
||||
*/
|
||||
WInfo_callback *m_info;
|
||||
|
||||
/* Open
|
||||
** Called by Winamp to request informations about a specified media (file, url, etc...)
|
||||
** returns 0 if succesful, 1 if not
|
||||
**
|
||||
** You must open, get all information and close the specified file here and store
|
||||
** the useful information into member elements for quick access by other functions
|
||||
*/
|
||||
virtual int Open(char *url) { return 1; }
|
||||
|
||||
/* GetTitle
|
||||
** Called by Winamp to get the decoded title about the file opened
|
||||
** i.e. id3 title name, etc...
|
||||
*/
|
||||
virtual void GetTitle(char *buf, int maxlen) { if (maxlen>0) buf[0]=0; };
|
||||
|
||||
/* GetInfoString
|
||||
** Called by Winamp to get extra informations about the file opened
|
||||
** i.e. "160kbps stereo 44Khz" for MP3 files,"4 channels" for MOD files,etc...
|
||||
*/
|
||||
virtual void GetInfoString(char *buf, int maxlen) { if (maxlen>0) buf[0]=0; };
|
||||
|
||||
/* GetLength
|
||||
** Called by Winamp to retrieves media type length in milliseconds
|
||||
** returns -1 if length is undefined/infinite
|
||||
*/
|
||||
virtual int GetLength(void) { return -1; };
|
||||
|
||||
/* GetMetaData
|
||||
** Fetches metadata by attribute name (Artist, Album, Bitrate, etc...)
|
||||
** attribute names are non case-sensitive.
|
||||
** returns size of data
|
||||
*/
|
||||
virtual int GetMetaData(char *name, char *data, int data_len) { if (data&&data_len>0) *data=0; return 0; }
|
||||
|
||||
/* ~WInputInfo
|
||||
** WInputInfo virtual destructor
|
||||
*/
|
||||
//virtual ~WInputInfo() { };
|
||||
virtual void Release(int)=0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* WINAMP Output Filter NOTIFY MESSAGES
|
||||
** Messages returned to notify Output Filter plug-ins of events
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
|
||||
/* WOFNM_FILETITLECHANGE
|
||||
** Sent when the song changes
|
||||
** param1=new filename song
|
||||
** param2=new title song
|
||||
*/
|
||||
WOFNM_FILETITLECHANGE=1024,
|
||||
|
||||
/* WOFNM_ENDOFDECODE
|
||||
** Sent when decoding ends
|
||||
*/
|
||||
WOFNM_ENDOFDECODE,
|
||||
|
||||
} WOutputFilterNotifyMsg;
|
||||
|
||||
|
||||
|
||||
|
||||
class WOutputFilter
|
||||
{
|
||||
protected:
|
||||
/* WOutputFilter
|
||||
** WOutputFilter constructor
|
||||
*/
|
||||
WOutputFilter() { m_next=NULL; };
|
||||
|
||||
public:
|
||||
/* m_player
|
||||
** Filled by Winamp. Pointer to Winamp 3 core player interface
|
||||
*/
|
||||
WPlayer_callback *m_player;
|
||||
|
||||
/* m_next
|
||||
** Internally used by Winamp. Pointer to next activated Output Filter
|
||||
*/
|
||||
WOutputFilter *m_next;
|
||||
|
||||
/* ~WOutputFilter
|
||||
** WOutputFilter destructor
|
||||
*/
|
||||
//virtual ~WOutputFilter() { };
|
||||
virtual void Release(int)=0;
|
||||
|
||||
/* GetDescription
|
||||
** Retrieves your plug-in's text description
|
||||
*/
|
||||
virtual char *GetDescription() { return "Unknown"; };
|
||||
|
||||
/* ProcessSamples
|
||||
** Render data as it receives it
|
||||
** sampledata: Data to process
|
||||
** bytes: number of bytes to process
|
||||
** bps: Bits per sample (8 or 16)
|
||||
** nch: Number of channels (1 or 2)
|
||||
** srate: Sample rate in Hz
|
||||
** killswitch: Will be set to 1 by winamp if stop if requested. Poll the pointed value very often to
|
||||
** make sure Winamp doesn't hang
|
||||
**
|
||||
** Returns the number of processed bytes or -1 if unable to open the device or an error occured.
|
||||
**
|
||||
** You have to open your device (ie. Directsound) the first time this function is called.
|
||||
*/
|
||||
virtual int ProcessSamples(char *sampledata, int bytes, int *bps, int *nch, int *srate, bool *killswitch) { return bytes; }
|
||||
|
||||
/* FlushSamples
|
||||
** Flushes output buffers so that all is written
|
||||
*/
|
||||
virtual void FlushSamples(bool *killswitch) { };
|
||||
|
||||
/* Restart
|
||||
** Called by Winamp after a seek
|
||||
*/
|
||||
virtual void Restart(void) { }
|
||||
|
||||
/* GetLatency
|
||||
** Returns < 0 for a final output latency, > 0 for an additive
|
||||
*/
|
||||
virtual int GetLatency(void) { return 0; }
|
||||
|
||||
/* Pause
|
||||
** Suspends output
|
||||
*/
|
||||
virtual void Pause(int pause) { }
|
||||
|
||||
/* ShutDown
|
||||
** Completely stops output
|
||||
**
|
||||
** Close your device here (not in destructor)
|
||||
*/
|
||||
virtual void ShutDown(void) { }
|
||||
|
||||
/* SetVolume
|
||||
** Sets the volume (0 to 255)
|
||||
** return 1 if volume successfully modified
|
||||
*/
|
||||
virtual int SetVolume(int volume) { return 0; }
|
||||
|
||||
/* SetPan
|
||||
** Sets Left-Right sound balance (-127 to 127)
|
||||
** return 1 if pan successfully modified
|
||||
*/
|
||||
virtual int SetPan(int pan) { return 0; }
|
||||
|
||||
/* Notify
|
||||
** Called by Winamp to notify what's going on
|
||||
*/
|
||||
virtual void Notify(WOutputFilterNotifyMsg msg, int data1, int data2) { }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class WInputSource
|
||||
{
|
||||
|
||||
protected:
|
||||
/* WInputSource
|
||||
** WInputSource constructor
|
||||
*/
|
||||
WInputSource(){ };
|
||||
|
||||
|
||||
public:
|
||||
/* m_player
|
||||
** Filled by Winamp. Pointer to Winamp 3 core interface
|
||||
*/
|
||||
WPlayer_callback *m_player;
|
||||
|
||||
/* GetDescription
|
||||
** Retrieves your plug-in's text description
|
||||
*/
|
||||
virtual char *GetDescription() { return "Unknown"; };
|
||||
|
||||
/* UsesOutputFilters
|
||||
** Returns whether or not the Output Filter pipeline can be used
|
||||
*/
|
||||
virtual int UsesOutputFilters(void) { return 1; }
|
||||
|
||||
/* Open
|
||||
** Used to open and prepare input media type
|
||||
*/
|
||||
virtual int Open(char *url, bool *killswitch)=0;
|
||||
|
||||
/* GetSamples
|
||||
** This function must fill bps, nch and srate.
|
||||
** Here, you have to fill the sample_buffer with decoded data. Be sure to fill it with the specified
|
||||
** size (bytes). Use an internal buffer, etc ...
|
||||
**
|
||||
** sample_buffer: buffer to put decoded data into
|
||||
** bytes: size of the sample_buffer
|
||||
** bps: Bits par sample (8 or 16)
|
||||
** nch: Number of channels (1 or 2)
|
||||
** srate: Sample rate in Hz
|
||||
** killswitch: Will be set to 1 by winamp if stop if requested. Poll the pointed value very often to
|
||||
** make sure Winamp doesn't hang
|
||||
*/
|
||||
virtual int GetSamples(char *sample_buffer, int bytes, int *bps, int *nch, int *srate, bool *killswitch)=0;
|
||||
|
||||
/* SetVolume
|
||||
** Sets the volume (0 to 255)
|
||||
** Return 1 if volume has been set
|
||||
*/
|
||||
virtual int SetVolume(int volume) { return 0; };
|
||||
|
||||
/* SetPan
|
||||
** Sets Left-Right sound balance (-127 to 127)
|
||||
** return 1 if pan successfully modified
|
||||
*/
|
||||
virtual int SetPan(int pan) { return 0; };
|
||||
|
||||
/* SetPosition
|
||||
** Sets position in ms. returns 0 on success, 1 if seek impossible
|
||||
*/
|
||||
virtual int SetPosition(int)=0;
|
||||
|
||||
/* Pause
|
||||
** Suspends input
|
||||
*/
|
||||
virtual void Pause(int pause) { };
|
||||
|
||||
/* GetPosition
|
||||
** Retrieve position in milliseconds
|
||||
*/
|
||||
virtual int GetPosition(void) { return 0; }
|
||||
|
||||
/* GetTitle
|
||||
** Called by Winamp to get the decoded title about the file opened
|
||||
** i.e. stream name, id3 title name, etc...
|
||||
*/
|
||||
virtual void GetTitle(char *buf, int maxlen) { if(maxlen>0) buf[0]=0; };
|
||||
|
||||
/* GetInfoString
|
||||
** Called by Winamp to get extra informations about the file openend
|
||||
** i.e. "32kbps 44khz", etc...
|
||||
*/
|
||||
virtual void GetInfoString(char *buf, int maxlen) { if(maxlen>0) buf[0]=0; };
|
||||
|
||||
/* GetLength
|
||||
** Called by Winamp to retrieves media type length in milliseconds
|
||||
** returns -1 if length is undefined/infinite
|
||||
*/
|
||||
virtual int GetLength(void) { return -1; }
|
||||
|
||||
/* ~WInputSource
|
||||
** ~WInputSource virtual destructor
|
||||
*/
|
||||
//virtual ~WInputSource() { };
|
||||
virtual void Release(int)=0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class WReader
|
||||
{
|
||||
protected:
|
||||
|
||||
/* WReader
|
||||
** WReader constructor
|
||||
*/
|
||||
WReader() { }
|
||||
|
||||
public:
|
||||
|
||||
/* m_player
|
||||
** Filled by Winamp. Pointer to Winamp 3 core interface
|
||||
*/
|
||||
WPlayer_callback *m_player;
|
||||
|
||||
/* GetDescription
|
||||
** Retrieves your plug-in's text description
|
||||
*/
|
||||
virtual char *GetDescription() { return "Unknown"; };
|
||||
|
||||
/* Open
|
||||
** Used to open a file, return 0 on success
|
||||
*/
|
||||
virtual int Open(char *url, bool *killswitch)=0;
|
||||
|
||||
/* Read
|
||||
** Returns number of BYTES read (if < length then eof or killswitch)
|
||||
*/
|
||||
virtual int Read(char *buffer, int length, bool *killswitch)=0;
|
||||
|
||||
/* GetLength
|
||||
** Returns length of the entire file in BYTES, return -1 on unknown/infinite (as for a stream)
|
||||
*/
|
||||
virtual int GetLength(void)=0;
|
||||
|
||||
/* CanSeek
|
||||
** Returns 1 if you can skip ahead in the file, 0 if not
|
||||
*/
|
||||
virtual int CanSeek(void)=0;
|
||||
|
||||
/* Seek
|
||||
** Jump to a certain absolute position
|
||||
*/
|
||||
virtual int Seek(int position, bool *killswitch)=0;
|
||||
|
||||
/* GetHeader
|
||||
** Retrieve header. Used in read_http to retrieve the HTTP header
|
||||
*/
|
||||
virtual char *GetHeader(char *name) { return 0; }
|
||||
|
||||
/* ~WReader
|
||||
** WReader virtual destructor
|
||||
*/
|
||||
//virtual ~WReader() { }
|
||||
virtual void Release(int)=0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* DLL PLUGINS EXPORT STRUCTURES */
|
||||
|
||||
#define READ_VER 0x100
|
||||
#define IN_VER 0x100
|
||||
#define OF_VER 0x100
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* version
|
||||
** Version revision number
|
||||
*/
|
||||
int version;
|
||||
|
||||
/* description
|
||||
** Text description of the reader plug-in
|
||||
*/
|
||||
char *description;
|
||||
|
||||
/* create
|
||||
** Function pointer to create a reader module
|
||||
*/
|
||||
WReader *(*create)();
|
||||
|
||||
/* ismine
|
||||
** Determines whether or not a file should be read by this plug-in
|
||||
*/
|
||||
int (*ismine)(char *url);
|
||||
|
||||
} reader_source;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* version
|
||||
** Version revision number
|
||||
*/
|
||||
int version;
|
||||
|
||||
/* description
|
||||
** Text description of the input plug-in
|
||||
*/
|
||||
char *description;
|
||||
|
||||
/* extension_list
|
||||
** Defines all the supported filetypes by this input plug-in
|
||||
** In semicolon delimited format ("ext;desc;ext;desc" etc).
|
||||
*/
|
||||
char *extension_list;
|
||||
|
||||
/* ismine
|
||||
** called before extension checks, to allow detection of tone://,http://, etc
|
||||
** Determines whether or not a file type should be decoded by this plug-in
|
||||
*/
|
||||
int (*ismine)(char *filename);
|
||||
|
||||
/* create
|
||||
** Function pointer to create a decoder module
|
||||
*/
|
||||
WInputSource *(*create)(void);
|
||||
|
||||
/* createinfo
|
||||
** Function pointer to create a decoder module information
|
||||
*/
|
||||
WInputInfo *(*createinfo)(void);
|
||||
|
||||
} input_source;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* version
|
||||
** Version revision number
|
||||
*/
|
||||
int version;
|
||||
|
||||
/* description
|
||||
** Text description of the output plug-in
|
||||
*/
|
||||
char *description;
|
||||
|
||||
/* create
|
||||
** Function pointer to create an Output Filter
|
||||
*/
|
||||
WOutputFilter *(*create)();
|
||||
|
||||
} output_filter;
|
||||
|
||||
|
||||
#endif
|
@@ -1,459 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "decoder.h"
|
||||
#include <math.h>
|
||||
#include <locale.h>
|
||||
#pragma warning(disable:4244)
|
||||
#include "shaper.h"
|
||||
#include "api__in_vorbis.h"
|
||||
|
||||
Decoder::~Decoder() {if (shaper) delete shaper;}
|
||||
|
||||
extern CfgInt
|
||||
cfg_mc6_dm, cfg_mc6_map;
|
||||
/*
|
||||
if (vorbis_cfg.use_hq_preamp)
|
||||
{
|
||||
sample *= pow(10., preamp_db/20);
|
||||
|
||||
//hard 6dB limiting
|
||||
if (sample < -0.5)
|
||||
sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
|
||||
else if (sample > 0.5)
|
||||
sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
|
||||
} */
|
||||
|
||||
#if 0
|
||||
static float q_tanh(float x)
|
||||
{
|
||||
double foo1, foo2;
|
||||
foo1 = pow(2.71828182845904523536028747135266, x);
|
||||
foo2 = 1.0 / foo1;
|
||||
return (foo1 -foo2) / (foo1 + foo2);
|
||||
}
|
||||
#else
|
||||
#define q_tanh tanh
|
||||
#endif
|
||||
|
||||
float VorbisFile::GetGain()
|
||||
{
|
||||
float peak;
|
||||
|
||||
vorbis_comment * c;
|
||||
float scale = 1.0f;
|
||||
c = ov_comment(&vf, -1);
|
||||
peak = 0.99f;
|
||||
if (c)
|
||||
{
|
||||
if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain", false))
|
||||
{
|
||||
char * _peak = 0, *_gain = 0;
|
||||
float gain = 0;
|
||||
bool have_rg = 0;
|
||||
float lwing_gain = 0;
|
||||
char *gain1 = 0, *gain2 = 0, *peak1 = 0, *peak2 = 0;
|
||||
gain1 = vorbis_comment_query(c, "replaygain_album_gain", 0);
|
||||
if (!gain1) gain1 = vorbis_comment_query(c, "rg_audiophile", 0);
|
||||
gain2 = vorbis_comment_query(c, "replaygain_track_gain", 0);
|
||||
if (!gain2) gain2 = vorbis_comment_query(c, "rg_radio", 0);
|
||||
|
||||
peak1 = vorbis_comment_query(c, "replaygain_album_peak", 0);
|
||||
peak2 = vorbis_comment_query(c, "replaygain_track_peak", 0);
|
||||
switch (AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"replaygain_source", 0))
|
||||
{
|
||||
case 0: // track
|
||||
_gain = gain2;
|
||||
if (!_gain && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
||||
_gain = gain1;
|
||||
_peak = peak2;
|
||||
if (!_peak && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
||||
_peak = peak1;
|
||||
break;
|
||||
case 1: // album
|
||||
_gain = gain1;
|
||||
if (!_gain && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
||||
_gain = gain2;
|
||||
_peak = peak1;
|
||||
if (!_peak && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
||||
_peak = peak2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_peak)
|
||||
{
|
||||
_peak = vorbis_comment_query(c, "rg_peak", 0);
|
||||
}
|
||||
|
||||
_locale_t C_locale = WASABI_API_LNG->Get_C_NumericLocale();
|
||||
|
||||
if (_peak) peak = _atof_l(_peak, C_locale);
|
||||
if (_gain) gain = _atof_l(_gain, C_locale);
|
||||
|
||||
if (!_peak && !_gain)
|
||||
{
|
||||
char * l = vorbis_comment_query(c, "lwing_gain", 0);
|
||||
if (l)
|
||||
{
|
||||
lwing_gain = _atof_l(l, C_locale);
|
||||
have_rg = 1;
|
||||
}
|
||||
}
|
||||
else have_rg = 1;
|
||||
|
||||
if (!have_rg)
|
||||
{
|
||||
gain = AGAVE_API_CONFIG->GetFloat(playbackConfigGroupGUID, L"non_replaygain", -6.0f);
|
||||
}
|
||||
|
||||
scale = powf(10, (gain) / 20.0f);
|
||||
if (lwing_gain)
|
||||
scale *= lwing_gain;
|
||||
else if (have_rg)
|
||||
switch (AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"replaygain_mode", 1))
|
||||
{
|
||||
case 1: // apply gain, but don't clip
|
||||
if (scale*peak > 1.0) scale = 1.0 / peak;
|
||||
break;
|
||||
case 2: // normalize
|
||||
scale = 1.0 / peak;
|
||||
break;
|
||||
case 3: // no clipping
|
||||
if (peak > 1.0f)
|
||||
scale = 1.0 / peak;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
void Decoder::process_rg()
|
||||
{
|
||||
scale = file->GetGain();
|
||||
}
|
||||
|
||||
void Decoder::setup_mc()
|
||||
{
|
||||
if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"mono", false))
|
||||
nch = 1;
|
||||
else if (src_nch == 6)
|
||||
{
|
||||
switch (cfg_mc6_dm)
|
||||
{
|
||||
case 2:
|
||||
nch = 4;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
nch = 2;
|
||||
break;
|
||||
case 5:
|
||||
nch = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nch > 2 && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"surround", true))
|
||||
nch = 2;
|
||||
}
|
||||
}
|
||||
|
||||
void Decoder::Flush()
|
||||
{
|
||||
bptr = 0;
|
||||
pcmbuf = 0;
|
||||
data = 0;
|
||||
pos = 0;
|
||||
if (shaper) {delete shaper;shaper = 0;}
|
||||
}
|
||||
|
||||
void Decoder::Init(VorbisFile * f, UINT _bits, UINT _nch, bool _useFloat, bool allowRG)
|
||||
{
|
||||
useFloat = _useFloat;
|
||||
|
||||
file = f;
|
||||
vorbis_info * i = ov_info(&file->vf, -1);
|
||||
|
||||
if (allowRG)
|
||||
process_rg();
|
||||
else
|
||||
scale = 1.0f;
|
||||
|
||||
if (useFloat)
|
||||
{
|
||||
dither = false;
|
||||
bps = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
dither = AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"dither", true);
|
||||
|
||||
if (_bits)
|
||||
bps = _bits;
|
||||
else
|
||||
bps = AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"bits", 16);
|
||||
}
|
||||
|
||||
if (useFloat)
|
||||
{
|
||||
clipmin = -10000; // some arbitrarily large number
|
||||
clipmax = 10000; // some arbitrarily large number
|
||||
}
|
||||
else
|
||||
{
|
||||
clipmin = - (1 << (bps - 1));
|
||||
clipmax = (1 << (bps - 1)) - 1;
|
||||
}
|
||||
sr = i->rate;
|
||||
nch = src_nch = i->channels;
|
||||
Flush();
|
||||
cur_link = file->vf.current_link;
|
||||
|
||||
if (_nch)
|
||||
nch = _nch;
|
||||
else
|
||||
setup_mc();
|
||||
}
|
||||
|
||||
UINT Decoder::DataAvailable()
|
||||
{
|
||||
return data * (bps >> 3);
|
||||
}
|
||||
|
||||
int Decoder::DoFrame()
|
||||
{
|
||||
need_reopen = 0;
|
||||
while (1)
|
||||
{
|
||||
data = ov_read_float(&file->vf, &pcmbuf, 576, 0);
|
||||
if ((int)data <= 0)
|
||||
{
|
||||
if (data == OV_HOLE) {continue;}
|
||||
data = 0;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
if (cur_link != file->vf.current_link)
|
||||
{
|
||||
vorbis_info* i = ov_info(&file->vf, -1);
|
||||
if (sr != (UINT)i->rate || src_nch != (UINT)i->channels)
|
||||
{
|
||||
UINT old_nch = nch, old_sr = sr;
|
||||
if (shaper) {delete shaper;shaper = 0;}
|
||||
sr = i->rate;
|
||||
src_nch = nch = i->channels;
|
||||
setup_mc();
|
||||
if (nch != old_nch || sr != old_sr)
|
||||
{
|
||||
need_reopen = 1;
|
||||
}
|
||||
}
|
||||
process_rg();
|
||||
cur_link = file->vf.current_link;
|
||||
}
|
||||
data *= nch;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Decoder::Read(UINT bytes, void * buf)
|
||||
{
|
||||
UINT wr = 0;
|
||||
if (buf && bytes && data > 0)
|
||||
{
|
||||
char* out = (char*)buf;
|
||||
UINT d;
|
||||
double mul;
|
||||
int ofs;
|
||||
float * img;
|
||||
|
||||
d = bytes / (bps >> 3);
|
||||
if (d > data) d = data;
|
||||
if (!d) return 0;
|
||||
data -= d;
|
||||
if (useFloat)
|
||||
{
|
||||
mul = 1.0;
|
||||
ofs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mul = (double)( (1 << ((bps) - 1)) - 1 );
|
||||
ofs = (bps == 8) ? 0x80 : 0;
|
||||
}
|
||||
wr += d * (bps >> 3);
|
||||
|
||||
img = (float*)alloca(sizeof(float) * nch);
|
||||
do
|
||||
{
|
||||
UINT cur_ch;
|
||||
if (nch == 1 && src_nch > 0)
|
||||
{
|
||||
UINT c;
|
||||
img[0] = 0;
|
||||
for (c = 0;c < src_nch;c++)
|
||||
{
|
||||
img[0] += pcmbuf[c][pos];
|
||||
}
|
||||
img[0] /= (float)src_nch;
|
||||
}
|
||||
else if (nch == src_nch && !(nch == 6 && cfg_mc6_dm == 1))
|
||||
{
|
||||
UINT c;
|
||||
for (c = 0;c < nch;c++)
|
||||
{
|
||||
img[c] = pcmbuf[c][pos];
|
||||
}
|
||||
}
|
||||
else if (src_nch == 6)
|
||||
{
|
||||
UINT FL, FR, C;
|
||||
if (cfg_mc6_map == 1)
|
||||
{
|
||||
FL = 0;
|
||||
FR = 1;
|
||||
C = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
FL = 0;
|
||||
C = 1;
|
||||
FR = 2;
|
||||
}
|
||||
|
||||
if (nch == 6)
|
||||
{ //remap order for correct 5.1 output
|
||||
img[0] = pcmbuf[FL][pos];
|
||||
img[1] = pcmbuf[FR][pos];
|
||||
img[2] = pcmbuf[C][pos];
|
||||
img[3] = pcmbuf[5][pos];
|
||||
img[4] = pcmbuf[3][pos];
|
||||
img[5] = pcmbuf[4][pos];
|
||||
}
|
||||
else if (nch == 2)
|
||||
{
|
||||
/*
|
||||
FL FR C BL BR LFE
|
||||
0 1 2 3 4 5
|
||||
|
||||
L,C,R,SL,SR,LFE
|
||||
0 1 2 3 4 5
|
||||
|
||||
|
||||
output:
|
||||
FL FR C LFE BL BR
|
||||
|
||||
|
||||
stereo:
|
||||
Lt=L+0.707*(V-SL-SR+LFE)
|
||||
Rt=R+0.707*(C+SL+SR+LFE)
|
||||
|
||||
|
||||
Lt=L+0.707*(C+LFE)
|
||||
Rt=R+0.707*(C+LFE)
|
||||
SLt=SL
|
||||
SRt=SR
|
||||
|
||||
*/
|
||||
if (cfg_mc6_dm == 4) //ds2
|
||||
{
|
||||
const double a = pow(10., 1.5 / 20.), b = 1 / a;
|
||||
img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] - a * pcmbuf[3][pos] - b * pcmbuf[4][pos] + pcmbuf[5][pos]);
|
||||
img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + b * pcmbuf[3][pos] + a * pcmbuf[4][pos] + pcmbuf[5][pos]);
|
||||
}
|
||||
else
|
||||
{
|
||||
img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] - pcmbuf[3][pos] - pcmbuf[4][pos] + pcmbuf[5][pos]);
|
||||
img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[3][pos] + pcmbuf[4][pos] + pcmbuf[5][pos]);
|
||||
}
|
||||
}
|
||||
else if (nch == 4)
|
||||
{
|
||||
img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[5][pos]);
|
||||
img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[5][pos]);
|
||||
img[2] = pcmbuf[3][pos];
|
||||
img[3] = pcmbuf[4][pos];
|
||||
}
|
||||
}
|
||||
|
||||
for (cur_ch = 0;cur_ch < nch;cur_ch++)
|
||||
{
|
||||
float v = img[cur_ch];
|
||||
int val;
|
||||
v *= scale;
|
||||
v *= mul;
|
||||
if (dither)
|
||||
{
|
||||
if (!shaper)
|
||||
{
|
||||
//Shaper(int freq,int _nch,int min,int max,int _dtype,int pdf,double noiseamp);
|
||||
shaper = new Shaper(sr, nch, clipmin, clipmax, 2, DITHER_TRIANGLE, 0);
|
||||
}
|
||||
// double peak=0;
|
||||
val = shaper->do_shaping(v /*,&peak*/, cur_ch);
|
||||
//shaper clips for us
|
||||
}
|
||||
else
|
||||
{
|
||||
val = (int)v;
|
||||
if (val < clipmin) val = clipmin;
|
||||
else if (val > clipmax) val = clipmax;
|
||||
//1<<16 = 0x10000
|
||||
|
||||
}
|
||||
val += ofs;
|
||||
|
||||
switch (bps)
|
||||
{
|
||||
case 8:
|
||||
*(BYTE*)out = (UINT)val;
|
||||
break;
|
||||
case 16:
|
||||
*(short*)out = val;
|
||||
break;
|
||||
case 24:
|
||||
{
|
||||
((BYTE*)out)[0] = (UINT)val;
|
||||
((BYTE*)out)[1] = (UINT)val >> 8;
|
||||
((BYTE*)out)[2] = (UINT)val >> 16;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
if (useFloat)
|
||||
{
|
||||
*(float *)out = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
//*(long*)out=val;
|
||||
//break;
|
||||
*(long*)out = 0;
|
||||
}
|
||||
break;
|
||||
};
|
||||
out += (bps >> 3);
|
||||
d--;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
while (d);
|
||||
|
||||
}
|
||||
return wr;
|
||||
}
|
||||
|
||||
int VorbisFile::Seek(double p) { return ov_time_seek(&vf, p);}
|
||||
|
||||
int Decoder::Seek(double p)
|
||||
{
|
||||
Flush();
|
||||
return file->Seek(p);
|
||||
}
|
||||
|
||||
//char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count)
|
||||
const char* VorbisFile::get_meta(const char* tag, UINT c)
|
||||
{
|
||||
return vorbis_comment_query(vf.seekable ? vf.vc + vf.current_link : vf.vc, (char*)tag, c);
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
class Shaper;
|
||||
|
||||
class Decoder
|
||||
{
|
||||
private:
|
||||
void process_rg();
|
||||
void setup_mc();
|
||||
float* bptr;
|
||||
float** pcmbuf;
|
||||
Shaper * shaper;
|
||||
UINT data,pos;
|
||||
float scale;
|
||||
int cur_link;
|
||||
int cur_preamp;
|
||||
int clipmin,clipmax;
|
||||
public:
|
||||
VorbisFile * file;
|
||||
|
||||
UINT nch,sr,kbps,bps,src_nch;
|
||||
|
||||
Decoder()
|
||||
{
|
||||
memset(this,0,sizeof(*this));
|
||||
}
|
||||
|
||||
~Decoder();
|
||||
|
||||
int Seek(double p);
|
||||
int Read(UINT bytes,void * buf);
|
||||
void Flush();
|
||||
void Init(VorbisFile * f, UINT _bits=0, UINT _nch=0, bool _useFloat=false, bool allowRG=true);
|
||||
void wa2_setinfo(UINT cur_bitrate);
|
||||
|
||||
UINT DataAvailable();
|
||||
int DoFrame();
|
||||
bool need_reopen;
|
||||
int play_init();
|
||||
bool play_inited;
|
||||
bool dither;
|
||||
bool useFloat;
|
||||
};
|
@@ -1,97 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "genres.h"
|
||||
#include <shlwapi.h>
|
||||
|
||||
extern const wchar_t *INI_DIRECTORY;
|
||||
|
||||
static void file_init(wchar_t *file_path, wchar_t *fn)
|
||||
{
|
||||
PathCombineW(file_path, INI_DIRECTORY, fn);
|
||||
}
|
||||
|
||||
static char eol[2]={13,10};
|
||||
|
||||
static char get_char(HANDLE f,BOOL * eof)
|
||||
{
|
||||
DWORD br=0;
|
||||
char r=0;
|
||||
ReadFile(f,&r,1,&br,0);
|
||||
if (!br) *eof=1;
|
||||
return r;
|
||||
}
|
||||
|
||||
void genres_read(HWND wnd, wchar_t* fn)
|
||||
{
|
||||
char temp[MAX_GENRE] = {0};
|
||||
char add[MAX_GENRE] = {0};
|
||||
BOOL eof=0;
|
||||
char c = 0;
|
||||
wchar_t file_path[MAX_PATH] = {0};
|
||||
HANDLE f;
|
||||
|
||||
file_init(file_path, fn);
|
||||
|
||||
f = CreateFileW(file_path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if (f==INVALID_HANDLE_VALUE) return;
|
||||
GetWindowTextA(wnd,add,MAX_GENRE);
|
||||
while(!eof)
|
||||
{
|
||||
UINT ptr=0;
|
||||
BOOL start=1;
|
||||
while(ptr<MAX_GENRE-1)
|
||||
{
|
||||
c=get_char(f,&eof);
|
||||
if (eof) break;
|
||||
if (c==10 || c==13)
|
||||
{
|
||||
if (start) continue;
|
||||
else break;
|
||||
}
|
||||
start=0;
|
||||
temp[ptr++]=c;
|
||||
}
|
||||
if (ptr)
|
||||
{
|
||||
temp[ptr]=0;
|
||||
SendMessage(wnd,CB_ADDSTRING,0, (LPARAM)temp);
|
||||
if (add[0])
|
||||
{
|
||||
if (!_stricmp(add,temp)) add[0]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(f);
|
||||
if (add[0]) SendMessage(wnd,CB_ADDSTRING,0,(LPARAM)add);
|
||||
}
|
||||
|
||||
void genres_write(HWND wnd, wchar_t* fn)
|
||||
{
|
||||
wchar_t file_path[MAX_PATH] = {0};
|
||||
char temp[MAX_GENRE] = {0};
|
||||
UINT max = 0,n = 0;
|
||||
DWORD bw = 0;
|
||||
HANDLE f;
|
||||
{
|
||||
char add[MAX_GENRE] = {0};
|
||||
GetWindowTextA(wnd,add,MAX_GENRE);
|
||||
if (!add[0]) return;
|
||||
max=(UINT)SendMessage(wnd,CB_GETCOUNT,0,0);
|
||||
for(n=0;n<max;n++)
|
||||
{
|
||||
SendMessage(wnd,CB_GETLBTEXT,n,(LPARAM)temp);
|
||||
if (!_stricmp(temp,add)) return;
|
||||
}
|
||||
SendMessage(wnd,CB_ADDSTRING,0,(LPARAM)add);
|
||||
}
|
||||
file_init(file_path, fn);
|
||||
f = CreateFileW(file_path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
if (f==INVALID_HANDLE_VALUE) return;
|
||||
max=(UINT)SendMessage(wnd,CB_GETCOUNT,0,0);
|
||||
for(n=0;n<max;n++)
|
||||
{
|
||||
SendMessage(wnd,CB_GETLBTEXT,n,(LPARAM)temp);
|
||||
bw = 0; WriteFile(f,temp,(DWORD)strlen(temp),&bw,0);
|
||||
bw = 0; WriteFile(f,eol,2,&bw,0);
|
||||
}
|
||||
CloseHandle(f);
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
#ifndef NULLSOFT_IN_VORBIS_GENRES_H
|
||||
#define NULLSOFT_IN_VORBIS_GENRES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void genres_read(HWND wnd, wchar_t* fn);
|
||||
void genres_write(HWND wnd, wchar_t* fn);
|
||||
#define MAX_GENRE 256
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -1,596 +0,0 @@
|
||||
#include "api__in_vorbis.h"
|
||||
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
|
||||
#include "rf.h"
|
||||
#include "main.h"
|
||||
#include "../Winamp/wa_ipc.h"
|
||||
#include <api/service/waservicefactory.h>
|
||||
#include "../nu/AutoWide.h"
|
||||
#include "../nu/AutoChar.h"
|
||||
extern CfgInt cfg_fix0r,cfg_httpseek2,cfg_proxy_mode,cfg_prebuf1,cfg_prebuf2,cfg_fsave,cfg_http_bsize;
|
||||
|
||||
#define CANSEEK
|
||||
|
||||
WORD *wdup(const char * src);//info.c
|
||||
|
||||
#define zeromem(x) memset(&x,0,sizeof(x))
|
||||
|
||||
class StreamSave
|
||||
{
|
||||
private:
|
||||
ogg_sync_state oy_src;
|
||||
ogg_stream_state os_src;
|
||||
ogg_stream_state os_dst;
|
||||
ogg_page og_src;
|
||||
ogg_page og_dst;
|
||||
ogg_packet op;
|
||||
StringW tmp_fn;
|
||||
BOOL is_temp;
|
||||
BOOL got_streams,got_delta,use_fix0r;
|
||||
ogg_int64_t pcm_delta;
|
||||
int packets,serial;
|
||||
HANDLE hFile;
|
||||
public:
|
||||
|
||||
StreamSave()
|
||||
{
|
||||
zeromem(oy_src);
|
||||
zeromem(os_src);
|
||||
zeromem(os_dst);
|
||||
zeromem(og_src);
|
||||
zeromem(og_dst);
|
||||
zeromem(op);
|
||||
got_streams=0;
|
||||
got_delta=0;
|
||||
pcm_delta=0;
|
||||
hFile=0;
|
||||
packets=0;
|
||||
serial=0;
|
||||
is_temp=1;
|
||||
|
||||
tmp_fn=cfg_dumpdir;
|
||||
if (tmp_fn[tmp_fn.Length()-1]!='\\') tmp_fn.AddChar('\\');
|
||||
|
||||
tmp_fn+=StringPrintfW(L"oggtemp%u.foo",GetTickCount64()&0xFFFF);
|
||||
|
||||
hFile=CreateFileW(tmp_fn,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_HIDDEN,0);
|
||||
if (hFile==INVALID_HANDLE_VALUE) hFile=0;
|
||||
else
|
||||
{
|
||||
ogg_sync_init(&oy_src);
|
||||
use_fix0r=cfg_fix0r;
|
||||
}
|
||||
};
|
||||
|
||||
void Write(void * ptr,UINT siz)
|
||||
{
|
||||
if (!hFile) return;
|
||||
|
||||
void * b=ogg_sync_buffer(&oy_src,siz);
|
||||
memcpy(b,ptr,siz);
|
||||
ogg_sync_wrote(&oy_src,siz);
|
||||
|
||||
while(ogg_sync_pageout(&oy_src,&og_src)>0)
|
||||
{
|
||||
if (!got_streams)
|
||||
{
|
||||
serial=ogg_page_serialno(&og_src);
|
||||
ogg_stream_init(&os_src,serial);
|
||||
ogg_stream_init(&os_dst,serial);
|
||||
got_streams=1;
|
||||
packets=0;
|
||||
got_delta=0;
|
||||
}
|
||||
else if (serial!=ogg_page_serialno(&og_src))
|
||||
{
|
||||
if (got_streams)
|
||||
{
|
||||
/*while(ogg_stream_flush(&os_dst,&og_dst))
|
||||
{
|
||||
write_page(dst,&og_dst,&wb);
|
||||
}*/
|
||||
|
||||
ogg_stream_clear(&os_src);
|
||||
ogg_stream_clear(&os_dst);
|
||||
}
|
||||
serial=ogg_page_serialno(&og_src);
|
||||
ogg_stream_init(&os_src,serial);
|
||||
ogg_stream_init(&os_dst,serial);
|
||||
|
||||
packets=0;
|
||||
got_delta=0;
|
||||
}
|
||||
|
||||
ogg_stream_pagein(&os_src,&og_src);
|
||||
while(ogg_stream_packetout(&os_src,&op)>0)
|
||||
{
|
||||
if (use_fix0r && !got_delta && packets>2 && op.granulepos>=0) //hack to fix saved streams
|
||||
{
|
||||
got_delta=1;
|
||||
if (op.granulepos>4096*(packets-2)) pcm_delta=op.granulepos;
|
||||
}
|
||||
if (got_delta)
|
||||
{
|
||||
if (op.granulepos>=pcm_delta) op.granulepos-=pcm_delta;
|
||||
else if (op.granulepos>0) op.granulepos=0;
|
||||
}
|
||||
ogg_stream_packetin(&os_dst,&op);
|
||||
packets++;
|
||||
}
|
||||
|
||||
while((packets==3 ? ogg_stream_flush(&os_dst,&og_dst) : ogg_stream_pageout(&os_dst,&og_dst))>0)
|
||||
{
|
||||
DWORD bw = 0;
|
||||
WriteFile(hFile,og_dst.header,og_dst.header_len,&bw,0);
|
||||
bw = 0; WriteFile(hFile,og_dst.body,og_dst.body_len,&bw,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixName(VorbisFile * vf,const char * streamname)
|
||||
{
|
||||
if (!hFile) return;
|
||||
CloseHandle(hFile);
|
||||
StringW fn(cfg_dumpdir);
|
||||
|
||||
if (fn[fn.Length()-1]!='\\') fn.AddChar('\\');
|
||||
|
||||
UINT n=fn.Length();
|
||||
fn+=(wchar_t *)AutoWide(vf->get_meta("TITLE", 0), CP_UTF8);
|
||||
UINT m=fn.Length();
|
||||
|
||||
while(n<m)
|
||||
{
|
||||
char * b="/\\:*?\"<>|";
|
||||
while(b && *b)
|
||||
{
|
||||
if (fn[n]==*b) {fn.SetChar(n,'_');break;}
|
||||
b++;
|
||||
}
|
||||
n++;
|
||||
};
|
||||
fn.AddStringA(".ogg");
|
||||
if (!MoveFileW(tmp_fn,fn))
|
||||
{
|
||||
DeleteFileW(fn);
|
||||
MoveFileW(tmp_fn,fn);
|
||||
}
|
||||
SetFileAttributesW(fn,FILE_ATTRIBUTE_NORMAL);
|
||||
hFile=CreateFileW(fn,GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
|
||||
|
||||
if (hFile==INVALID_HANDLE_VALUE) {hFile=0;}
|
||||
else SetFilePointer(hFile,0,0,FILE_END);
|
||||
is_temp=0;
|
||||
}
|
||||
|
||||
~StreamSave()
|
||||
{
|
||||
if (hFile)
|
||||
{
|
||||
/*if (got_streams)
|
||||
{
|
||||
while(ogg_stream_flush(&os_dst,&og_dst))
|
||||
{
|
||||
write_page(dst,&og_dst,&wb);
|
||||
}
|
||||
}*/
|
||||
|
||||
ogg_stream_clear(&os_src);
|
||||
ogg_stream_clear(&os_dst);
|
||||
|
||||
SetFilePointer(hFile,0,0,FILE_CURRENT);
|
||||
CloseHandle(hFile);
|
||||
if (is_temp) DeleteFileW(tmp_fn);
|
||||
}
|
||||
ogg_sync_clear(&oy_src);
|
||||
}
|
||||
};
|
||||
|
||||
static const char * do_proxy(const char * url)
|
||||
{
|
||||
switch(cfg_proxy_mode)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case 1:
|
||||
{
|
||||
const char * p=strstr(url,"://");
|
||||
if (!p) p=url;
|
||||
while(p && *p && *p!=':' && *p!='/') p++;
|
||||
if (p && *p==':')
|
||||
{
|
||||
if (atoi(p+1)!=80) return 0;
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
char *x = (char *)SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GET_PROXY_STRING);
|
||||
if (x == (char *)1 || !x || !*x)
|
||||
return 0;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VorbisFile_HTTP : public VorbisFile
|
||||
{
|
||||
protected:
|
||||
api_httpreceiver *get;
|
||||
UINT bsize;
|
||||
uint64_t len;
|
||||
UINT pos;
|
||||
UINT seekpos;
|
||||
BOOL can_seek;
|
||||
StreamSave * saver;
|
||||
virtual void Idle();
|
||||
virtual int f_seek(__int64 offset,int whence);
|
||||
virtual size_t f_read(UINT siz,void * ptr);
|
||||
virtual UINT f_tell();
|
||||
virtual UINT FileSize() {return len;}
|
||||
bool is_live;
|
||||
|
||||
public:
|
||||
virtual int GetType() {return TYPE_HTTP;}
|
||||
virtual bool IsLive() {return is_live;}
|
||||
bool http_init();
|
||||
|
||||
void do_prebuf() {VorbisFile::do_prebuf();fillbuf(bsize * cfg_prebuf1 / 100,0);}
|
||||
|
||||
VorbisFile_HTTP(UINT s, const wchar_t *u,bool is_info, bool hasauth) : VorbisFile(u,is_info), usedauth(hasauth)
|
||||
{
|
||||
get=0;
|
||||
can_seek=0;
|
||||
len=pos=seekpos=0;
|
||||
bsize=s;
|
||||
saver=0;
|
||||
m_needs_auth=0;
|
||||
lpinfo[0]=0;
|
||||
force_lpinfo[0]=0;
|
||||
is_live = false;
|
||||
memset(dlg_realm, 0, sizeof(dlg_realm));
|
||||
}
|
||||
|
||||
~VorbisFile_HTTP()
|
||||
{
|
||||
if (get)
|
||||
{
|
||||
waServiceFactory *sf = mod.service->service_getServiceByGuid(httpreceiverGUID);
|
||||
if (sf)
|
||||
sf->releaseInterface(get);
|
||||
get=0;
|
||||
}
|
||||
if (saver) delete saver;
|
||||
}
|
||||
|
||||
void fillbuf(UINT max,bool shutup);
|
||||
|
||||
size_t _http_read(char* ptr,size_t total);
|
||||
int reconnect(UINT ofs);
|
||||
virtual void post_init()
|
||||
{
|
||||
if (saver) saver->FixName(this,get->getheader("ice-name"));
|
||||
}
|
||||
|
||||
static BOOL CALLBACK httpDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
||||
int m_needs_auth;
|
||||
char dlg_realm[256];
|
||||
char lpinfo[256];
|
||||
char force_lpinfo[256];
|
||||
bool usedauth;
|
||||
};
|
||||
|
||||
int VorbisFile_HTTP::reconnect(UINT ofs)
|
||||
{
|
||||
// get.reset_headers();
|
||||
get->addheader("User-Agent: WinampOGG/5.24(MPEG stream compatible)");
|
||||
get->addheader("Accept:*/*");
|
||||
if (ofs>0) get->addheader(StringPrintf("Range: bytes=%u-",ofs));
|
||||
get->connect(AutoChar(url));
|
||||
|
||||
Status(WASABI_API_LNGSTRINGW(IDS_CONNECTING));
|
||||
|
||||
int st=get->run();
|
||||
if (st<0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VorbisFile_HTTP::fillbuf(UINT max,bool shutup)
|
||||
{
|
||||
if (len>0 && pos+max>len) max=len-pos;
|
||||
while(!Aborting() && !abort_prebuf) //stop prebuffering if we wanna seek
|
||||
{
|
||||
if (!shutup)
|
||||
{
|
||||
Status(StringPrintfW(WASABI_API_LNGSTRINGW(IDS_PREBUFFERING), get->bytes_available()*100/bsize));
|
||||
}
|
||||
if (get->run()) break;
|
||||
if (Aborting() || abort_prebuf || get->bytes_available()>=(int)max) break;
|
||||
Sleep(2);
|
||||
}
|
||||
if (!shutup)
|
||||
{
|
||||
Status(0);
|
||||
}
|
||||
}
|
||||
|
||||
size_t VorbisFile_HTTP::_http_read(char* ptr,size_t total)
|
||||
{
|
||||
#ifdef CANSEEK
|
||||
if (seekpos!=-1)
|
||||
{
|
||||
UINT sp=seekpos;
|
||||
seekpos=-1;
|
||||
if (sp!=pos)
|
||||
{
|
||||
if (sp>pos && sp<=pos+get->bytes_available())
|
||||
{
|
||||
get->get_bytes(0,sp-pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reconnect(sp))
|
||||
{
|
||||
return 0;//oh well...
|
||||
}
|
||||
}
|
||||
pos=sp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
UINT wr=0;
|
||||
while(!Aborting() && wr<total)
|
||||
{
|
||||
int st=get->run();
|
||||
int d=get->get_bytes(ptr,(int)total-wr);
|
||||
if (st && !d) break;
|
||||
wr+=d;
|
||||
ptr+=d;
|
||||
pos+=d;
|
||||
if ((len>0 && pos>=len) || wr>=total || Aborting()) break;
|
||||
if (use_prebuf) fillbuf(bsize * cfg_prebuf2 / 100,0);
|
||||
else Sleep(1);
|
||||
}
|
||||
return wr;
|
||||
}
|
||||
|
||||
void VorbisFile_HTTP::Idle()
|
||||
{
|
||||
get->run();
|
||||
Sleep(1);
|
||||
get->run();
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
size_t VorbisFile_HTTP::f_read(UINT siz,void* ptr)
|
||||
{
|
||||
if (Aborting()) return 0;//fixme
|
||||
int i=(int)_http_read((char*)ptr,siz);
|
||||
if (i>0 && saver) saver->Write(ptr,i);
|
||||
return i;
|
||||
}
|
||||
|
||||
int VorbisFile_HTTP::f_seek(ogg_int64_t offset,int whence)
|
||||
{
|
||||
#ifdef CANSEEK
|
||||
if (can_seek)
|
||||
{
|
||||
switch(whence)
|
||||
{
|
||||
case FILE_BEGIN:
|
||||
seekpos=(int)offset;
|
||||
break;
|
||||
case FILE_END:
|
||||
seekpos=len+(int)offset;
|
||||
break;
|
||||
case FILE_CURRENT:
|
||||
seekpos=pos+(int)offset;
|
||||
break;
|
||||
}
|
||||
if (seekpos>len) seekpos=len;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
UINT VorbisFile_HTTP::f_tell()
|
||||
{
|
||||
#ifdef CANSEEK
|
||||
if (can_seek)
|
||||
{
|
||||
if (seekpos!=-1) return seekpos;
|
||||
else return pos;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWND GetDialogBoxParent()
|
||||
{
|
||||
HWND parent = (HWND)SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT);
|
||||
if (!parent || parent == (HWND)1)
|
||||
return mod.hMainWindow;
|
||||
return parent;
|
||||
}
|
||||
|
||||
bool VorbisFile_HTTP::http_init()
|
||||
{
|
||||
if (mod.service)
|
||||
{
|
||||
waServiceFactory *sf = mod.service->service_getServiceByGuid(httpreceiverGUID);
|
||||
if (sf) get = (api_httpreceiver *)sf->getInterface();
|
||||
}
|
||||
if (!get) return false;
|
||||
get->open(API_DNS_AUTODNS, bsize, do_proxy(AutoChar(url)));
|
||||
|
||||
if (reconnect(0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CANSEEK
|
||||
// if (cfg_httpseek)
|
||||
{
|
||||
//need to get http headers first
|
||||
while(!memcmp(get->getallheaders(),"\0\0",2))
|
||||
{
|
||||
if (get->run()<0 || Aborting())
|
||||
{
|
||||
int reply = get->getreplycode();
|
||||
if ( reply == 401 )
|
||||
{
|
||||
api_connection *mcon=get->GetConnection();
|
||||
if ( mcon && mcon->GetReceiveBytesAvailable())
|
||||
{
|
||||
char p[1024]="";
|
||||
while ( mcon->GetReceiveBytesAvailable() )
|
||||
{
|
||||
char b[2048]="";
|
||||
mcon->ReceiveLine(b,2048);
|
||||
if ( *b )
|
||||
{
|
||||
char *t= strstr(b,"WWW-Authenticate:");
|
||||
if ( t && *t )
|
||||
{
|
||||
char *y = strstr(t,"\"");
|
||||
if ( y && *y )
|
||||
{
|
||||
y++;
|
||||
if ( *y )
|
||||
{
|
||||
char *u = strstr(y,"\"");
|
||||
if ( u && *u )
|
||||
{
|
||||
*u = 0;
|
||||
wsprintfA(p,"%s",y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( *p ) // found our realm
|
||||
{
|
||||
if (!force_lpinfo[0]) GetPrivateProfileStringA("HTTP-AUTH",p,"",force_lpinfo,sizeof(force_lpinfo),INI_FILE);
|
||||
if (!force_lpinfo[0] || lpinfo[0] || usedauth )
|
||||
{
|
||||
lstrcpynA(dlg_realm,p,sizeof(dlg_realm));
|
||||
if (!WASABI_API_DIALOGBOXPARAM(IDD_HTTPAUTH, GetDialogBoxParent(), httpDlgProc, (LPARAM)this))
|
||||
{
|
||||
force_lpinfo[0]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePrivateProfileStringA("HTTP-AUTH",p,force_lpinfo,INI_FILE);
|
||||
}
|
||||
}
|
||||
Status(WASABI_API_LNGSTRINGW(IDS_AUTH_REQUIRED));
|
||||
m_needs_auth=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//hg->get.wait(10);
|
||||
Sleep(1);
|
||||
}
|
||||
len=get->content_length();
|
||||
const char* poo=get->getheader("icy-name");
|
||||
if (poo) stream_title=poo;
|
||||
if (cfg_httpseek2 && len) can_seek=1;
|
||||
is_live=(len<=0);
|
||||
}
|
||||
#endif
|
||||
|
||||
//if (hg->len==0 || hg->len==-1) hg->can_seek=0;
|
||||
seekpos=-1;
|
||||
|
||||
if (cfg_fsave && !can_seek)
|
||||
{
|
||||
saver=new StreamSave;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
VorbisFile * VorbisFile::Create_HTTP(const char * url,bool is_info)
|
||||
{
|
||||
VorbisFile_HTTP * r=new VorbisFile_HTTP(cfg_http_bsize,AutoWide(url),is_info, false);
|
||||
if (r)
|
||||
{
|
||||
if (!r->http_init())
|
||||
{
|
||||
int trys=0;
|
||||
while ( r && r->m_needs_auth && trys++ < 2)
|
||||
{
|
||||
const char *p=strstr(url,"://");
|
||||
if (p && *p)
|
||||
{
|
||||
p += 3;
|
||||
if (p && *p)
|
||||
{
|
||||
char lurl[4096] = {0};
|
||||
wsprintfA(lurl, "http://%s@%s", r->force_lpinfo, p);
|
||||
delete r;
|
||||
r = new VorbisFile_HTTP(cfg_http_bsize,AutoWide(lurl),is_info, true);
|
||||
if (r && r->http_init())
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete r;
|
||||
r=0;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
BOOL CALLBACK VorbisFile_HTTP::httpDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
VorbisFile_HTTP *_this;
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
#ifdef WIN64
|
||||
SetWindowLong(hwndDlg, GWLP_USERDATA, (LONG)lParam);
|
||||
_this = (VorbisFile_HTTP*)(GetWindowLong(hwndDlg, GWLP_USERDATA));
|
||||
#else
|
||||
SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)lParam);
|
||||
_this = (VorbisFile_HTTP*)GetWindowLong(hwndDlg, GWL_USERDATA);
|
||||
#endif
|
||||
if (_this->force_lpinfo[0])
|
||||
SetDlgItemTextA(hwndDlg,IDC_EDITAUTH,_this->force_lpinfo);
|
||||
else SetDlgItemTextA(hwndDlg,IDC_EDITAUTH,_this->lpinfo);
|
||||
SetDlgItemTextA(hwndDlg,IDC_REALM,_this->dlg_realm);
|
||||
return 1;
|
||||
|
||||
case WM_COMMAND:
|
||||
#ifdef WIN64
|
||||
_this = (VorbisFile_HTTP*)GetWindowLong(hwndDlg, GWLP_USERDATA);
|
||||
#else
|
||||
_this = (VorbisFile_HTTP*)GetWindowLong(hwndDlg, GWL_USERDATA);
|
||||
#endif
|
||||
if (LOWORD(wParam) == IDOKAUTH)
|
||||
{
|
||||
char *p;
|
||||
GetDlgItemTextA(hwndDlg,IDC_EDITAUTH,_this->force_lpinfo,sizeof(_this->force_lpinfo));
|
||||
p = strstr(_this->force_lpinfo,"\r");
|
||||
if ( p && *p ) *p=0;
|
||||
p = strstr(_this->force_lpinfo,"\n");
|
||||
if ( p && *p ) *p=0;
|
||||
EndDialog(hwndDlg,1);
|
||||
}
|
||||
else if (LOWORD(wParam) == IDCANCELAUTH)
|
||||
{
|
||||
EndDialog(hwndDlg,0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -1,415 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Polish resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
|
||||
#pragma code_page(1250)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""version.rc2""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Polish resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ABOUT DIALOGEX 0, 0, 173, 113
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_CUSTOM1,"XIPH_CLASS",0x0,6,8,44,40
|
||||
CTEXT "",IDC_RPM,7,56,45,8
|
||||
CTEXT "",IDC_RPM2,4,64,51,8
|
||||
LTEXT "",IDC_ABOUT_TEXT,58,8,110,85
|
||||
DEFPUSHBUTTON "OK",IDCANCEL,117,93,50,14
|
||||
END
|
||||
|
||||
IDD_HTTPAUTH DIALOGEX 0, 0, 154, 70
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Ogg Authentication"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Realm: ",IDC_STATIC,4,4,25,8
|
||||
LTEXT "",IDC_REALM,37,4,113,8
|
||||
LTEXT "Enter your login and password in the form of:\n\tlogin:password",IDC_STATIC,4,15,146,17
|
||||
EDITTEXT IDC_EDITAUTH,4,35,146,12,ES_AUTOHSCROLL
|
||||
DEFPUSHBUTTON "OK",IDOKAUTH,4,52,50,13
|
||||
PUSHBUTTON "Cancel",IDCANCELAUTH,100,53,50,13
|
||||
END
|
||||
|
||||
IDD_INFO_DLG_NEW DIALOGEX 0, 0, 329, 238
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
CAPTION "Ogg Vorbis Info"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "File/URL :",-1,6,6,34,8
|
||||
EDITTEXT IDC_URL,43,5,282,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
GROUPBOX "File / Stream Info",IDC_STATIC_MISC,224,20,101,120
|
||||
EDITTEXT IDC_MISC,231,30,88,107,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER
|
||||
GROUPBOX "Chained Streams",IDC_STATIC_CS,224,155,101,30
|
||||
PUSHBUTTON "<= previous",IDC_PREV_STREAM,229,167,44,13
|
||||
PUSHBUTTON "next =>",IDC_NEXT_STREAM,276,167,43,13
|
||||
CONTROL "Hide special fields",IDC_HIDE_SPEC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,190,73,10
|
||||
PUSHBUTTON "",IDC_MODE_TOGGLE,228,203,93,13
|
||||
PUSHBUTTON "Close",IDCANCEL,273,220,48,13
|
||||
END
|
||||
|
||||
IDD_INFO_PANEL_SIMPLE DIALOGEX 0, 0, 227, 218
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
GROUPBOX "Standard Tags",IDC_STATIC_STD,3,2,219,119
|
||||
LTEXT "Title",IDC_STATIC,29,16,14,8
|
||||
EDITTEXT IDC_TITLE,48,14,168,12,ES_AUTOHSCROLL
|
||||
LTEXT "Artist",IDC_STATIC,27,32,16,8
|
||||
EDITTEXT IDC_ARTIST,48,30,168,12,ES_AUTOHSCROLL
|
||||
LTEXT "Album",IDC_STATIC,24,48,19,8
|
||||
EDITTEXT IDC_ALBUM,48,46,124,12,ES_AUTOHSCROLL
|
||||
LTEXT "Track:",IDC_STATIC_TRACK,175,48,21,8
|
||||
EDITTEXT IDC_TRACK,198,46,18,12,ES_AUTOHSCROLL
|
||||
LTEXT "Year",IDC_STATIC,28,64,16,8
|
||||
EDITTEXT IDC_DATE,48,62,56,12,ES_AUTOHSCROLL
|
||||
LTEXT "Genre",IDC_STATIC,117,64,22,8
|
||||
COMBOBOX IDC_GENRE,140,62,77,68,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Comment",IDC_STATIC,13,80,29,8
|
||||
EDITTEXT IDC_COMMENT,48,78,169,37,ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL
|
||||
GROUPBOX "Other",IDC_STATIC_TAGS,3,123,219,91
|
||||
LISTBOX IDC_LIST,10,134,207,75,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
END
|
||||
|
||||
IDD_INFO_PANEL_ADVANCED DIALOGEX 0, 0, 227, 218
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
LISTBOX IDC_LIST,3,3,219,212,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
END
|
||||
|
||||
IDD_INFO DIALOGEX 0, 0, 341, 164
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
GROUPBOX "Advanced",IDC_STATIC,0,0,341,164
|
||||
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,6,13,164,143
|
||||
LTEXT "Name:",IDC_STATIC,175,13,22,8
|
||||
EDITTEXT IDC_NAME,175,23,159,14,ES_AUTOHSCROLL
|
||||
LTEXT "Value:",IDC_STATIC,175,39,21,8
|
||||
EDITTEXT IDC_VALUE,175,49,159,90,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
|
||||
PUSHBUTTON "Add New",IDC_BUTTON_ADD,176,142,50,13
|
||||
PUSHBUTTON "Delete",IDC_BUTTON_DEL,230,142,50,13
|
||||
PUSHBUTTON "Delete All",IDC_BUTTON_DELALL,284,142,50,13
|
||||
END
|
||||
|
||||
IDD_CONFIG DIALOGEX 0, 0, 222, 261
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
GROUPBOX "Decoding",IDC_STATIC,4,4,214,93
|
||||
CONTROL "Buffer full files from disk",IDC_FULLBUF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,17,89,10
|
||||
CONTROL "Show average bitrate while playing",IDC_AVG_BR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,31,128,10
|
||||
GROUPBOX "5.1-Channel Input Processing",IDC_STATIC,10,44,201,47
|
||||
LTEXT "Apply conversion:",IDC_STATIC,16,58,72,8,0,WS_EX_RIGHT
|
||||
COMBOBOX IDC_MC6_DM,95,56,110,96,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Source channel order:",IDC_STATIC,16,75,72,8,0,WS_EX_RIGHT
|
||||
COMBOBOX IDC_MC6_MAP,95,73,110,96,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
GROUPBOX "Streaming",IDC_STATIC,4,101,214,139
|
||||
LTEXT "Buffer size",IDC_STATIC,10,115,34,8
|
||||
EDITTEXT IDC_HTTP_BSIZE,48,113,28,12,ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "KB",IDC_STATIC,80,115,9,8
|
||||
GROUPBOX "Prebuffering:",IDC_STATIC,10,129,201,44
|
||||
LTEXT "At start:",IDC_STATIC,16,142,31,8
|
||||
CONTROL "",IDC_SLIDER1,"msctls_trackbar32",TBS_NOTICKS | WS_TABSTOP,70,141,130,10
|
||||
LTEXT "After underrun:",IDC_STATIC,16,153,54,8
|
||||
CONTROL "",IDC_SLIDER2,"msctls_trackbar32",TBS_NOTICKS | WS_TABSTOP,70,152,130,10
|
||||
LTEXT "0%",IDC_STATIC,71,161,13,8
|
||||
LTEXT "50%",IDC_STATIC,122,161,18,8
|
||||
LTEXT "100%",IDC_STATIC,185,161,20,8
|
||||
LTEXT "Use Winamp's proxy server settings:",IDC_STATIC,10,179,120,8
|
||||
COMBOBOX IDC_PROXY,134,177,77,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
GROUPBOX "",IDC_STATIC,10,191,201,43
|
||||
CONTROL "Save streamed files to:",IDC_FSAVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,201,89,10
|
||||
PUSHBUTTON "default",IDC_SSAVE_FMT_DEF,165,200,40,11
|
||||
PUSHBUTTON "",IDC_STREAM_SAVE,15,215,105,13
|
||||
EDITTEXT IDC_SSAVE_FMT,120,215,85,13,ES_AUTOHSCROLL
|
||||
DEFPUSHBUTTON "OK",IDOK,124,244,45,13
|
||||
PUSHBUTTON "Cancel",IDCANCEL,173,244,45,13
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_ABOUT, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 4
|
||||
RIGHTMARGIN, 168
|
||||
TOPMARGIN, 4
|
||||
BOTTOMMARGIN, 107
|
||||
END
|
||||
|
||||
IDD_HTTPAUTH, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 4
|
||||
RIGHTMARGIN, 150
|
||||
TOPMARGIN, 4
|
||||
BOTTOMMARGIN, 66
|
||||
END
|
||||
|
||||
IDD_CONFIG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 4
|
||||
RIGHTMARGIN, 218
|
||||
TOPMARGIN, 4
|
||||
BOTTOMMARGIN, 257
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Bitmap
|
||||
//
|
||||
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP9$(DISABLED) BITMAP "oggdrop\\120.bmp"
|
||||
#else
|
||||
IDB_BITMAP9 BITMAP "oggdrop\\120.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP8$(DISABLED) BITMAP "oggdrop\\119.bmp"
|
||||
#else
|
||||
IDB_BITMAP8 BITMAP "oggdrop\\119.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP7$(DISABLED) BITMAP "oggdrop\\118.bmp"
|
||||
#else
|
||||
IDB_BITMAP7 BITMAP "oggdrop\\118.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP6$(DISABLED) BITMAP "oggdrop\\117.bmp"
|
||||
#else
|
||||
IDB_BITMAP6 BITMAP "oggdrop\\117.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP5$(DISABLED) BITMAP "oggdrop\\116.bmp"
|
||||
#else
|
||||
IDB_BITMAP5 BITMAP "oggdrop\\116.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP4$(DISABLED) BITMAP "oggdrop\\115.bmp"
|
||||
#else
|
||||
IDB_BITMAP4 BITMAP "oggdrop\\115.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP3$(DISABLED) BITMAP "oggdrop\\114.bmp"
|
||||
#else
|
||||
IDB_BITMAP3 BITMAP "oggdrop\\114.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP2$(DISABLED) BITMAP "oggdrop\\113.bmp"
|
||||
#else
|
||||
IDB_BITMAP2 BITMAP "oggdrop\\113.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP12$(DISABLED) BITMAP "oggdrop\\123.bmp"
|
||||
#else
|
||||
IDB_BITMAP12 BITMAP "oggdrop\\123.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP11$(DISABLED) BITMAP "oggdrop\\122.bmp"
|
||||
#else
|
||||
IDB_BITMAP11 BITMAP "oggdrop\\122.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP10$(DISABLED) BITMAP "oggdrop\\121.bmp"
|
||||
#else
|
||||
IDB_BITMAP10 BITMAP "oggdrop\\121.bmp"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
||||
#if defined(APSTUDIO_INVOKED)
|
||||
IDB_BITMAP1$(DISABLED) BITMAP "oggdrop\\112.bmp"
|
||||
#else
|
||||
IDB_BITMAP1 BITMAP "oggdrop\\112.bmp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PNG
|
||||
//
|
||||
|
||||
IDB_PNG1 PNG "oggdrop\\112.png"
|
||||
IDB_PNG2 PNG "oggdrop\\113.png"
|
||||
IDB_PNG3 PNG "oggdrop\\114.png"
|
||||
IDB_PNG4 PNG "oggdrop\\115.png"
|
||||
IDB_PNG5 PNG "oggdrop\\116.png"
|
||||
IDB_PNG6 PNG "oggdrop\\117.png"
|
||||
IDB_PNG7 PNG "oggdrop\\118.png"
|
||||
IDB_PNG8 PNG "oggdrop\\119.png"
|
||||
IDB_PNG9 PNG "oggdrop\\120.png"
|
||||
IDB_PNG10 PNG "oggdrop\\121.png"
|
||||
IDB_PNG11 PNG "oggdrop\\122.png"
|
||||
IDB_PNG12 PNG "oggdrop\\123.png"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_NULLSOFT_VORBIS_DECODER "Nullsoft Vorbis Decoder v%s"
|
||||
65535 "{5C5BCA4E-279E-4867-8E24-58C8B186959A}"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_NULLSOFT_VORBIS_DECODER_OLD "Nullsoft Vorbis Decoder"
|
||||
IDS_FILE_ERROR "file error"
|
||||
IDS_LENGTH "Length: "
|
||||
IDS_AVERAGE_BITRATE "Average bitrate: "
|
||||
IDS_FILE_SIZE "File size: "
|
||||
IDS_NOMINAL_BITRATE "Nominal bitrate: "
|
||||
IDS_MIN_BITRATE "Min bitrate: "
|
||||
IDS_MAX_BITRATE "Max bitrate: "
|
||||
IDS_CHANNELS "Channels"
|
||||
IDS_SAMPLING_RATE "Sampling rate"
|
||||
IDS_SERIAL_NUMBER "Serial number"
|
||||
IDS_VERSION "Version"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_VENDOR "Vendor"
|
||||
IDS_TO_SIMPLE_MODE "<< to simple mode"
|
||||
IDS_TO_ADVANCED_MODE "to advanced mode >>"
|
||||
IDS_OGG_VORBIS_INFO "Ogg Vorbis info - %s"
|
||||
IDS_BEST_RPM "Best: %u RPM"
|
||||
IDS_LEAVE_AS_IS "leave as is"
|
||||
IDS_REMAP_6_CHANNELS "remap 6 channels"
|
||||
IDS_DOWNMIX_TO_4_CHANNELS "downmix to 4 channels"
|
||||
IDS_DOWNMIX_TO_2_CHANNELS_DS "downmix to 2 channels (DS)"
|
||||
IDS_DOWNMIX_TO_2_CHANNELS_DS2 "downmix to 2 channels (DS2)"
|
||||
IDS_DOWNMIX_TO_MONO "downmix to mono"
|
||||
IDS_CORRECT_FL_FC_FR_BL_BR_LFE "correct (FL FC FR BL BR LFE)"
|
||||
IDS_BROKEN_FL_FR_FC_BL_BR_LFE "broken (FL FR FC BL BR LFE)"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_ABOUT_TEXT "%s\n<> 2001-2023 Winamp SA\nWritten by: Peter Pawlowski\nBuild date: %hs\n\nThanks to:\n Craig Freer\n Tomi 'Nebularia' Jylh<6C>-Ollila\n Jack Moffitt\n Szabolcs P<>ter"
|
||||
IDS_TITLE_PREFERENCES "%s Preferences"
|
||||
IDS_NEVER "never"
|
||||
IDS_PORT_80_ONLY "port 80 only"
|
||||
IDS_ALWAYS "always"
|
||||
IDS_SELECT_OUTPUT_DIRECTORY "Select output directory:"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CONNECTING "Connecting..."
|
||||
IDS_PREBUFFERING "Prebuffering : %u%%"
|
||||
IDS_AUTH_REQUIRED "Authentication Required"
|
||||
IDS_OGG_FILES "Ogg Vorbis Files (*.OGG;*.OGA)"
|
||||
IDS_NAME "Name"
|
||||
IDS_VALUE "Value"
|
||||
IDS_KBPS "kbps"
|
||||
IDS_HZ "Hz"
|
||||
IDS_GAME_SPEED "%u RPM"
|
||||
IDS_BYTES "bytes"
|
||||
IDS_FAMILY_STRING "Ogg Vorbis File"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
#include "version.rc2"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
@@ -1,65 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29424.173
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_vorbis", "in_vorbis.vcxproj", "{7C58AC02-7941-42BE-8F97-9BF2064D6631}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9} = {4FC28B55-2A14-43D5-86F7-201054F338A9}
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8} = {49238ED1-3146-49AB-9523-E9826EE4A0C8}
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4} = {EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libogg", "..\libogg\libogg.vcxproj", "{4FC28B55-2A14-43D5-86F7-201054F338A9}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vorbis_static", "..\libvorbis\win32\vorbis_static.vcxproj", "{49238ED1-3146-49AB-9523-E9826EE4A0C8}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vorbisfile_static", "..\libvorbis\win32\vorbisfile_static.vcxproj", "{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|Win32.Build.0 = Release|Win32
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|x64.Build.0 = Debug|x64
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|x64.ActiveCfg = Release|x64
|
||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|x64.Build.0 = Release|x64
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|Win32.Build.0 = Release|Win32
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|x64.Build.0 = Debug|x64
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|x64.ActiveCfg = Release|x64
|
||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|x64.Build.0 = Release|x64
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|Win32.Build.0 = Release|Win32
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|x64.Build.0 = Debug|x64
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|x64.ActiveCfg = Release|x64
|
||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|x64.Build.0 = Release|x64
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|Win32.Build.0 = Release|Win32
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|x64.Build.0 = Debug|x64
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|x64.ActiveCfg = Release|x64
|
||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3248659F-0FFC-4CF4-A9BC-F7D10C713D5D}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,339 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{7C58AC02-7941-42BE-8F97-9BF2064D6631}</ProjectGuid>
|
||||
<RootNamespace>in_vorbis</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg">
|
||||
<VcpkgEnableManifest>false</VcpkgEnableManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WA2;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0415</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;WA2;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0415</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0415</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0415</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\external_dependencies\openmpt-trunk\include\vorbis\win32\vorbisfile_static.vcxproj">
|
||||
<Project>{ec9475d2-fee2-4f8c-9bb9-a11d5eb597c4}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
|
||||
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\nsmkv\Lacing.cpp" />
|
||||
<ClCompile Include="..\..\..\nsmkv\vint.cpp" />
|
||||
<ClCompile Include="about.cpp" />
|
||||
<ClCompile Include="chainedstream_parse.cpp" />
|
||||
<ClCompile Include="config.cpp" />
|
||||
<ClCompile Include="c_string.cpp" />
|
||||
<ClCompile Include="decoder.cpp" />
|
||||
<ClCompile Include="ExtendedRead.cpp" />
|
||||
<ClCompile Include="genres.c" />
|
||||
<ClCompile Include="http.cpp" />
|
||||
<ClCompile Include="infobox.cpp" />
|
||||
<ClCompile Include="info_.cpp" />
|
||||
<ClCompile Include="localfile.cpp" />
|
||||
<ClCompile Include="mkv_vorbis_decoder.cpp" />
|
||||
<ClCompile Include="shaper.cpp" />
|
||||
<ClCompile Include="vcedit.c" />
|
||||
<ClCompile Include="wa2.cpp" />
|
||||
<ClCompile Include="winnt_helper.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="api__in_vorbis.h" />
|
||||
<ClInclude Include="c_string.h" />
|
||||
<ClInclude Include="decoder.h" />
|
||||
<ClInclude Include="genres.h" />
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="mkv_vorbis_decoder.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="shaper.h" />
|
||||
<ClInclude Include="vcedit.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="in_vorbis.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="oggdrop\112.png" />
|
||||
<Image Include="oggdrop\113.png" />
|
||||
<Image Include="oggdrop\114.png" />
|
||||
<Image Include="oggdrop\115.png" />
|
||||
<Image Include="oggdrop\116.png" />
|
||||
<Image Include="oggdrop\117.png" />
|
||||
<Image Include="oggdrop\118.png" />
|
||||
<Image Include="oggdrop\119.png" />
|
||||
<Image Include="oggdrop\120.png" />
|
||||
<Image Include="oggdrop\121.png" />
|
||||
<Image Include="oggdrop\122.png" />
|
||||
<Image Include="oggdrop\123.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@@ -1,145 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="winnt_helper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wa2.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vcedit.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shaper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mkv_vorbis_decoder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="localfile.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="infobox.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="info_.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="http.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="genres.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ExtendedRead.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="decoder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="config.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="chainedstream_parse.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="c_string.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="about.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\nsmkv\Lacing.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\nsmkv\vint.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="api__in_vorbis.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="c_string.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="decoder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="genres.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mkv_vorbis_decoder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shaper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vcedit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="oggdrop\112.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\113.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\114.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\115.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\116.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\117.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\118.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\119.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\120.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\121.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\122.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="oggdrop\123.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{7c471b36-309f-402b-a247-e640a094f9bc}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Ressource Files">
|
||||
<UniqueIdentifier>{735fc214-c8e5-4619-8c70-a184a8373c92}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{00aa1653-baa3-4e88-b6d1-fa408b0c4a85}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Image Files">
|
||||
<UniqueIdentifier>{32126a2c-dd90-4901-a5e1-aee5b7363e37}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="in_vorbis.rc">
|
||||
<Filter>Ressource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@@ -1,658 +0,0 @@
|
||||
//tag editor file i/o code, title formatting interface
|
||||
#include "main.h"
|
||||
#include "genres.h"
|
||||
#include "../nu/AutoWide.h"
|
||||
#include "../nu/AutoChar.h"
|
||||
#include "../nu/ns_wc.h"
|
||||
#include "api__in_vorbis.h"
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include <shlwapi.h>
|
||||
#include "vcedit.h"
|
||||
#include <strsafe.h>
|
||||
#include "resource.h"
|
||||
|
||||
namespace ogg_helper //chainedstream_parse
|
||||
{
|
||||
int num_get_tracks(HANDLE hFile);
|
||||
int query_chained_stream_offset(HANDLE hFile, int idx, __int64 * out_beginning, __int64 * out_end);
|
||||
}
|
||||
|
||||
/*static void xfer(HANDLE src, HANDLE dst, __int64 size)
|
||||
{
|
||||
enum { BUFFER = 1024 * 1024 };
|
||||
void * buffer = malloc((int)(BUFFER > size ? size : BUFFER));
|
||||
while (size > 0)
|
||||
{
|
||||
int d = BUFFER;
|
||||
if ((__int64)d > size) d = (int)size;
|
||||
DWORD br = 0;
|
||||
ReadFile(src, buffer, d, &br, 0);
|
||||
WriteFile(dst, buffer, d, &br, 0);
|
||||
size -= d;
|
||||
}
|
||||
}*/
|
||||
|
||||
static void seek64(HANDLE src, __int64 offset)
|
||||
{
|
||||
__int64 temp = offset;
|
||||
SetFilePointer(src, *(DWORD*)&temp, ((long*)&temp + 1), FILE_BEGIN);
|
||||
}
|
||||
|
||||
extern OSVERSIONINFO os_ver;
|
||||
extern HANDLE hThread;
|
||||
|
||||
static DWORDLONG get_space(const wchar_t * url)
|
||||
{
|
||||
ULARGE_INTEGER free_space;
|
||||
char zzz[4] = {(char)url[0], (char)url[1], (char)url[2], 0}; //"c:\";
|
||||
|
||||
free_space.QuadPart = 0;
|
||||
|
||||
if (os_ver.dwPlatformId == VER_PLATFORM_WIN32_NT || (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && LOWORD(os_ver.dwBuildNumber) > 1000))
|
||||
{
|
||||
static BOOL (WINAPI* pGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
|
||||
if (!pGetDiskFreeSpaceEx)
|
||||
{
|
||||
pGetDiskFreeSpaceEx = (BOOL (WINAPI*)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER))GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetDiskFreeSpaceExA");
|
||||
}
|
||||
if (pGetDiskFreeSpaceEx)
|
||||
{
|
||||
ULARGE_INTEGER blah1, blah2;
|
||||
pGetDiskFreeSpaceEx((LPCTSTR)zzz, &free_space, &blah1, &blah2);
|
||||
}
|
||||
}
|
||||
if (!free_space.QuadPart)
|
||||
{
|
||||
DWORD spc, bps, nfc, tnc;
|
||||
GetDiskFreeSpaceA(zzz, &spc, &bps, &nfc, &tnc);
|
||||
free_space.QuadPart = UInt32x32To64(spc * bps, nfc);
|
||||
}
|
||||
return free_space.QuadPart;
|
||||
}
|
||||
|
||||
bool sync_movefile(const wchar_t * src, const wchar_t * dst);
|
||||
|
||||
struct vcedit_param
|
||||
{
|
||||
HANDLE hFile;
|
||||
__int64 remaining;
|
||||
};
|
||||
|
||||
static size_t callback_fread(void *ptr, size_t size, size_t nmemb, vcedit_param * param)
|
||||
{
|
||||
int to_read = (int)(nmemb *size);
|
||||
if (to_read > param->remaining) to_read = (int)param->remaining;
|
||||
DWORD br = 0;
|
||||
ReadFile(param->hFile, ptr, to_read, &br, 0);
|
||||
param->remaining -= br;
|
||||
return br / size;
|
||||
}
|
||||
|
||||
static size_t callback_write(const void *ptr, size_t size, size_t nmemb, HANDLE hFile)
|
||||
{
|
||||
DWORD bw = 0;
|
||||
WriteFile(hFile, ptr, (DWORD)(size*nmemb), &bw, 0);
|
||||
return bw / size;
|
||||
}
|
||||
|
||||
BOOL modify_file(const wchar_t* url, const vorbis_comment * comments, int links)
|
||||
{ //also used for stream save fix
|
||||
HANDLE dst = INVALID_HANDLE_VALUE;
|
||||
int scream = 0;
|
||||
StringW tmp;
|
||||
|
||||
winampGetExtendedFileInfoW_Cleanup();
|
||||
|
||||
tmp = url;
|
||||
tmp += L".tmp";
|
||||
|
||||
HANDLE src = CreateFileW(url, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
|
||||
if (src != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ULARGE_INTEGER src_size;
|
||||
src_size.LowPart = GetFileSize(src, &src_size.HighPart);
|
||||
if (src_size.QuadPart > get_space(url))
|
||||
{ //shit happens... try default temp location
|
||||
StringW tempdir;
|
||||
GetTempPathW(MAX_PATH, StringTempW(tempdir, MAX_PATH));
|
||||
if (get_space(tempdir) < src_size.QuadPart)
|
||||
{ //oh well
|
||||
CloseHandle(src);
|
||||
src = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
{
|
||||
tmp = tempdir;
|
||||
if (tmp[tmp.Length() - 1] != '\\') tmp.AddChar('\\');
|
||||
|
||||
StringCchPrintfW(StringTempW(tempdir, MAX_PATH), MAX_PATH, L"ogg%u_%u.tmp", GetTickCount(), GetCurrentProcessId());
|
||||
tmp.AddString(tempdir);
|
||||
}
|
||||
}
|
||||
dst = CreateFileW(tmp, GENERIC_WRITE | GENERIC_READ, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
}
|
||||
|
||||
if (dst != INVALID_HANDLE_VALUE && src != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
{
|
||||
FILETIME ct;
|
||||
GetFileTime(src, &ct, 0, 0);
|
||||
SetFileTime(dst, &ct, 0, 0);
|
||||
}
|
||||
|
||||
int num_links = ogg_helper::num_get_tracks(src);
|
||||
if (num_links < links) scream = 1;
|
||||
else
|
||||
{
|
||||
int cur_link;
|
||||
for (cur_link = 0; cur_link < links && !scream; cur_link++)
|
||||
{
|
||||
__int64 stream_beginning, stream_end;
|
||||
if (ogg_helper::query_chained_stream_offset(src, cur_link, &stream_beginning, &stream_end))
|
||||
{
|
||||
seek64(src, stream_beginning);
|
||||
vcedit_state *vs;
|
||||
vcedit_param param;
|
||||
param.hFile = src;
|
||||
param.remaining = stream_end - stream_beginning;
|
||||
vs = vcedit_new_state();
|
||||
if (vcedit_open_callbacks(vs, ¶m, (vcedit_read_func)callback_fread, (vcedit_write_func)callback_write) < 0)
|
||||
{
|
||||
scream = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vorbis_comment * vc = vcedit_comments(vs);
|
||||
vorbis_comment_clear(vc);
|
||||
vorbis_comment_init(vc);
|
||||
const vorbis_comment * vc_src = comments + cur_link;
|
||||
|
||||
int n;
|
||||
for (n = 0;n < vc_src->comments;n++)
|
||||
{
|
||||
if (vc_src->user_comments[n])
|
||||
vorbis_comment_add(vc, vc_src->user_comments[n]);
|
||||
}
|
||||
|
||||
vcedit_write(vs, dst);
|
||||
vcedit_clear(vs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else scream = 1;
|
||||
if (src != INVALID_HANDLE_VALUE) CloseHandle(src);
|
||||
if (dst != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(dst);
|
||||
if (scream)
|
||||
{
|
||||
DeleteFileW(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!scream)
|
||||
{
|
||||
BOOL f_sync;
|
||||
EnterCriticalSection(&sync);
|
||||
|
||||
f_sync = !_wcsicmp(url, cur_file) && hThread; //check for i/o conflict with currently played file
|
||||
LeaveCriticalSection(&sync);
|
||||
if (f_sync)
|
||||
{ //drat, it's now playing
|
||||
scream = !sync_movefile(tmp, url);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!DeleteFileW(url)) scream = 1;
|
||||
else
|
||||
{
|
||||
if (!MoveFileW(tmp, url))
|
||||
{
|
||||
if (!CopyFileW(tmp, url, 0)) scream = 1;
|
||||
DeleteFileW(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scream) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
wchar_t *wdup(const char * src)
|
||||
{
|
||||
return _wcsdup(StringW(src));
|
||||
}
|
||||
|
||||
extern StringW stat_disp;
|
||||
|
||||
void GetFileInfo(const wchar_t *file, wchar_t *title, int *len)
|
||||
{
|
||||
VorbisFile* vf = 0;
|
||||
BOOL is_cur_file = 0;
|
||||
BOOL is_vf_local = 1;
|
||||
if (title) *title = 0;
|
||||
if (len) *len = -1;
|
||||
|
||||
if (!file || !*file)
|
||||
{
|
||||
file = cur_file;
|
||||
is_cur_file = 1;
|
||||
}
|
||||
else if (!lstrcmpiW(file, cur_file))
|
||||
{
|
||||
is_cur_file = 1;
|
||||
}
|
||||
|
||||
if (title && stat_disp.Length() > 0 && is_cur_file)
|
||||
{
|
||||
lstrcpynW(title, stat_disp, 256);
|
||||
title = 0;
|
||||
}
|
||||
|
||||
if (!len && !title) return ;
|
||||
|
||||
if (is_cur_file)
|
||||
{
|
||||
EnterCriticalSection(&sync);
|
||||
if (theFile)
|
||||
{
|
||||
vf = theFile;
|
||||
is_vf_local = 0;
|
||||
}
|
||||
else
|
||||
LeaveCriticalSection(&sync);
|
||||
}
|
||||
|
||||
if (!vf)
|
||||
{
|
||||
vf = VorbisFile::Create(file, 1);
|
||||
if (!vf)
|
||||
{
|
||||
if (title)
|
||||
{
|
||||
lstrcpynW(title, PathFindFileNameW(file), 256);
|
||||
wchar_t *blah = PathFindExtensionW(title);
|
||||
*blah=0;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
*len = (int)(vf->Length() * 1000);
|
||||
}
|
||||
|
||||
if (title)
|
||||
{
|
||||
const char *t = vf->get_meta("ARTIST", 0);
|
||||
if (t)
|
||||
{
|
||||
MultiByteToWideCharSZ(CP_UTF8, 0, t, -1, title, 256);
|
||||
t = vf->get_meta("TITLE", 0);
|
||||
if (t)
|
||||
{
|
||||
StringCchCatW(title, 256, L" - ");
|
||||
StringCchCatW(title, 256, AutoWide(t, CP_UTF8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *t = vf->get_meta("TITLE", 0);
|
||||
if (t)
|
||||
MultiByteToWideCharSZ(CP_UTF8, 0, t, -1, title, 256);
|
||||
else
|
||||
{
|
||||
lstrcpynW(title, PathFindFileNameW(file), 256);
|
||||
wchar_t *blah = PathFindExtensionW(title);
|
||||
*blah=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//q:
|
||||
if (is_vf_local)
|
||||
delete vf;
|
||||
else
|
||||
LeaveCriticalSection(&sync);
|
||||
}
|
||||
|
||||
void w9x_itow(wchar_t *dest, int value, int destlen)
|
||||
{
|
||||
StringCchPrintfW(dest, destlen, L"%d", value);
|
||||
|
||||
}
|
||||
void w9x_utow(wchar_t *dest, int value, int destlen)
|
||||
{
|
||||
StringCchPrintfW(dest, destlen, L"%u", value);
|
||||
}
|
||||
void w9x_htow(wchar_t *dest, int value, int destlen)
|
||||
{
|
||||
StringCchPrintfW(dest, destlen, L"%08x", value);
|
||||
}
|
||||
|
||||
static void print_misc(VorbisFile * _vf,int link,wchar_t * out, int outlen)
|
||||
{
|
||||
OggVorbis_File * vf=&_vf->vf;
|
||||
double t=ov_time_total(vf,link);
|
||||
vorbis_info * vi=ov_info(vf,link);
|
||||
vorbis_comment * vc=ov_comment(vf,link);
|
||||
if (!vi || !vc) {WASABI_API_LNGSTRINGW_BUF(IDS_FILE_ERROR,out,outlen);return;}
|
||||
|
||||
wchar_t kbps_str[16] = {0};
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_KBPS, kbps_str, 16);
|
||||
|
||||
wchar_t length[48]=L"", avgbitrate[48]=L"", filesize[48]=L"", nombitrate[48]=L"", maxbitrate[48]=L"", minbitrate[48]=L"";
|
||||
if (t>0)
|
||||
{
|
||||
int h = (int)(t/3600.0);
|
||||
int m = (int)(t/60.0)%60;
|
||||
int s = (int)t%60;
|
||||
|
||||
if(h>0) StringCchPrintfW(length,48,L"%s%u:%02u:%02u\r\n",WASABI_API_LNGSTRINGW(IDS_LENGTH),h,m,s);
|
||||
else if(m>0) StringCchPrintfW(length,48,L"%s%u:%02u\r\n",WASABI_API_LNGSTRINGW(IDS_LENGTH),m,s);
|
||||
else if(s>0) StringCchPrintfW(length,48,L"%s%u\r\n",WASABI_API_LNGSTRINGW(IDS_LENGTH),s);
|
||||
|
||||
UINT fs=_vf->FileSize();
|
||||
if (fs>0)
|
||||
{
|
||||
int kbps = (int)(((double)fs)/(t*125.0));
|
||||
wchar_t tmp[32] = {0};
|
||||
StringCchPrintfW(avgbitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_AVERAGE_BITRATE),kbps,kbps_str);
|
||||
|
||||
int fs1=fs/1000000;
|
||||
int fs2=(fs/1000)%1000;
|
||||
int fs3=fs%1000;
|
||||
if(fs1)
|
||||
StringCchPrintfW(filesize,48,L"%s%u%03u%03u %s\r\n",WASABI_API_LNGSTRINGW(IDS_FILE_SIZE),fs1,fs2,fs3,WASABI_API_LNGSTRINGW_BUF(IDS_BYTES,tmp,32));
|
||||
else if(fs2)
|
||||
StringCchPrintfW(filesize,48,L"%s%u%03u %s\r\n",WASABI_API_LNGSTRINGW(IDS_FILE_SIZE),fs2,fs3,WASABI_API_LNGSTRINGW_BUF(IDS_BYTES,tmp,32));
|
||||
else
|
||||
StringCchPrintfW(filesize,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_FILE_SIZE),fs3,WASABI_API_LNGSTRINGW_BUF(IDS_BYTES,tmp,32));
|
||||
}
|
||||
}
|
||||
|
||||
if (vi->bitrate_nominal>0)
|
||||
StringCchPrintfW(nombitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_NOMINAL_BITRATE),vi->bitrate_nominal/1000,kbps_str);
|
||||
|
||||
if (vi->bitrate_lower>0)
|
||||
StringCchPrintfW(minbitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_MIN_BITRATE),vi->bitrate_lower/1000,kbps_str);
|
||||
|
||||
if (vi->bitrate_nominal>0)
|
||||
StringCchPrintfW(maxbitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_MAX_BITRATE),vi->bitrate_nominal/1000,kbps_str);
|
||||
|
||||
wchar_t tmp[32] = {0}, tmp2[32] = {0}, tmp3[32] = {0}, tmp4[32] = {0}, tmp5[32] = {0}, hzStr[8] = {0};
|
||||
StringCchPrintfW(out,outlen,L"%s%s%s%s%s%s%s: %u\r\n%s: %u %s\r\n%s: %u\r\n%s: %u\r\n%s: \r\n%s",
|
||||
length, avgbitrate, filesize, nombitrate, maxbitrate, minbitrate,
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_CHANNELS,tmp,32),vi->channels,
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SAMPLING_RATE,tmp2,32),vi->rate, WASABI_API_LNGSTRINGW_BUF(IDS_HZ,hzStr,8),
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SERIAL_NUMBER,tmp3,32),ov_serialnumber(vf,link),
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_VERSION,tmp4,32),vi->version,
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_VENDOR,tmp5,32),(wchar_t*)AutoWide(vc->vendor,CP_UTF8));
|
||||
}
|
||||
|
||||
static VorbisFile* last_vf = 0;
|
||||
static wchar_t last_file[MAX_PATH] = {0};
|
||||
static FILETIME ftLastWriteTime;
|
||||
|
||||
// is used to determine if the last write time of the file has changed when
|
||||
// asked to get the metadata for the same cached file so we can update things
|
||||
BOOL HasFileTimeChanged(const wchar_t *fn)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA fileData = {0};
|
||||
if (GetFileAttributesExW(fn, GetFileExInfoStandard, &fileData) == TRUE)
|
||||
{
|
||||
if(CompareFileTime(&ftLastWriteTime, &fileData.ftLastWriteTime))
|
||||
{
|
||||
ftLastWriteTime = fileData.ftLastWriteTime;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void UpdateFileTimeChanged(const wchar_t *fn)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA fileData;
|
||||
if (GetFileAttributesExW(fn, GetFileExInfoStandard, &fileData) == TRUE)
|
||||
{
|
||||
ftLastWriteTime = fileData.ftLastWriteTime;
|
||||
}
|
||||
}
|
||||
|
||||
// need to call this when we shut down just to make sure things are correctly cleaned up
|
||||
//(the joys of caching for speed)
|
||||
void winampGetExtendedFileInfoW_Cleanup(void)
|
||||
{
|
||||
if (last_vf)
|
||||
{
|
||||
delete last_vf;
|
||||
last_vf = 0;
|
||||
}
|
||||
last_file[0] = 0;
|
||||
}
|
||||
|
||||
static void CALLBACK winampGetExtendedFileInfoW_Timer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD elapsed)
|
||||
{
|
||||
// TODO need to do a better way of getting and caching the metadata
|
||||
// this is _just_ a temp fix for the file being locked when it
|
||||
// it really needs 'class Info' to be able to cache and read.
|
||||
KillTimer(hwnd, eventId);
|
||||
winampGetExtendedFileInfoW_Cleanup();
|
||||
}
|
||||
|
||||
bool KeywordMatch(const char *mainString, const char *keyword)
|
||||
{
|
||||
return !_stricmp(mainString, keyword);
|
||||
}
|
||||
|
||||
#define START_TAG_ALIAS(name, alias) if (KeywordMatch(data, name)) lookup=alias
|
||||
#define TAG_ALIAS(name, alias) else if (KeywordMatch(data, name)) lookup=alias
|
||||
extern "C" __declspec( dllexport ) int winampGetExtendedFileInfoW(const wchar_t *fn, const char *data, wchar_t *dest, int destlen)
|
||||
{
|
||||
if (!_stricmp(data, "type"))
|
||||
{
|
||||
dest[0] = '0';
|
||||
dest[1] = 0;
|
||||
return 1;
|
||||
}
|
||||
else if (!_stricmp(data, "rateable"))
|
||||
{
|
||||
dest[0] = '1';
|
||||
dest[1] = 0;
|
||||
return 1;
|
||||
}
|
||||
else if (!_stricmp(data, "streammetadata"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fn || (fn && !fn[0])) return 0;
|
||||
|
||||
if (!_stricmp(data, "family"))
|
||||
{
|
||||
LPCWSTR e;
|
||||
int pID = -1;
|
||||
DWORD lcid;
|
||||
e = PathFindExtensionW(fn);
|
||||
if (L'.' != *e) return 0;
|
||||
e++;
|
||||
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
|
||||
if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, e, -1, L"OGG", -1) ||
|
||||
CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, e, -1, L"OGA", -1)) pID = IDS_FAMILY_STRING;
|
||||
if (pID != -1 && S_OK == StringCchCopyW(dest, destlen, WASABI_API_LNGSTRINGW(pID))) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_stricmp(data, "mime"))
|
||||
{
|
||||
StringCchCopyW(dest, destlen, L"audio/ogg");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// attempt to cache/use a cached instance of VorbisFile to speed up metadata queries
|
||||
// which is especially needed with large ogg files (like with a 4Mb embedded image!)
|
||||
VorbisFile* vf = 0;
|
||||
if(last_file[0] && !_wcsicmp(last_file, fn) && !HasFileTimeChanged(fn))
|
||||
{
|
||||
vf = last_vf;
|
||||
}
|
||||
else
|
||||
{
|
||||
// different file so clean up if there's a cached instance
|
||||
if(last_vf)
|
||||
{
|
||||
delete last_vf;
|
||||
last_vf = 0;
|
||||
}
|
||||
// open the new file and cache the current filename for subsequent query checks
|
||||
vf = VorbisFile::Create(fn, 1);
|
||||
lstrcpynW(last_file, fn, MAX_PATH);
|
||||
}
|
||||
|
||||
if (!vf) return 0;
|
||||
else last_vf = vf;
|
||||
|
||||
// TODO need to do a better way of getting and caching the metadata
|
||||
// this is _just_ a temp fix for the file being locked when it
|
||||
// it really needs 'class Info' to be able to cache and read.
|
||||
SetTimer(mod.hMainWindow, 256, 2000, winampGetExtendedFileInfoW_Timer);
|
||||
|
||||
const char *lookup = 0;
|
||||
if (!_stricmp(data, "length"))
|
||||
{
|
||||
int len = (int)(vf->Length() * 1000);
|
||||
w9x_itow(dest, len, destlen);
|
||||
return 1;
|
||||
}
|
||||
else if (!_stricmp(data, "bitrate"))
|
||||
{
|
||||
int br = vf->get_avg_bitrate();
|
||||
w9x_itow(dest, br, destlen);
|
||||
return 1;
|
||||
}
|
||||
else if (!_stricmp(data, "SERIALNUMBER"))
|
||||
{
|
||||
w9x_utow(dest, ov_serialnumber(&vf->vf, -1), destlen);
|
||||
return 1;
|
||||
}
|
||||
else if (!_stricmp(data, "SERIALNUMBER_HEX"))
|
||||
{
|
||||
w9x_htow(dest, ov_serialnumber(&vf->vf, -1), destlen);
|
||||
return 1;
|
||||
}
|
||||
else if (!_stricmp(data, "gain"))
|
||||
{
|
||||
float gain = 20.0f*(float)log10(vf->GetGain());
|
||||
StringCchPrintfW(dest, destlen, L"%-+.2f dB", gain);
|
||||
return 1;
|
||||
}
|
||||
else if(!_stricmp(data,"formatinformation"))
|
||||
{
|
||||
print_misc(vf,0,dest,destlen);
|
||||
return 1;
|
||||
}
|
||||
TAG_ALIAS("title", "TITLE");
|
||||
TAG_ALIAS("artist", "ARTIST");
|
||||
TAG_ALIAS("album", "ALBUM");
|
||||
TAG_ALIAS("genre", "GENRE");
|
||||
TAG_ALIAS("comment", "COMMENT");
|
||||
TAG_ALIAS("year", "DATE");
|
||||
TAG_ALIAS("track", "TRACKNUMBER");
|
||||
TAG_ALIAS("albumartist", "ALBUMARTIST");
|
||||
TAG_ALIAS("composer", "COMPOSER");
|
||||
TAG_ALIAS("disc", "DISCNUMBER");
|
||||
TAG_ALIAS("publisher", "PUBLISHER");
|
||||
TAG_ALIAS("conductor", "CONDUCTOR");
|
||||
TAG_ALIAS("tool", "ENCODED-BY");
|
||||
TAG_ALIAS("replaygain_track_gain", "REPLAYGAIN_TRACK_GAIN");
|
||||
TAG_ALIAS("replaygain_track_peak", "REPLAYGAIN_TRACK_PEAK");
|
||||
TAG_ALIAS("replaygain_album_gain", "REPLAYGAIN_ALBUM_GAIN");
|
||||
TAG_ALIAS("replaygain_album_peak", "REPLAYGAIN_ALBUM_PEAK");
|
||||
TAG_ALIAS("GracenoteFileID", "GRACENOTEFILEID");
|
||||
TAG_ALIAS("GracenoteExtData", "GRACENOTEEXTDATA");
|
||||
TAG_ALIAS("bpm", "BPM");
|
||||
TAG_ALIAS("remixing", "REMIXING");
|
||||
TAG_ALIAS("subtitle", "VERSION");
|
||||
TAG_ALIAS("isrc", "ISRC");
|
||||
TAG_ALIAS("category", "CATEGORY");
|
||||
TAG_ALIAS("rating", "RATING");
|
||||
TAG_ALIAS("producer", "PRODUCER");
|
||||
|
||||
if (!lookup)
|
||||
return 0;
|
||||
|
||||
const char *value = vf->get_meta(lookup, 0);
|
||||
|
||||
if(KeywordMatch("comment",data)) {
|
||||
if(!value || !*value) value = vf->get_meta("DESCRIPTION", 0);
|
||||
}
|
||||
|
||||
if(KeywordMatch("year",data)) {
|
||||
if(!value || !*value) value = vf->get_meta("YEAR", 0);
|
||||
}
|
||||
|
||||
if(KeywordMatch("track",data)) {
|
||||
if(!value || !*value) value = vf->get_meta("TRACK", 0);
|
||||
}
|
||||
|
||||
if(KeywordMatch("albumartist",data)) {
|
||||
if(!value || !*value) value = vf->get_meta("ALBUM ARTIST", 0);
|
||||
if(!value || !*value) value = vf->get_meta("ENSEMBLE", 0);
|
||||
}
|
||||
|
||||
if(KeywordMatch("publisher",data)) {
|
||||
if(!value || !*value) value = vf->get_meta("ORGANIZATION", 0);
|
||||
}
|
||||
|
||||
if(KeywordMatch("category",data)) {
|
||||
if(!value || !*value) value = vf->get_meta("CONTENTGROUP", 0);
|
||||
if(!value || !*value) value = vf->get_meta("GROUPING", 0);
|
||||
}
|
||||
|
||||
if(KeywordMatch(data, "rating")) {
|
||||
if(!value || !*value) value = vf->get_meta("RATING", 0);
|
||||
if(value && *value) {
|
||||
int rating = atoi(value);
|
||||
// keeps things limited to our range of 0-100
|
||||
if (rating >= 100) {
|
||||
rating = 5;
|
||||
}
|
||||
// 1-100 case
|
||||
else if (rating > 5 && rating < 100) {
|
||||
rating /= 20;
|
||||
// shift up by one rating when in next band
|
||||
// 1-20 = 1, 21-40 = 2, 41-60 = 3, 61-80 = 4, 81-100 = 5
|
||||
rating += ((atoi(value) - (rating * 20)) > 0);
|
||||
}
|
||||
// Remove support for old 1-10 range
|
||||
/* or maybe we're dealing with a 1-10 range
|
||||
else if (rating > 5) {
|
||||
rating /= 2;
|
||||
} */
|
||||
|
||||
// otherwise it is hopefully in the 0-5 range
|
||||
else if (rating > 0 && rating <= 5) {
|
||||
}
|
||||
// otherwise just make sure and set zero
|
||||
else {
|
||||
rating = 0;
|
||||
}
|
||||
|
||||
StringCchPrintfW(dest, destlen, L"%u", rating);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(value)
|
||||
MultiByteToWideCharSZ(CP_UTF8, 0, value, -1, dest, destlen);
|
||||
else
|
||||
{
|
||||
dest[0]=0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@@ -1,260 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "../nu/AutoChar.h"
|
||||
|
||||
extern CfgInt cfg_fullbuf;
|
||||
|
||||
int VorbisFile::_f_close(void *) {return 0;}
|
||||
|
||||
int VorbisFile::_f_seek(void* rs,__int64 offset,int whence)
|
||||
{
|
||||
return ((VorbisFile*)rs)->f_seek(offset,whence);
|
||||
}
|
||||
|
||||
size_t VorbisFile::_f_read(void* ptr,size_t size,size_t nmemb,void * rs)
|
||||
{
|
||||
return ((VorbisFile*)rs)->f_read((UINT)(size*nmemb),ptr);
|
||||
}
|
||||
|
||||
long VorbisFile::_f_tell(void* rs)
|
||||
{
|
||||
return ((VorbisFile*)rs)->f_tell();
|
||||
}
|
||||
|
||||
ov_callbacks VorbisFile::oc={_f_read,_f_seek,_f_close,_f_tell};
|
||||
|
||||
static __int64 Seek64(HANDLE hf, __int64 distance, DWORD MoveMethod)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
|
||||
li.QuadPart = distance;
|
||||
|
||||
li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod);
|
||||
|
||||
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
||||
{
|
||||
li.QuadPart = -1;
|
||||
}
|
||||
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
static __int64 FileSize64(HANDLE file)
|
||||
{
|
||||
LARGE_INTEGER position;
|
||||
position.QuadPart=0;
|
||||
position.LowPart = GetFileSize(file, (LPDWORD)&position.HighPart);
|
||||
|
||||
if (position.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
|
||||
return INVALID_FILE_SIZE;
|
||||
else
|
||||
return position.QuadPart;
|
||||
}
|
||||
|
||||
class VorbisFile_Local : public VorbisFile
|
||||
{
|
||||
private:
|
||||
HANDLE hFile;
|
||||
protected:
|
||||
int f_seek(__int64 offset,int whence)
|
||||
{
|
||||
if(whence==SEEK_SET) offset+=baseoffs;
|
||||
if (Seek64(hFile,offset,whence) != INVALID_SET_FILE_POINTER) return 0;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
size_t f_read(UINT siz,void * ptr)
|
||||
{
|
||||
DWORD bw=0;
|
||||
ReadFile(hFile,ptr,siz,&bw,0);
|
||||
return bw;
|
||||
}
|
||||
|
||||
UINT f_tell()
|
||||
{
|
||||
return (UINT)(SetFilePointer(hFile,0,0,FILE_CURRENT)-baseoffs);
|
||||
}
|
||||
|
||||
UINT FileSize()
|
||||
{
|
||||
return (UINT)(FileSize64(hFile)-baseoffs);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int GetType() {return TYPE_LOCAL;}
|
||||
VorbisFile_Local(HANDLE f,const wchar_t * u,bool is_info) : VorbisFile(u,is_info) {hFile=f;}
|
||||
~VorbisFile_Local() {CloseHandle(hFile);}
|
||||
};
|
||||
|
||||
class VorbisFile_Mem : public VorbisFile
|
||||
{
|
||||
BYTE * block;
|
||||
UINT size,ptr;
|
||||
protected:
|
||||
int f_seek(__int64 offset,int whence)
|
||||
{
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
ptr=(UINT)(offset+baseoffs);
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
ptr+=(UINT)offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
ptr=size+whence;
|
||||
break;
|
||||
}
|
||||
if (ptr<=size) return 0;
|
||||
else {ptr=size;return -1;}
|
||||
}
|
||||
|
||||
size_t f_read(UINT siz,void * out)
|
||||
{
|
||||
UINT d=size-ptr;
|
||||
if (d>siz) d=siz;
|
||||
memcpy(out,block+ptr,d);
|
||||
ptr+=d;
|
||||
return d;
|
||||
}
|
||||
|
||||
UINT f_tell()
|
||||
{
|
||||
return (UINT)(ptr-baseoffs);
|
||||
}
|
||||
|
||||
UINT FileSize()
|
||||
{
|
||||
return (UINT)(size-baseoffs);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int GetType() {return TYPE_LOCAL;}
|
||||
|
||||
VorbisFile_Mem(HANDLE f,const wchar_t * u,bool is_info) : VorbisFile(u,is_info)
|
||||
{
|
||||
size=GetFileSize(f,0);
|
||||
ptr=0;
|
||||
block=(BYTE*)malloc(size);
|
||||
DWORD br = 0;
|
||||
ReadFile(f,block,size,&br,0);
|
||||
CloseHandle(f);
|
||||
}
|
||||
|
||||
~VorbisFile_Mem() {free(block);}
|
||||
};
|
||||
|
||||
VorbisFile * VorbisFile::Create(const wchar_t *url, bool is_info)
|
||||
{
|
||||
VorbisFile * r;
|
||||
if (PathIsURLW(url))
|
||||
{
|
||||
if (is_info) return 0;
|
||||
r=Create_HTTP(AutoChar(url),is_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
__int64 baseoffs=0;
|
||||
HANDLE f=CreateFileW(url,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
|
||||
if (f==INVALID_HANDLE_VALUE) return 0;
|
||||
{
|
||||
DWORD dw = 0, br = 0;
|
||||
ReadFile(f,&dw,4,&br,0);
|
||||
if(br==4 && dw=='SggO')
|
||||
{
|
||||
SetFilePointer(f,0,0,FILE_BEGIN);
|
||||
}
|
||||
else if(br==4 && dw=='FFIR')
|
||||
{
|
||||
//RIFF file
|
||||
DWORD wavhdr = 0, nb = 0;
|
||||
SetFilePointer(f,4,0,FILE_CURRENT);
|
||||
ReadFile(f,&wavhdr,4,&nb,0);
|
||||
if(nb!=4 || wavhdr!='EVAW')
|
||||
{
|
||||
goto abort;
|
||||
}
|
||||
|
||||
//find data starting point
|
||||
char tmp[1024] = {0};
|
||||
ReadFile(f,&tmp,1024,&nb,0);
|
||||
for(int i=0;i<1020;i++)
|
||||
if(tmp[i]=='d'&&tmp[i+1]=='a'&&tmp[i+2]=='t'&&tmp[i+3]=='a')
|
||||
{
|
||||
baseoffs=i+12+8;
|
||||
Seek64(f, baseoffs, FILE_BEGIN);
|
||||
}
|
||||
|
||||
if(!baseoffs) goto abort;
|
||||
}
|
||||
else
|
||||
{
|
||||
abort:
|
||||
CloseHandle(f);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r=cfg_fullbuf ? (VorbisFile*)new VorbisFile_Mem(f,url,is_info) : (VorbisFile*)new VorbisFile_Local(f,url,is_info);
|
||||
r->setBaseOffset(baseoffs);
|
||||
}
|
||||
if (r && !r->init())
|
||||
{
|
||||
delete r;
|
||||
r=0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool VorbisFile::init()
|
||||
{
|
||||
if (ov_open_callbacks(this,&vf,0,0,oc)) return 0;
|
||||
//TODO bitrate
|
||||
UINT siz=FileSize();
|
||||
double len=Length();
|
||||
if (siz>0 && len>0)
|
||||
{
|
||||
UINT divisor = (UINT)(len*125.0);
|
||||
if (divisor)
|
||||
avg_kbps=siz/divisor;
|
||||
}
|
||||
|
||||
post_init();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_http(const char* url)
|
||||
{
|
||||
return (!_strnicmp(url,"http://",7) || !_strnicmp(url,"https://",8));
|
||||
}
|
||||
|
||||
void VorbisFile::set_meta(const vorbis_comment * vc,int links)
|
||||
{
|
||||
if (links == vf.links)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<links;n++)
|
||||
{
|
||||
vorbis_comment_clear(vf.vc+n);
|
||||
/*
|
||||
extern void vorbis_comment_init(vorbis_comment *vc);
|
||||
extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
|
||||
extern void vorbis_comment_add_tag(vorbis_comment *vc,char *tag, char *contents);
|
||||
extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
|
||||
extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
|
||||
extern void vorbis_comment_clear(vorbis_comment *vc);
|
||||
*/
|
||||
}
|
||||
_ogg_free(vf.vc);
|
||||
vf.vc = (vorbis_comment*) _ogg_calloc(links,sizeof(vorbis_comment));
|
||||
for(n=0;n<links;n++)
|
||||
{
|
||||
vorbis_comment_init(vf.vc+n);
|
||||
int c;
|
||||
for(c=0;c<vc[n].comments;c++)
|
||||
{
|
||||
vorbis_comment_add(vf.vc+n,vc[n].user_comments[c]);
|
||||
}
|
||||
vf.vc[n].vendor = _strdup(vc[n].vendor);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,220 +0,0 @@
|
||||
#ifndef IN_VORBIS_MAIN_H
|
||||
#define IN_VORBIS_MAIN_H
|
||||
|
||||
#define WINSOCK_API_LINKAGE
|
||||
|
||||
#ifndef STRICT
|
||||
#define STRICT
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
extern int (*warand)();
|
||||
extern float (*warandf)();
|
||||
|
||||
inline void * z_malloc(int x)
|
||||
{
|
||||
void* foo=malloc(x);
|
||||
if (foo) memset(foo,0,x);
|
||||
return foo;
|
||||
}
|
||||
#include <shlwapi.h>
|
||||
#include <malloc.h>
|
||||
#define uitoa(x,y) _itoa(x,y,10)
|
||||
#define atoui atoi
|
||||
|
||||
#include <vorbis\vorbisfile.h>
|
||||
#include "c_string.h"
|
||||
#include "../Winamp/in2.h"
|
||||
|
||||
extern In_Module mod;
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#define VER L"1.79"
|
||||
#define _NAME "Nullsoft Vorbis Decoder"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern const char *INI_FILE;
|
||||
extern const wchar_t *INI_DIRECTORY;
|
||||
}
|
||||
class CfgVar
|
||||
{
|
||||
private:
|
||||
String name;
|
||||
CfgVar * next;
|
||||
static CfgVar * list;
|
||||
public:
|
||||
|
||||
static void ReadConfig();
|
||||
static void WriteConfig();
|
||||
|
||||
//helpers
|
||||
static bool read_struct(const char *inifile, const char *section, const char * name,void * ptr,UINT size);
|
||||
static void write_struct(const char *inifile, const char *section, const char * name,void * ptr,UINT size);
|
||||
static void write_int(const char *inifile, const char *section, const char * name,int val);
|
||||
static int read_int(const char *inifile, const char *section,const char * name,int def);
|
||||
|
||||
protected:
|
||||
CfgVar(const char * n) : name(n) {next=list;list=this;}
|
||||
virtual void Read(const char * name)=0;
|
||||
virtual void Write(const char * name)=0;
|
||||
};
|
||||
|
||||
class CfgInt : private CfgVar
|
||||
{
|
||||
private:
|
||||
int def,value;
|
||||
public:
|
||||
CfgInt(const char * name,int _def) : CfgVar(name) {value=def=_def;}
|
||||
inline int operator=(int x) {value=x;return value;}
|
||||
inline operator int() {return value;}
|
||||
private:
|
||||
virtual void Read(const char * name);
|
||||
virtual void Write(const char * name);
|
||||
};
|
||||
|
||||
class CfgString : private CfgVar, public StringW
|
||||
{
|
||||
private:
|
||||
StringW def;
|
||||
public:
|
||||
CfgString(const char * name,const char * _def) : CfgVar(name), StringW(_def), def(_def) {}
|
||||
private:
|
||||
virtual void Read(const char * name);
|
||||
virtual void Write(const char * name);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class CfgStructT : private CfgVar
|
||||
{
|
||||
public:
|
||||
T data;
|
||||
CfgStructT(const char * name) : CfgVar(name) {}
|
||||
private:
|
||||
void Read(const char * name) { read_struct(INI_FILE, "in_vorbis",name,&data,sizeof(data));}
|
||||
void Write(const char * name) {if (IsValueDefault()) WritePrivateProfileStringA("in_vorbis", name, 0, INI_FILE); else write_struct(INI_FILE, "in_vorbis", name, &data, sizeof(data));}
|
||||
protected:
|
||||
virtual bool IsValueDefault() {return 0;}
|
||||
};
|
||||
|
||||
|
||||
class CfgFont : public CfgStructT<LOGFONT>
|
||||
{
|
||||
private:
|
||||
void get_def(LOGFONT * f) {memset(f,0,sizeof(LOGFONT));GetObject(GetStockObject(DEFAULT_GUI_FONT),sizeof(LOGFONT),f);}
|
||||
virtual bool IsValueDefault()
|
||||
{
|
||||
LOGFONT t;
|
||||
get_def(&t);
|
||||
return !memcmp(&data,&t,sizeof(LOGFONT));
|
||||
}
|
||||
public:
|
||||
CfgFont(const char * name) : CfgStructT<LOGFONT>(name)
|
||||
{
|
||||
get_def(&data);
|
||||
}
|
||||
};
|
||||
|
||||
extern int32_t priority_tab[7];
|
||||
extern HINSTANCE hIns;
|
||||
|
||||
extern CfgString cfg_ssave_format,cfg_dumpdir;
|
||||
|
||||
int is_http(const char* url);
|
||||
|
||||
class VorbisFile
|
||||
{
|
||||
protected:
|
||||
virtual int f_seek(__int64 offset,int whence)=0;
|
||||
virtual size_t f_read(UINT siz,void * ptr)=0;
|
||||
virtual UINT f_tell()=0;
|
||||
static int _f_close(void *);
|
||||
static int _f_seek(void* rs,__int64 offset,int whence);
|
||||
static size_t _f_read(void* ptr,size_t size,size_t nmemb,void * rs);
|
||||
static long _f_tell(void* rs);
|
||||
static ov_callbacks oc;
|
||||
static VorbisFile * Create_HTTP(const char * url,bool is_info);
|
||||
VorbisFile(const wchar_t * u, bool is_info) : url(u) {memset(&vf,0,sizeof(vf));stopping=0;abort_prebuf=0;avg_kbps=0;use_prebuf=0;primary=!is_info; baseoffs=0;}
|
||||
bool init();
|
||||
virtual void post_init() {};
|
||||
UINT avg_kbps;
|
||||
bool Aborting();
|
||||
|
||||
__int64 baseoffs;
|
||||
public:
|
||||
enum {TYPE_LOCAL,TYPE_HTTP};
|
||||
virtual int GetType()=0;
|
||||
virtual bool IsLive() {return 0;}
|
||||
virtual void do_prebuf() {use_prebuf=1;abort_prebuf=0;};
|
||||
StringW url;
|
||||
String withlp;
|
||||
String stream_title;
|
||||
bool stopping,abort_prebuf,use_prebuf;
|
||||
bool primary;//display status messages or not
|
||||
OggVorbis_File vf;
|
||||
UINT get_avg_bitrate()
|
||||
{
|
||||
if (avg_kbps>0) return avg_kbps;
|
||||
vorbis_info * vi=ov_info(&vf,-1);
|
||||
if (!vi) return 0;
|
||||
return vi->bitrate_nominal/1000;
|
||||
}
|
||||
|
||||
const char* get_meta(const char* tag,UINT c);
|
||||
void set_meta(const vorbis_comment * vc,int links);
|
||||
|
||||
static VorbisFile * Create(const wchar_t * url,bool is_info);
|
||||
|
||||
double Length() {return ov_time_total(&vf,-1);}
|
||||
double GetPos() {return ov_time_tell(&vf);}
|
||||
int Seek(double p);
|
||||
void Status(const wchar_t * zzz);
|
||||
virtual UINT FileSize()=0;
|
||||
|
||||
virtual ~VorbisFile() {ov_clear(&vf);}
|
||||
virtual void Idle() {Sleep(10);}
|
||||
|
||||
virtual void setBaseOffset(__int64 offs) { baseoffs=offs; }
|
||||
|
||||
float GetGain();
|
||||
};
|
||||
|
||||
extern VorbisFile * theFile;
|
||||
|
||||
extern StringW cur_file;
|
||||
|
||||
extern CRITICAL_SECTION sync;
|
||||
|
||||
BOOL modify_file(const wchar_t* url,const vorbis_comment * comments,int links);
|
||||
void winampGetExtendedFileInfoW_Cleanup(void);
|
||||
void UpdateFileTimeChanged(const wchar_t *fn);
|
||||
void do_cfg(int s);
|
||||
bool KeywordMatch(const char *mainString, const char *keyword);
|
||||
|
||||
class Info
|
||||
{
|
||||
public:
|
||||
Info(const wchar_t *filename);
|
||||
~Info();
|
||||
bool Save();
|
||||
int Error() { return vc==0?1:0; }
|
||||
int GetNumMetadataItems();
|
||||
void EnumMetadata(int n,wchar_t *key,int keylen, wchar_t *val, int vallen);
|
||||
void RemoveMetadata(wchar_t * key);
|
||||
void RemoveMetadata(int n);
|
||||
void SetMetadata(wchar_t *key, wchar_t *val);
|
||||
void SetMetadata(int n, wchar_t *key, wchar_t *val);
|
||||
void SetTag(int n,wchar_t *key); // changes the key name
|
||||
private:
|
||||
const wchar_t *filename;
|
||||
vorbis_comment * vc;
|
||||
int numstreams, stream;
|
||||
};
|
||||
|
||||
// {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F}
|
||||
static const GUID playbackConfigGroupGUID =
|
||||
{ 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf } };
|
||||
|
||||
#endif //IN_VORBIS_MAIN_H
|
@@ -1,194 +0,0 @@
|
||||
#include "mkv_vorbis_decoder.h"
|
||||
#include "../nsmkv/Lacing.h"
|
||||
#include "../nsmkv/Cluster.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
int MKVDecoderCreator::CreateAudioDecoder(const char *codec_id,
|
||||
const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data,
|
||||
unsigned int preferred_bits, unsigned int max_channels, bool floating_point,
|
||||
ifc_mkvaudiodecoder **decoder)
|
||||
{
|
||||
if (!strcmp(codec_id, "A_VORBIS"))
|
||||
{
|
||||
MKVVorbis *vorbis = new MKVVorbis;
|
||||
vorbis_info_init(&vorbis->info);
|
||||
vorbis_comment_init(&vorbis->comment);
|
||||
nsmkv::LacingState lacing_state;
|
||||
if (nsmkv::Lacing::GetState(nsmkv::BlockBinary::XIPH_LACING, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &lacing_state))
|
||||
{
|
||||
const uint8_t *frame;
|
||||
size_t frame_len;
|
||||
uint16_t frame_number=0;
|
||||
while (nsmkv::Lacing::GetFrame(frame_number, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &frame, &frame_len, &lacing_state))
|
||||
{
|
||||
ogg_packet packet = {const_cast<uint8_t *>(frame), (long)frame_len, (frame_number==0), 0, 0 /*-1?*/, vorbis->packet_number++};
|
||||
int ret = vorbis_synthesis_headerin(&vorbis->info, &vorbis->comment, &packet);
|
||||
if (ret != 0)
|
||||
goto bail;
|
||||
frame_number++;
|
||||
}
|
||||
if (vorbis_synthesis_init(&vorbis->dsp, &vorbis->info) == 0
|
||||
&& vorbis_block_init(&vorbis->dsp, &vorbis->block) == 0)
|
||||
{
|
||||
vorbis->bps = preferred_bits?preferred_bits:16;
|
||||
*decoder = vorbis;
|
||||
return CREATEDECODER_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
bail:
|
||||
delete vorbis;
|
||||
return CREATEDECODER_FAILURE;
|
||||
}
|
||||
|
||||
return CREATEDECODER_NOT_MINE;
|
||||
}
|
||||
|
||||
|
||||
#define CBCLASS MKVDecoderCreator
|
||||
START_DISPATCH;
|
||||
CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
||||
|
||||
MKVVorbis::MKVVorbis()
|
||||
{
|
||||
bps=16;
|
||||
packet_number=0;
|
||||
}
|
||||
|
||||
#define PA_CLIP_( val, min, max )\
|
||||
{ val = ((val) < (min)) ? (min) : (((val) > (max)) ? (max) : (val)); }
|
||||
|
||||
#if defined(_M_IX86)
|
||||
static __inline long float_to_long(double t)
|
||||
{
|
||||
long r;
|
||||
__asm fld t
|
||||
__asm fistp r
|
||||
return r;
|
||||
}
|
||||
#else
|
||||
#define float_to_long(x) ((long)( x ))
|
||||
#endif
|
||||
|
||||
inline static void clip(double &x, double a, double b)
|
||||
{
|
||||
double x1 = fabs (x - a);
|
||||
double x2 = fabs (x - b);
|
||||
x = x1 + (a + b);
|
||||
x -= x2;
|
||||
x *= 0.5;
|
||||
}
|
||||
|
||||
static void Float32_To_Int24_Clip(void *destinationBuffer, void *sourceBuffer, size_t count, size_t channels, double gain)
|
||||
{
|
||||
float *src = (float*)sourceBuffer;
|
||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
||||
gain*=65536.*32768.;
|
||||
while ( count-- )
|
||||
{
|
||||
/* convert to 32 bit and drop the low 8 bits */
|
||||
double scaled = *src * gain;
|
||||
clip( scaled, -2147483648., 2147483647.);
|
||||
signed long temp = (signed long) scaled;
|
||||
|
||||
dest[0] = (unsigned char)(temp >> 8);
|
||||
dest[1] = (unsigned char)(temp >> 16);
|
||||
dest[2] = (unsigned char)(temp >> 24);
|
||||
|
||||
src++;
|
||||
dest += 3*channels;
|
||||
}
|
||||
}
|
||||
|
||||
static void Float32_To_Int16_Clip(void *destinationBuffer, void *sourceBuffer, size_t count, size_t channels, double gain)
|
||||
{
|
||||
float *src = (float*)sourceBuffer;
|
||||
signed short *dest = (signed short*)destinationBuffer;
|
||||
|
||||
gain*=32768.0;
|
||||
while ( count-- )
|
||||
{
|
||||
long samp = float_to_long((*src) * gain/* - 0.5*/);
|
||||
|
||||
PA_CLIP_( samp, -0x8000, 0x7FFF );
|
||||
*dest = (signed short) samp;
|
||||
|
||||
src ++;
|
||||
dest += channels;
|
||||
}
|
||||
}
|
||||
|
||||
int MKVVorbis::DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
|
||||
{
|
||||
uint8_t *out = (uint8_t *)outputBuffer;
|
||||
ogg_packet packet = {(uint8_t *)inputBuffer, (long)inputBufferBytes, 0, 0, 0 -1, packet_number++};
|
||||
int ret = vorbis_synthesis(&block, &packet);
|
||||
if (ret == 0)
|
||||
{
|
||||
vorbis_synthesis_blockin(&dsp,&block);
|
||||
long channels = info.channels;
|
||||
float **pcm;
|
||||
int samples = vorbis_synthesis_pcmout(&dsp, &pcm);
|
||||
if (samples)
|
||||
{
|
||||
switch(bps)
|
||||
{
|
||||
case 16:
|
||||
for(int i=0;i<channels;i++)
|
||||
{
|
||||
Float32_To_Int16_Clip(out, pcm[i], samples, channels, 1.0 /*gain*/);
|
||||
out+=2;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
for(int i=0;i<channels;i++)
|
||||
{
|
||||
Float32_To_Int24_Clip(out, pcm[i], samples, channels, 1.0 /*gain*/);
|
||||
out+=3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*outputBufferBytes = samples*channels*bps/8;
|
||||
// let the decoder know we're processed them
|
||||
vorbis_synthesis_read(&dsp,samples);
|
||||
return MKV_SUCCESS;
|
||||
}
|
||||
return MKV_FAILURE;
|
||||
}
|
||||
|
||||
int MKVVorbis::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
|
||||
{
|
||||
*sampleRate = info.rate;
|
||||
*channels = info.channels;
|
||||
*bitsPerSample = bps;
|
||||
*isFloat = false; // TODO
|
||||
return MKV_SUCCESS;
|
||||
}
|
||||
|
||||
void MKVVorbis::Flush()
|
||||
{
|
||||
vorbis_synthesis_restart(&dsp);
|
||||
}
|
||||
|
||||
void MKVVorbis::Close()
|
||||
{
|
||||
// TODO: benski> verify
|
||||
vorbis_info_clear(&info);
|
||||
vorbis_comment_clear(&comment);
|
||||
vorbis_dsp_clear(&dsp);
|
||||
vorbis_block_clear(&block);
|
||||
delete this;
|
||||
}
|
||||
#define CBCLASS MKVVorbis
|
||||
START_DISPATCH;
|
||||
//CB(OUTPUT_FRAME_SIZE, OutputFrameSize)
|
||||
CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
|
||||
CB(DECODE_BLOCK, DecodeBlock)
|
||||
VCB(FLUSH, Flush)
|
||||
VCB(CLOSE, Close)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
@@ -1,41 +0,0 @@
|
||||
#pragma once
|
||||
#include "../in_mkv/ifc_mkvaudiodecoder.h"
|
||||
#include "../in_mkv/svc_mkvdecoder.h"
|
||||
#include <vorbis/codec.h>
|
||||
|
||||
// {6058D315-2F08-4b2f-903E-4C2E6B5EFFA9}
|
||||
static const GUID mkv_vorbis_guid =
|
||||
{ 0x6058d315, 0x2f08, 0x4b2f, { 0x90, 0x3e, 0x4c, 0x2e, 0x6b, 0x5e, 0xff, 0xa9 } };
|
||||
|
||||
|
||||
class MKVDecoderCreator : public svc_mkvdecoder
|
||||
{
|
||||
public:
|
||||
static const char *getServiceName() { return "Vorbis MKV Decoder"; }
|
||||
static GUID getServiceGuid() { return mkv_vorbis_guid; }
|
||||
int CreateAudioDecoder(const char *codec_id,
|
||||
const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data,
|
||||
unsigned int preferred_bits, unsigned int max_channels, bool floating_point,
|
||||
ifc_mkvaudiodecoder **decoder);
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
class MKVVorbis : public ifc_mkvaudiodecoder
|
||||
{
|
||||
public:
|
||||
MKVVorbis();
|
||||
int DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes);
|
||||
int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat);
|
||||
void Flush();
|
||||
void Close();
|
||||
//private:
|
||||
unsigned int bps;
|
||||
vorbis_info info;
|
||||
vorbis_dsp_state dsp;
|
||||
vorbis_block block;
|
||||
vorbis_comment comment;
|
||||
ogg_int64_t packet_number;
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
Before Width: | Height: | Size: 782 B |
Before Width: | Height: | Size: 817 B |
Before Width: | Height: | Size: 753 B |
Before Width: | Height: | Size: 705 B |
Before Width: | Height: | Size: 725 B |
Before Width: | Height: | Size: 809 B |
Before Width: | Height: | Size: 824 B |
Before Width: | Height: | Size: 829 B |
Before Width: | Height: | Size: 720 B |
Before Width: | Height: | Size: 719 B |
Before Width: | Height: | Size: 727 B |
Before Width: | Height: | Size: 755 B |
@@ -1,177 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by ogg.rc
|
||||
//
|
||||
#define IDS_NULLSOFT_VORBIS_DECODER_OLD 0
|
||||
#define IDS_PLEASE_ENTER_TAG_NAME 1
|
||||
#define IDS_TAG_NAME_CONTAINS_INVALID_CHARS 2
|
||||
#define IDOKAUTH 3
|
||||
#define IDS_ERASE_ALL_FIELDS_ON_LIST 3
|
||||
#define IDCANCELAUTH 4
|
||||
#define IDS_WARNING 4
|
||||
#define IDS_FILE_ERROR 5
|
||||
#define IDS_LENGTH 6
|
||||
#define IDS_AVERAGE_BITRATE 7
|
||||
#define IDS_FILE_SIZE 8
|
||||
#define IDS_NOMINAL_BITRATE 9
|
||||
#define IDS_MIN_BITRATE 10
|
||||
#define IDS_MAX_BITRATE 11
|
||||
#define IDS_CHANNELS 12
|
||||
#define IDS_SAMPLING_RATE 13
|
||||
#define IDS_SERIAL_NUMBER 14
|
||||
#define IDS_VERSION 15
|
||||
#define IDS_Vendor 16
|
||||
#define IDS_VENDOR 16
|
||||
#define IDS_TO_SIMPLE_MODE 17
|
||||
#define IDS_TO_ADVANCED_MODE 18
|
||||
#define IDS_OGG_VORBIS_INFO 19
|
||||
#define IDS_WRITE_ERROR 20
|
||||
#define IDS_BEST_RPM 21
|
||||
#define IDS_ABOUT 22
|
||||
#define IDS_LEAVE_AS_IS 24
|
||||
#define IDS_REMAP_6_CHANNELS 25
|
||||
#define IDS_DOWNMIX_TO_4_CHANNELS 26
|
||||
#define IDS_DOWNMIX_TO_2_CHANNELS_DS 27
|
||||
#define IDS_DOWNMIX_TO_2_CHANNELS_DS2 28
|
||||
#define IDS_DOWNMIX_TO_MONO 29
|
||||
#define IDS_CORRECT_FL_FC_FR_BL_BR_LFE 30
|
||||
#define IDS_BROKEN_FL_FR_FC_BL_BR_LFE 31
|
||||
#define IDS_IDLE 32
|
||||
#define IDS_ABOUT_TEXT 32
|
||||
#define IDS_LOWEST 33
|
||||
#define IDS_BELOW_NORMAL 34
|
||||
#define IDS_NORMAL 35
|
||||
#define IDS_ABOVE_NORMAL 36
|
||||
#define IDS_HIGHEST 37
|
||||
#define IDS_TIME_CRITICAL 38
|
||||
#define IDS_TITLE_PREFERENCES 39
|
||||
#define IDS_DO_NOT_ENABLE_24_BIT_OUTPUT 40
|
||||
#define IDS_ONE_TIME_FAQ_REMINDER 41
|
||||
#define IDS_RUNNING_ON_NT_OS 42
|
||||
#define IDS_RUNNING_ON_WIN9X 43
|
||||
#define IDS_NEVER 44
|
||||
#define IDS_PORT_80_ONLY 45
|
||||
#define IDS_ALWAYS 46
|
||||
#define IDS_SELECT_OUTPUT_DIRECTORY 47
|
||||
#define IDS_DECODING 48
|
||||
#define IDS_DISPLAY 49
|
||||
#define IDS_STREAMING 50
|
||||
#define IDS_CONNECTING 51
|
||||
#define IDS_PREBUFFERING 52
|
||||
#define IDS_AUTH_REQUIRED 53
|
||||
#define IDS_OGG_FILES 54
|
||||
#define IDS_NAME 55
|
||||
#define IDS_VALUE 56
|
||||
#define IDS_KBPS 57
|
||||
#define IDS_STRING2 58
|
||||
#define IDS_HZ 58
|
||||
#define IDS_GAME_SPEED 59
|
||||
#define IDS_STRING1 60
|
||||
#define IDS_BYTES 60
|
||||
#define IDS_FAMILY_STRING 61
|
||||
#define IDC_CONFIG_TAB1 101
|
||||
#define IDD_INFO_DLG 102
|
||||
#define IDC_CONFIG_TAB2 102
|
||||
#define IDC_CONFIG_TAB3 103
|
||||
#define IDD_INFO_DLG1 104
|
||||
#define IDC_CONFIG_TAB4 104
|
||||
#define IDD_ABOUT 112
|
||||
#define IDB_BITMAP1 115
|
||||
#define IDB_BITMAP2 116
|
||||
#define IDB_BITMAP3 117
|
||||
#define IDB_BITMAP4 118
|
||||
#define IDB_BITMAP5 119
|
||||
#define IDB_BITMAP6 120
|
||||
#define IDB_BITMAP7 121
|
||||
#define IDB_BITMAP8 122
|
||||
#define IDB_BITMAP9 123
|
||||
#define IDB_BITMAP10 124
|
||||
#define IDB_BITMAP11 125
|
||||
#define IDB_BITMAP12 126
|
||||
#define IDD_HTTPAUTH 128
|
||||
#define IDD_INFO 131
|
||||
#define IDD_DIALOG1 132
|
||||
#define IDD_CONFIG 132
|
||||
#define IDD_INFO_DLG_NEW 133
|
||||
#define IDD_INFO_PANEL_ADVANCED 134
|
||||
#define IDD_INFO_PANEL_SIMPLE 135
|
||||
#define IDB_PNG1 136
|
||||
#define IDB_PNG2 137
|
||||
#define IDB_PNG3 138
|
||||
#define IDB_PNG4 139
|
||||
#define IDB_PNG5 140
|
||||
#define IDB_PNG6 141
|
||||
#define IDB_PNG7 142
|
||||
#define IDB_PNG8 143
|
||||
#define IDB_PNG9 144
|
||||
#define IDB_PNG10 145
|
||||
#define IDB_PNG11 146
|
||||
#define IDB_PNG12 147
|
||||
#define IDC_LIST 1001
|
||||
#define IDC_NAME 1002
|
||||
#define IDC_TITLE 1002
|
||||
#define IDC_VALUE 1003
|
||||
#define IDC_ARTIST 1003
|
||||
#define IDC_HTTP_BSIZE 1004
|
||||
#define IDC_ALBUM 1004
|
||||
#define IDC_STREAM_SAVE 1005
|
||||
#define IDC_GENRE 1005
|
||||
#define IDC_FSAVE 1006
|
||||
#define IDC_YEAR 1006
|
||||
#define IDC_DATE 1006
|
||||
#define IDC_CUSTOM1 1007
|
||||
#define IDC_MISC 1007
|
||||
#define IDC_AVG_BR 1008
|
||||
#define IDC_FIX0R 1009
|
||||
#define IDC_PROXY 1012
|
||||
#define IDC_URL 1012
|
||||
#define IDC_SLIDER1 1013
|
||||
#define IDC_SLIDER2 1014
|
||||
#define IDC_BUTTON_ADD 1015
|
||||
#define IDC_BUTTON_DEL 1016
|
||||
#define IDC_BUTTON_DELALL 1017
|
||||
#define IDC_RPM 1018
|
||||
#define IDC_RPM2 1019
|
||||
#define IDC_MC6_DM 1020
|
||||
#define IDC_MC6_MAP 1021
|
||||
#define IDC_SSAVE_FMT 1022
|
||||
#define IDC_SSAVE_FMT_DEF 1023
|
||||
#define IDC_FULLBUF 1025
|
||||
#define IDC_EDITAUTH 1026
|
||||
#define IDC_REALM 1027
|
||||
#define IDC_TRACK 1028
|
||||
#define IDC_STATIC_MISC 1034
|
||||
#define IDC_STATIC_TAGS 1035
|
||||
#define IDC_STATIC_STD 1036
|
||||
#define IDC_STATIC_TRACK 1037
|
||||
#define IDC_SEPARATE 1038
|
||||
#define IDC_DELETE_ALL 1039
|
||||
#define IDC_RG 1040
|
||||
#define IDC_RG_MODE 1041
|
||||
#define IDC_NOCLIP 1042
|
||||
#define IDC_HARDLIMIT 1043
|
||||
#define IDC_PREAMP_STAT 1044
|
||||
#define IDC_TAB 1045
|
||||
#define IDC_MODE_TOGGLE 1053
|
||||
#define IDC_NEXT_STREAM 1054
|
||||
#define IDC_PREV_STREAM 1055
|
||||
#define IDC_STATIC_CS 1056
|
||||
#define IDC_HIDE_SPEC 1058
|
||||
#define IDC_COMMENT 1060
|
||||
#define IDC_ABOUT_TEXT 1061
|
||||
#define IDC_OS_BLAH 1062
|
||||
#define IDC_REMEMBER_INFOSIZE 1063
|
||||
#define IDC_FONTNAME 1064
|
||||
#define IDC_PREAMP_RG 1065
|
||||
#define IDS_NULLSOFT_VORBIS_DECODER 65534
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 148
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1067
|
||||
#define _APS_NEXT_SYMED_VALUE 105
|
||||
#endif
|
||||
#endif
|
@@ -1,108 +0,0 @@
|
||||
#ifndef _RF_H_
|
||||
#define _RF_H_
|
||||
|
||||
//based on Tempura specs.
|
||||
//NOT compatible with WA3 alphas
|
||||
|
||||
class WReader
|
||||
{
|
||||
protected:
|
||||
|
||||
/* WReader
|
||||
** WReader constructor
|
||||
*/
|
||||
WReader() : m_player(0) { }
|
||||
|
||||
public:
|
||||
|
||||
/* m_player
|
||||
** Filled by Winamp. Pointer to Winamp 3 core interface
|
||||
*/
|
||||
/*WPlayer_callback*/ void *m_player; //PP: hack. read_file.dll doesn't call it at all. simply don't touch it
|
||||
|
||||
/* GetDescription
|
||||
** Retrieves your plug-in's text description
|
||||
*/
|
||||
virtual char *GetDescription() { return "Unknown"; };
|
||||
|
||||
/* Open
|
||||
** Used to open a file, return 0 on success
|
||||
*/
|
||||
virtual int Open(char *url, bool *killswitch)=0;
|
||||
|
||||
/* Read
|
||||
** Returns number of BYTES read (if < length then eof or killswitch)
|
||||
*/
|
||||
virtual int Read(char *buffer, int length, bool *killswitch)=0;
|
||||
|
||||
/* GetLength
|
||||
** Returns length of the entire file in BYTES, return -1 on unknown/infinite (as for a stream)
|
||||
*/
|
||||
virtual int GetLength(void)=0;
|
||||
|
||||
/* CanSeek
|
||||
** Returns 1 if you can skip ahead in the file, 0 if not
|
||||
*/
|
||||
virtual int CanSeek(void)=0; //PP: currently available read_file.dll vesions can always seek in any direction
|
||||
|
||||
/* Seek
|
||||
** Jump to a certain absolute position
|
||||
*/
|
||||
virtual int Seek(int position, bool *killswitch)=0;
|
||||
|
||||
/* GetHeader
|
||||
** Retrieve header. Used in read_http to retrieve the HTTP header
|
||||
*/
|
||||
virtual char *GetHeader(char *name) { return 0; }
|
||||
|
||||
/* ~WReader
|
||||
** WReader virtual destructor
|
||||
*/
|
||||
//virtual ~WReader() { }
|
||||
virtual void Release(int) {};
|
||||
//PP: hack - shut up linker when getting rid of evil CRT library; seems to work OK under Tempura
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#define READ_VER 0x100
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* version
|
||||
** Version revision number
|
||||
*/
|
||||
int version;
|
||||
|
||||
/* description
|
||||
** Text description of the reader plug-in
|
||||
*/
|
||||
char *description;
|
||||
|
||||
/* create
|
||||
** Function pointer to create a reader module
|
||||
*/
|
||||
WReader *(*create)();
|
||||
|
||||
/* ismine
|
||||
** Determines whether or not a file should be read by this plug-in
|
||||
*/
|
||||
int (*ismine)(char *url);
|
||||
|
||||
} reader_source;
|
||||
|
||||
//exported symbol is:
|
||||
//int readerSource(HINSTANCE,reader_source**);
|
||||
|
||||
/*
|
||||
(not a part of Tempura specs)
|
||||
int _stdcall gzip_writefile(char* path,void* buf,DWORD size) - writes a memory block to a GZIP file - in_midi calls it from file info box
|
||||
|
||||
other hacks:
|
||||
recent versions understand file://... urls, can do partial file access (eg. "partial://00006666-66660000:c:\foo\bar.dat\zzz.wav" (zzz.wav is the "display name" + extension to make winamp select correct plug-in) and auto-detect CD drive letter (eg. #:\x.mp3 will scan all drives for that file; also works with partial:// )
|
||||
you can (for an example) build a playlist which will play Unreal soundtrack directly from the game CD on any system
|
||||
latest read_file.dll is bundled with the midi plug-in: http://www.blorp.com/~peter/zips/in_midi.zip
|
||||
*/
|
||||
|
||||
#endif
|
@@ -1,245 +0,0 @@
|
||||
#include "Shaper.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535897932384626433832795028842
|
||||
#endif
|
||||
|
||||
#define RANDBUFLEN 65536
|
||||
|
||||
#define RINT(x) ((x) >= 0 ? ((int)((x) + 0.5)) : ((int)((x) - 0.5)))
|
||||
|
||||
const int scoeffreq[] =
|
||||
{
|
||||
0, 48000, 44100, 37800, 32000, 22050, 48000, 44100
|
||||
};
|
||||
|
||||
|
||||
const int scoeflen[] =
|
||||
{
|
||||
1, 16, 20, 16, 16, 15, 16, 15
|
||||
};
|
||||
|
||||
const int samp[] =
|
||||
{
|
||||
8, 18, 27, 8, 8, 8, 10, 9
|
||||
};
|
||||
|
||||
const double shapercoefs[8][21] =
|
||||
{
|
||||
{
|
||||
-1
|
||||
}
|
||||
, /* triangular dither */
|
||||
|
||||
{ -2.8720729351043701172, 5.0413231849670410156, -6.2442994117736816406, 5.8483986854553222656,
|
||||
-3.7067542076110839844, 1.0495119094848632812, 1.1830236911773681641, -2.1126792430877685547,
|
||||
1.9094531536102294922, -0.99913084506988525391, 0.17090806365013122559, 0.32615602016448974609,
|
||||
-0.39127644896507263184, 0.26876461505889892578, -0.097676105797290802002, 0.023473845794796943665,
|
||||
}, /* 48k, N=16, amp=18 */
|
||||
|
||||
{ -2.6773197650909423828, 4.8308925628662109375, -6.570110321044921875, 7.4572014808654785156,
|
||||
-6.7263274192810058594, 4.8481650352478027344, -2.0412089824676513672, -0.7006359100341796875,
|
||||
2.9537565708160400391, -4.0800385475158691406, 4.1845216751098632812, -3.3311812877655029297,
|
||||
2.1179926395416259766, -0.879302978515625, 0.031759146600961685181, 0.42382788658142089844,
|
||||
-0.47882103919982910156, 0.35490813851356506348, -0.17496839165687561035, 0.060908168554306030273,
|
||||
}, /* 44.1k, N=20, amp=27 */
|
||||
|
||||
{ -1.6335992813110351562, 2.2615492343902587891, -2.4077029228210449219, 2.6341717243194580078,
|
||||
-2.1440362930297851562, 1.8153258562088012695, -1.0816224813461303711, 0.70302653312683105469,
|
||||
-0.15991993248462677002, -0.041549518704414367676, 0.29416576027870178223, -0.2518316805362701416,
|
||||
0.27766478061676025391, -0.15785403549671173096, 0.10165894031524658203, -0.016833892092108726501,
|
||||
}, /* 37.8k, N=16 */
|
||||
|
||||
{ -0.82901298999786376953, 0.98922657966613769531, -0.59825712442398071289, 1.0028809309005737305,
|
||||
-0.59938216209411621094, 0.79502451419830322266, -0.42723315954208374023, 0.54492527246475219727,
|
||||
-0.30792605876922607422, 0.36871799826622009277, -0.18792048096656799316, 0.2261127084493637085,
|
||||
-0.10573341697454452515, 0.11435490846633911133, -0.038800679147243499756, 0.040842197835445404053,
|
||||
}, /* 32k, N=16 */
|
||||
|
||||
{ -0.065229974687099456787, 0.54981261491775512695, 0.40278548002243041992, 0.31783768534660339355,
|
||||
0.28201797604560852051, 0.16985194385051727295, 0.15433363616466522217, 0.12507140636444091797,
|
||||
0.08903945237398147583, 0.064410120248794555664, 0.047146003693342208862, 0.032805237919092178345,
|
||||
0.028495194390416145325, 0.011695005930960178375, 0.011831838637590408325,
|
||||
}, /* 22.05k, N=15 */
|
||||
|
||||
{ -2.3925774097442626953, 3.4350297451019287109, -3.1853709220886230469, 1.8117271661758422852,
|
||||
0.20124770700931549072, -1.4759907722473144531, 1.7210904359817504883, -0.97746700048446655273,
|
||||
0.13790138065814971924, 0.38185903429985046387, -0.27421241998672485352, -0.066584214568138122559,
|
||||
0.35223302245140075684, -0.37672343850135803223, 0.23964276909828186035, -0.068674825131893157959,
|
||||
}, /* 48k, N=16, amp=10 */
|
||||
|
||||
{ -2.0833916664123535156, 3.0418450832366943359, -3.2047898769378662109, 2.7571926116943359375,
|
||||
-1.4978630542755126953, 0.3427594602108001709, 0.71733748912811279297, -1.0737057924270629883,
|
||||
1.0225815773010253906, -0.56649994850158691406, 0.20968692004680633545, 0.065378531813621520996,
|
||||
-0.10322438180446624756, 0.067442022264003753662, 0.00495197344571352005,
|
||||
}, /* 44.1k, N=15, amp=9 */
|
||||
|
||||
#if 0
|
||||
{ -3.0259189605712890625, 6.0268716812133789062, -9.195003509521484375, 11.824929237365722656,
|
||||
-12.767142295837402344, 11.917946815490722656, -9.1739168167114257812, 5.3712320327758789062,
|
||||
-1.1393624544143676758, -2.4484779834747314453, 4.9719839096069335938, -6.0392003059387207031,
|
||||
5.9359521865844726562, -4.903278350830078125, 3.5527443885803222656, -2.1909697055816650391,
|
||||
1.1672389507293701172, -0.4903914332389831543, 0.16519790887832641602, -0.023217858746647834778,
|
||||
}, /* 44.1k, N=20 */
|
||||
#endif
|
||||
};
|
||||
|
||||
#define POOLSIZE 97
|
||||
|
||||
Shaper::Shaper(int freq, int _nch, int min, int max, int _dtype, int pdf, double noiseamp)
|
||||
{
|
||||
int i;
|
||||
float pool[POOLSIZE] = {0};
|
||||
|
||||
nch = _nch;
|
||||
dtype = _dtype;
|
||||
|
||||
for (i = 1;i < 6;i++) if (freq == scoeffreq[i]) break;
|
||||
/* if ((dtype == 3 || dtype == 4) && i == 6) {
|
||||
fprintf(stderr,"Warning: ATH based noise shaping for destination frequency %dHz is not available, using triangular dither\n",freq);
|
||||
}*/
|
||||
if (dtype == 2 || i == 6) i = 0;
|
||||
if (dtype == 4 && (i == 1 || i == 2)) i += 5;
|
||||
|
||||
shaper_type = i;
|
||||
|
||||
shapebuf = (double**)malloc(sizeof(double *) * nch);
|
||||
shaper_len = scoeflen[shaper_type];
|
||||
|
||||
for (i = 0;i < nch;i++)
|
||||
shapebuf[i] = (double*)calloc(shaper_len, sizeof(double));
|
||||
|
||||
shaper_clipmin = min;
|
||||
shaper_clipmax = max;
|
||||
|
||||
randbuf = (REAL*)malloc(sizeof(REAL) * RANDBUFLEN);
|
||||
|
||||
for (i = 0;i < POOLSIZE;i++) pool[i] = warandf();
|
||||
|
||||
switch (pdf)
|
||||
{
|
||||
case DITHER_RECTANGLE: // rectangular
|
||||
for (i = 0;i < RANDBUFLEN;i++)
|
||||
{
|
||||
float r;
|
||||
int p;
|
||||
|
||||
p = warand() % POOLSIZE;
|
||||
r = pool[p]; pool[p] = warandf();
|
||||
randbuf[i] = (REAL)(noiseamp * (((double)r) - 0.5));
|
||||
}
|
||||
break;
|
||||
|
||||
case DITHER_TRIANGLE:
|
||||
for (i = 0;i < RANDBUFLEN;i++)
|
||||
{
|
||||
float r1, r2;
|
||||
int p;
|
||||
|
||||
p = warand() % POOLSIZE;
|
||||
r1 = pool[p]; pool[p] = warandf();
|
||||
p = warand() % POOLSIZE;
|
||||
r2 = pool[p]; pool[p] = warandf();
|
||||
randbuf[i] = (REAL)(noiseamp * ((((double)r1)) - (((double)r2))));
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case DITHER_GAUSSIAN: // gaussian
|
||||
for (i = 0;i < RANDBUFLEN;i++)
|
||||
{
|
||||
int sw = 0;
|
||||
double t, u;
|
||||
double r;
|
||||
int p;
|
||||
|
||||
if (sw == 0)
|
||||
{
|
||||
sw = 1;
|
||||
|
||||
p = warand() % POOLSIZE;
|
||||
r = ((double)pool[p]); pool[p] = warandf();
|
||||
|
||||
t = sqrt(-2 * log(1 - r));
|
||||
|
||||
p = warand() % POOLSIZE;
|
||||
r = ((double)pool[p]); pool[p] = warandf();
|
||||
|
||||
u = 2 * M_PI * r;
|
||||
|
||||
randbuf[i] = noiseamp * t * cos(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
sw = 0;
|
||||
|
||||
randbuf[i] = noiseamp * t * sin(u);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
randptr = 0;
|
||||
|
||||
// if (dtype == 0 || dtype == 1) return 1;
|
||||
//return samp[shaper_type];
|
||||
}
|
||||
|
||||
Shaper::~Shaper()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < nch;i++) free(shapebuf[i]);
|
||||
free(shapebuf);
|
||||
free(randbuf);
|
||||
}
|
||||
|
||||
int Shaper::do_shaping(double s,/*double *peak,*/int ch)
|
||||
{
|
||||
double u, h;
|
||||
int i;
|
||||
|
||||
if (dtype == 1)
|
||||
{
|
||||
s += randbuf[randptr++ & (RANDBUFLEN-1)];
|
||||
|
||||
if (s < shaper_clipmin)
|
||||
{
|
||||
//double d = (double)s / shaper_clipmin;
|
||||
//*peak = *peak < d ? d : *peak;
|
||||
s = shaper_clipmin;
|
||||
}
|
||||
if (s > shaper_clipmax)
|
||||
{
|
||||
//double d = (double)s / shaper_clipmax;
|
||||
//*peak = *peak < d ? d : *peak;
|
||||
s = shaper_clipmax;
|
||||
}
|
||||
|
||||
return RINT(s);
|
||||
}
|
||||
|
||||
h = 0;
|
||||
for (i = 0;i < shaper_len;i++)
|
||||
h += shapercoefs[shaper_type][i] * shapebuf[ch][i];
|
||||
s += h;
|
||||
u = s;
|
||||
s += randbuf[randptr++ & (RANDBUFLEN-1)];
|
||||
if (s < shaper_clipmin)
|
||||
{
|
||||
//double d = (double)s / shaper_clipmin;
|
||||
//*peak = *peak < d ? d : *peak;
|
||||
s = shaper_clipmin;
|
||||
}
|
||||
if (s > shaper_clipmax)
|
||||
{
|
||||
//double d = (double)s / shaper_clipmax;
|
||||
//*peak = *peak < d ? d : *peak;
|
||||
s = shaper_clipmax;
|
||||
}
|
||||
s = RINT(s);
|
||||
for (i = shaper_len - 2;i >= 0;i--) shapebuf[ch][i+1] = shapebuf[ch][i];
|
||||
shapebuf[ch][0] = s - u;
|
||||
|
||||
return (int)s;
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
//from SSRC
|
||||
#ifndef NULLSOFT_VORBIS_SHAPER_H
|
||||
#define NULLSOFT_VORBIS_SHAPER_H
|
||||
#include "main.h"
|
||||
|
||||
typedef float REAL;
|
||||
enum
|
||||
{
|
||||
DITHER_RECTANGLE=0,
|
||||
DITHER_TRIANGLE=1,
|
||||
DITHER_GAUSSIAN=2,
|
||||
};
|
||||
class Shaper
|
||||
{
|
||||
double **shapebuf;
|
||||
int shaper_type,shaper_len,shaper_clipmin,shaper_clipmax;
|
||||
REAL *randbuf;
|
||||
int randptr;
|
||||
int dtype;
|
||||
int nch;
|
||||
|
||||
public:
|
||||
Shaper(int freq,int _nch,int min,int max,int _dtype,int pdf,double noiseamp);
|
||||
|
||||
int do_shaping(double s,/*double *peak,*/int ch);
|
||||
|
||||
~Shaper();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,2 +0,0 @@
|
||||
#include "main.h"
|
||||
|
@@ -1,491 +0,0 @@
|
||||
/* This program is licensed under the GNU Library General Public License, version 2,
|
||||
* a copy of which is included with this program (LICENCE.LGPL).
|
||||
*
|
||||
* (c) 2000-2001 Michael Smith <msmith@labyrinth.net.au>
|
||||
*
|
||||
*
|
||||
* Comment editing backend, suitable for use by nice frontend interfaces.
|
||||
*
|
||||
* last modified: $Id: vcedit.c,v 1.3 2013/10/22 14:17:11 dromagod Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include <vorbis/codec.h>
|
||||
|
||||
#include "vcedit.h"
|
||||
//#include "i18n.h"
|
||||
|
||||
|
||||
#define CHUNKSIZE 4096
|
||||
|
||||
vcedit_state *vcedit_new_state(void)
|
||||
{
|
||||
vcedit_state *state = malloc(sizeof(vcedit_state));
|
||||
memset(state, 0, sizeof(vcedit_state));
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
char *vcedit_error(vcedit_state *state)
|
||||
{
|
||||
return state->lasterror;
|
||||
}
|
||||
|
||||
vorbis_comment *vcedit_comments(vcedit_state *state)
|
||||
{
|
||||
return state->vc;
|
||||
}
|
||||
|
||||
static void vcedit_clear_internals(vcedit_state *state)
|
||||
{
|
||||
if(state->vc)
|
||||
{
|
||||
vorbis_comment_clear(state->vc);
|
||||
free(state->vc);
|
||||
}
|
||||
if(state->os)
|
||||
{
|
||||
ogg_stream_clear(state->os);
|
||||
free(state->os);
|
||||
}
|
||||
if(state->oy)
|
||||
{
|
||||
ogg_sync_clear(state->oy);
|
||||
free(state->oy);
|
||||
}
|
||||
if(state->vendor)
|
||||
free(state->vendor);
|
||||
if(state->mainbuf)
|
||||
free(state->mainbuf);
|
||||
if(state->bookbuf)
|
||||
free(state->bookbuf);
|
||||
if(state->vi) {
|
||||
vorbis_info_clear(state->vi);
|
||||
free(state->vi);
|
||||
}
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
}
|
||||
|
||||
void vcedit_clear(vcedit_state *state)
|
||||
{
|
||||
if(state)
|
||||
{
|
||||
vcedit_clear_internals(state);
|
||||
free(state);
|
||||
}
|
||||
}
|
||||
|
||||
/* Next two functions pulled straight from libvorbis, apart from one change
|
||||
* - we don't want to overwrite the vendor string.
|
||||
*/
|
||||
static void _v_writestring(oggpack_buffer *o,char *s, int len)
|
||||
{
|
||||
while(len--)
|
||||
{
|
||||
oggpack_write(o,*s++,8);
|
||||
}
|
||||
}
|
||||
|
||||
static int _commentheader_out(vorbis_comment *vc, char *vendor, ogg_packet *op)
|
||||
{
|
||||
oggpack_buffer opb;
|
||||
|
||||
oggpack_writeinit(&opb);
|
||||
|
||||
/* preamble */
|
||||
oggpack_write(&opb,0x03,8);
|
||||
_v_writestring(&opb,"vorbis", 6);
|
||||
|
||||
/* vendor */
|
||||
oggpack_write(&opb,(unsigned long)strlen(vendor),32);
|
||||
_v_writestring(&opb,vendor, (int)strlen(vendor));
|
||||
|
||||
/* comments */
|
||||
oggpack_write(&opb,vc->comments,32);
|
||||
if(vc->comments){
|
||||
int i;
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(vc->user_comments[i]){
|
||||
oggpack_write(&opb,vc->comment_lengths[i],32);
|
||||
_v_writestring(&opb,vc->user_comments[i],
|
||||
vc->comment_lengths[i]);
|
||||
}else{
|
||||
oggpack_write(&opb,0,32);
|
||||
}
|
||||
}
|
||||
}
|
||||
oggpack_write(&opb,1,1);
|
||||
|
||||
op->packet = _ogg_malloc(oggpack_bytes(&opb));
|
||||
memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
|
||||
|
||||
op->bytes=oggpack_bytes(&opb);
|
||||
op->b_o_s=0;
|
||||
op->e_o_s=0;
|
||||
op->granulepos=0;
|
||||
|
||||
oggpack_writeclear(&opb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _blocksize(vcedit_state *s, ogg_packet *p)
|
||||
{
|
||||
int this = vorbis_packet_blocksize(s->vi, p);
|
||||
int ret = (this + s->prevW)/4;
|
||||
|
||||
if(!s->prevW)
|
||||
{
|
||||
s->prevW = this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->prevW = this;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _fetch_next_packet(vcedit_state *s, ogg_packet *p, ogg_page *page)
|
||||
{
|
||||
int result = ogg_stream_packetout(s->os, p);
|
||||
|
||||
if(result > 0)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
if(s->eosin)
|
||||
return 0;
|
||||
while(ogg_sync_pageout(s->oy, page) <= 0)
|
||||
{
|
||||
char *buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
|
||||
int bytes = (int)s->read(buffer,1, CHUNKSIZE, s->in);
|
||||
ogg_sync_wrote(s->oy, bytes);
|
||||
if(bytes == 0)
|
||||
return 0;
|
||||
}
|
||||
if(ogg_page_eos(page))
|
||||
s->eosin = 1;
|
||||
else if(ogg_page_serialno(page) != s->serial)
|
||||
{
|
||||
s->eosin = 1;
|
||||
s->extrapage = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ogg_stream_pagein(s->os, page);
|
||||
return _fetch_next_packet(s, p, page);
|
||||
}
|
||||
}
|
||||
|
||||
int vcedit_open(vcedit_state *state, FILE *in)
|
||||
{
|
||||
return vcedit_open_callbacks(state, (void *)in,
|
||||
(vcedit_read_func)fread, (vcedit_write_func)fwrite);
|
||||
}
|
||||
|
||||
int vcedit_open_callbacks(vcedit_state *state, void *in,
|
||||
vcedit_read_func read_func, vcedit_write_func write_func)
|
||||
{
|
||||
|
||||
char *buffer;
|
||||
int bytes,i;
|
||||
ogg_packet *header;
|
||||
ogg_packet header_main;
|
||||
ogg_packet header_comments;
|
||||
ogg_packet header_codebooks;
|
||||
ogg_page og;
|
||||
|
||||
state->in = in;
|
||||
state->read = read_func;
|
||||
state->write = write_func;
|
||||
|
||||
state->oy = malloc(sizeof(ogg_sync_state));
|
||||
ogg_sync_init(state->oy);
|
||||
|
||||
buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
|
||||
bytes = (int)state->read(buffer, 1, CHUNKSIZE, state->in);
|
||||
|
||||
ogg_sync_wrote(state->oy, bytes);
|
||||
|
||||
if(ogg_sync_pageout(state->oy, &og) != 1)
|
||||
{
|
||||
if(bytes<CHUNKSIZE)
|
||||
state->lasterror = "Input truncated or empty.";
|
||||
else
|
||||
state->lasterror = "Input is not an Ogg bitstream.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
state->serial = ogg_page_serialno(&og);
|
||||
|
||||
state->os = malloc(sizeof(ogg_stream_state));
|
||||
ogg_stream_init(state->os, state->serial);
|
||||
|
||||
state->vi = malloc(sizeof(vorbis_info));
|
||||
vorbis_info_init(state->vi);
|
||||
|
||||
state->vc = malloc(sizeof(vorbis_comment));
|
||||
vorbis_comment_init(state->vc);
|
||||
|
||||
if(ogg_stream_pagein(state->os, &og) < 0)
|
||||
{
|
||||
state->lasterror = "Error reading first page of Ogg bitstream.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(ogg_stream_packetout(state->os, &header_main) != 1)
|
||||
{
|
||||
state->lasterror = "Error reading initial header packet.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(vorbis_synthesis_headerin(state->vi, state->vc, &header_main) < 0)
|
||||
{
|
||||
state->lasterror = "Ogg bitstream does not contain vorbis data.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
state->mainlen = header_main.bytes;
|
||||
state->mainbuf = malloc(state->mainlen);
|
||||
memcpy(state->mainbuf, header_main.packet, header_main.bytes);
|
||||
|
||||
i = 0;
|
||||
header = &header_comments;
|
||||
while(i<2) {
|
||||
while(i<2) {
|
||||
int result = ogg_sync_pageout(state->oy, &og);
|
||||
if(result == 0) break; /* Too little data so far */
|
||||
else if(result == 1)
|
||||
{
|
||||
ogg_stream_pagein(state->os, &og);
|
||||
while(i<2)
|
||||
{
|
||||
result = ogg_stream_packetout(state->os, header);
|
||||
if(result == 0) break;
|
||||
if(result == -1)
|
||||
{
|
||||
state->lasterror = "Corrupt secondary header.";
|
||||
goto err;
|
||||
}
|
||||
vorbis_synthesis_headerin(state->vi, state->vc, header);
|
||||
if(i==1)
|
||||
{
|
||||
state->booklen = header->bytes;
|
||||
state->bookbuf = malloc(state->booklen);
|
||||
memcpy(state->bookbuf, header->packet,
|
||||
header->bytes);
|
||||
}
|
||||
i++;
|
||||
header = &header_codebooks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
|
||||
bytes = (int)state->read(buffer, 1, CHUNKSIZE, state->in);
|
||||
if(bytes == 0 && i < 2)
|
||||
{
|
||||
state->lasterror = "EOF before end of vorbis headers.";
|
||||
goto err;
|
||||
}
|
||||
ogg_sync_wrote(state->oy, bytes);
|
||||
}
|
||||
|
||||
/* Copy the vendor tag */
|
||||
bytes = (int)strlen(state->vc->vendor);
|
||||
state->vendor = malloc(bytes +1);
|
||||
strncpy(state->vendor, state->vc->vendor, bytes);
|
||||
|
||||
/* Headers are done! */
|
||||
return 0;
|
||||
|
||||
err:
|
||||
vcedit_clear_internals(state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vcedit_write(vcedit_state *state, void *out)
|
||||
{
|
||||
ogg_stream_state streamout;
|
||||
ogg_packet header_main;
|
||||
ogg_packet header_comments;
|
||||
ogg_packet header_codebooks;
|
||||
|
||||
ogg_page ogout, ogin;
|
||||
ogg_packet op;
|
||||
ogg_int64_t granpos = 0;
|
||||
int result;
|
||||
char *buffer;
|
||||
int bytes;
|
||||
int needflush=0, needout=0;
|
||||
|
||||
state->eosin = 0;
|
||||
state->extrapage = 0;
|
||||
|
||||
header_main.bytes = state->mainlen;
|
||||
header_main.packet = state->mainbuf;
|
||||
header_main.b_o_s = 1;
|
||||
header_main.e_o_s = 0;
|
||||
header_main.granulepos = 0;
|
||||
|
||||
header_codebooks.bytes = state->booklen;
|
||||
header_codebooks.packet = state->bookbuf;
|
||||
header_codebooks.b_o_s = 0;
|
||||
header_codebooks.e_o_s = 0;
|
||||
header_codebooks.granulepos = 0;
|
||||
|
||||
ogg_stream_init(&streamout, state->serial);
|
||||
|
||||
_commentheader_out(state->vc, state->vendor, &header_comments);
|
||||
|
||||
ogg_stream_packetin(&streamout, &header_main);
|
||||
ogg_stream_packetin(&streamout, &header_comments);
|
||||
ogg_stream_packetin(&streamout, &header_codebooks);
|
||||
|
||||
while((result = ogg_stream_flush(&streamout, &ogout)))
|
||||
{
|
||||
if(state->write(ogout.header,1,ogout.header_len, out) !=
|
||||
(size_t) ogout.header_len)
|
||||
goto cleanup;
|
||||
if(state->write(ogout.body,1,ogout.body_len, out) !=
|
||||
(size_t) ogout.body_len)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while(_fetch_next_packet(state, &op, &ogin))
|
||||
{
|
||||
int size;
|
||||
size = _blocksize(state, &op);
|
||||
granpos += size;
|
||||
|
||||
if(needflush)
|
||||
{
|
||||
if(ogg_stream_flush(&streamout, &ogout))
|
||||
{
|
||||
if(state->write(ogout.header,1,ogout.header_len,
|
||||
out) != (size_t) ogout.header_len)
|
||||
goto cleanup;
|
||||
if(state->write(ogout.body,1,ogout.body_len,
|
||||
out) != (size_t) ogout.body_len)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else if(needout)
|
||||
{
|
||||
if(ogg_stream_pageout(&streamout, &ogout))
|
||||
{
|
||||
if(state->write(ogout.header,1,ogout.header_len,
|
||||
out) != (size_t) ogout.header_len)
|
||||
goto cleanup;
|
||||
if(state->write(ogout.body,1,ogout.body_len,
|
||||
out) != (size_t) ogout.body_len)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
needflush=needout=0;
|
||||
|
||||
if(op.granulepos == -1)
|
||||
{
|
||||
op.granulepos = granpos;
|
||||
ogg_stream_packetin(&streamout, &op);
|
||||
}
|
||||
else /* granulepos is set, validly. Use it, and force a flush to
|
||||
account for shortened blocks (vcut) when appropriate */
|
||||
{
|
||||
if(granpos > op.granulepos)
|
||||
{
|
||||
granpos = op.granulepos;
|
||||
ogg_stream_packetin(&streamout, &op);
|
||||
needflush=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ogg_stream_packetin(&streamout, &op);
|
||||
needout=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
streamout.e_o_s = 1;
|
||||
while(ogg_stream_flush(&streamout, &ogout))
|
||||
{
|
||||
if(state->write(ogout.header,1,ogout.header_len,
|
||||
out) != (size_t) ogout.header_len)
|
||||
goto cleanup;
|
||||
if(state->write(ogout.body,1,ogout.body_len,
|
||||
out) != (size_t) ogout.body_len)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (state->extrapage)
|
||||
{
|
||||
if(state->write(ogin.header,1,ogin.header_len,
|
||||
out) != (size_t) ogin.header_len)
|
||||
goto cleanup;
|
||||
if (state->write(ogin.body,1,ogin.body_len, out) !=
|
||||
(size_t) ogin.body_len)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
state->eosin=0; /* clear it, because not all paths to here do */
|
||||
while(!state->eosin) /* We reached eos, not eof */
|
||||
{
|
||||
/* We copy the rest of the stream (other logical streams)
|
||||
* through, a page at a time. */
|
||||
while(1)
|
||||
{
|
||||
result = ogg_sync_pageout(state->oy, &ogout);
|
||||
if(result==0)
|
||||
break;
|
||||
if(result<0)
|
||||
state->lasterror = "Corrupt or missing data, continuing...";
|
||||
else
|
||||
{
|
||||
/* Don't bother going through the rest, we can just
|
||||
* write the page out now */
|
||||
if(state->write(ogout.header,1,ogout.header_len,
|
||||
out) != (size_t) ogout.header_len) {
|
||||
// fprintf(stderr, "Bumming out\n");
|
||||
goto cleanup;
|
||||
}
|
||||
if(state->write(ogout.body,1,ogout.body_len, out) !=
|
||||
(size_t) ogout.body_len) {
|
||||
// fprintf(stderr, "Bumming out 2\n");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
|
||||
bytes = (int)state->read(buffer,1, CHUNKSIZE, state->in);
|
||||
ogg_sync_wrote(state->oy, bytes);
|
||||
if(bytes == 0)
|
||||
{
|
||||
state->eosin = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
ogg_stream_clear(&streamout);
|
||||
ogg_packet_clear(&header_comments);
|
||||
|
||||
free(state->mainbuf);
|
||||
free(state->bookbuf);
|
||||
state->mainbuf = state->bookbuf = NULL;
|
||||
|
||||
if(!state->eosin)
|
||||
{
|
||||
state->lasterror =
|
||||
"Error writing stream to output. "
|
||||
"Output stream may be corrupted or truncated.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,62 +0,0 @@
|
||||
/* This program is licensed under the GNU Library General Public License, version 2,
|
||||
* a copy of which is included with this program (with filename LICENSE.LGPL).
|
||||
*
|
||||
* (c) 2000-2001 Michael Smith <msmith@labyrinth.net.au>
|
||||
*
|
||||
* VCEdit header.
|
||||
*
|
||||
* last modified: $ID:$
|
||||
*/
|
||||
|
||||
#ifndef __VCEDIT_H
|
||||
#define __VCEDIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include <vorbis/codec.h>
|
||||
|
||||
typedef size_t (*vcedit_read_func)(void *, size_t, size_t, void *);
|
||||
typedef size_t (*vcedit_write_func)(const void *, size_t, size_t, void *);
|
||||
|
||||
typedef struct {
|
||||
ogg_sync_state *oy;
|
||||
ogg_stream_state *os;
|
||||
|
||||
vorbis_comment *vc;
|
||||
vorbis_info *vi;
|
||||
|
||||
vcedit_read_func read;
|
||||
vcedit_write_func write;
|
||||
|
||||
void *in;
|
||||
long serial;
|
||||
unsigned char *mainbuf;
|
||||
unsigned char *bookbuf;
|
||||
int mainlen;
|
||||
int booklen;
|
||||
char *lasterror;
|
||||
char *vendor;
|
||||
int prevW;
|
||||
int extrapage;
|
||||
int eosin;
|
||||
} vcedit_state;
|
||||
|
||||
extern vcedit_state * vcedit_new_state(void);
|
||||
extern void vcedit_clear(vcedit_state *state);
|
||||
extern vorbis_comment * vcedit_comments(vcedit_state *state);
|
||||
extern int vcedit_open(vcedit_state *state, FILE *in);
|
||||
extern int vcedit_open_callbacks(vcedit_state *state, void *in,
|
||||
vcedit_read_func read_func, vcedit_write_func write_func);
|
||||
extern int vcedit_write(vcedit_state *state, void *out);
|
||||
extern char * vcedit_error(vcedit_state *state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __VCEDIT_H */
|
||||
|
@@ -1,39 +0,0 @@
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#include "../../../Winamp/buildType.h"
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,79,0,0
|
||||
PRODUCTVERSION WINAMP_PRODUCTVER
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Winamp SA"
|
||||
VALUE "FileDescription", "Winamp Input Plug-in"
|
||||
VALUE "FileVersion", "1,79,0,0"
|
||||
VALUE "InternalName", "Nullsoft Vorbis Decoder"
|
||||
VALUE "LegalCopyright", "Copyright <20> 2001-2023 Winamp SA"
|
||||
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
|
||||
VALUE "OriginalFilename", "in_vorbis.dll"
|
||||
VALUE "ProductName", "Winamp"
|
||||
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
@@ -1,2 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "api__in_vorbis.h"
|
@@ -1,114 +0,0 @@
|
||||
libdiscid ChangeLog:
|
||||
--------------------
|
||||
|
||||
libdiscid-0.6.2:
|
||||
|
||||
- ISRC and MCN support on BSD
|
||||
- LIB-60: fix make check for default device on generic/unknown platform
|
||||
- make Doxygen output reproducible (no timestamps)
|
||||
- remove newline for Linux device "1" from proc
|
||||
|
||||
libdiscid-0.6.1:
|
||||
|
||||
- LIB-59: windows: fix bug preventing ISRC reads
|
||||
|
||||
libdiscid-0.6.0:
|
||||
|
||||
- LIB-41: add discid_get_troc_string() for fuzzy toc lookup
|
||||
- LIB-54: add libmusicbrainz example with fuzzy toc lookup
|
||||
- LIB-43: windows: the default drive is the first cd drive letter
|
||||
- LIB-45: Linux/BSD/Solaris: try several possible default device names
|
||||
- LIB-28: Mac: allow drive numbers as devices, default now "1"
|
||||
- LIB-55, LIB-56: allow drive numbers for Windows and Linux
|
||||
- LIB-53: discid_get_submission_url() returns the new NGS url
|
||||
currently no functional change, the old url was redirected
|
||||
- LIB-52: more validation for parameters of discid_put()
|
||||
- LIB-48: assert successful read/put when API is used
|
||||
- the discisrc example prints the name of the device used
|
||||
|
||||
libdiscid-0.5.2:
|
||||
|
||||
- LIB-51: fix ISRC reading on Mac OS X again
|
||||
- LIB-50: fix segfault in mb_disc_load_toc on Solaris
|
||||
- LIB-26: add a better test suite, including valgrind memcheck target
|
||||
- print time information in the discid example
|
||||
|
||||
libdiscid-0.5.1:
|
||||
|
||||
- LIB-40: discid_get_webservice_url() (web service version 1) is deprecated
|
||||
please use libmusicbrainz to gather metadata by disc ID
|
||||
- LIB-7: rewrote data track handling, releases with multiple data tracks
|
||||
This also fixes LIB-18 (no ID for DVDs) and LIB-9 (PS/PS2 CDs)
|
||||
- LIB-44: fix invalid disc IDs on first read of multi-session discs
|
||||
- LIB-37: Autotools optimization (non-recursive build etc.)
|
||||
- LIB-42: remove Windows 9x platform code
|
||||
- renamed openbsd platform code to netbsd, still used by both.
|
||||
|
||||
libdiscid-0.5.0:
|
||||
|
||||
- LIB-29: add read_sparse() for faster reading again
|
||||
- LIB-35: add HAVE_SPARSE_READ and VERSION_* defines
|
||||
- LIB-36: hide internal symbols on Linux/Unix
|
||||
- LIB-34: distmac and distwin32 cmake targets
|
||||
|
||||
libdiscid-0.4.1:
|
||||
|
||||
- fix distribution: include disc_generic.c in Autotools dist
|
||||
|
||||
libdiscid-0.4.0:
|
||||
|
||||
- LIB-23: add has_feature() and get_feature_list() to API (platform check)
|
||||
- add get_version_string() to API
|
||||
- CMake : add FreeBSD, NetBSD, OpenBSD -> all platforms supported
|
||||
- LIB-24: support generic platform (discid_put() only)
|
||||
- Win32 : Added versioninfo resource to DLL
|
||||
- LIB-32: change libtool from -version-info to -version-name
|
||||
- LIB-27: fix (k)FreeBSD includes
|
||||
- fix lots of compiler warnings
|
||||
|
||||
libdiscid-0.3.2:
|
||||
|
||||
- fix distribution so it works for autotools AND cmake
|
||||
|
||||
libdiscid-0.3.1:
|
||||
|
||||
- ISRC and MCN support on Linux
|
||||
- Autotools: fix Windows, remove unneeded libs on SunOS
|
||||
- CMake: add Cygwin, add SunOS, fix Mac OS X
|
||||
- updated docs, created INSTALL file
|
||||
|
||||
libdiscid-0.3.0:
|
||||
|
||||
- Fixed reading of 99 track CDs on Mac OS X.
|
||||
- Added API for reading ISRCs and MCNs (implemented on Windows and Mac OS X).
|
||||
- Added Solaris, OpenBSD and kFreeBSD support.
|
||||
|
||||
libdiscid-0.2.2:
|
||||
|
||||
- Set libtool version number to 2:1:2 because it is backwards compatible
|
||||
with versions 0.1.x. Thanks to Luks for spotting this.
|
||||
|
||||
|
||||
libdiscid-0.2.1:
|
||||
|
||||
- Added code for automatic CD drive detection on darwin (Rob).
|
||||
|
||||
|
||||
libdiscid-0.2.0:
|
||||
|
||||
- Use accurate TOC reading method for multi-session CDs on
|
||||
Windows NT/2000/XP (Lukas).
|
||||
- Replace custom MSVC makefile with CMake build system (Lukas).
|
||||
- Added support for FreeBSD (Patrick Hurrelmann).
|
||||
- Addded the discid_get_webservice_url() function (Rob).
|
||||
|
||||
|
||||
libdiscid-0.1.1:
|
||||
|
||||
- Use generic 'cdaudio' device name on windows (Lukas).
|
||||
|
||||
|
||||
libdiscid-0.1.0:
|
||||
|
||||
- Initial public release.
|
||||
|
@@ -1,30 +0,0 @@
|
||||
A Library for creating MusicBrainz DiscIDs
|
||||
------------------------------------------
|
||||
|
||||
libdiscid is a C library for creating MusicBrainz DiscIDs from audio CDs.
|
||||
It reads a CD's table of contents (TOC) and generates an identifier which
|
||||
can be used to lookup the CD at MusicBrainz (http://musicbrainz.org).
|
||||
Additionally, it provides a submission URL for adding the DiscID to the
|
||||
database.
|
||||
|
||||
The library also provides FreeDB disc IDs, and MCN + ISRCs, if available.
|
||||
|
||||
The interface of this library is new, but the DiscID algorithm and the
|
||||
operating system dependent CD-ROM/DVD-ROM access code have been ported
|
||||
from libmusicbrainz version 2.
|
||||
|
||||
|
||||
Please report all bugs you find via the MusicBrainz bug tracker.
|
||||
Don't forget to state which OS and what version you are using:
|
||||
|
||||
http://tickets.musicbrainz.org/browse/LIB
|
||||
|
||||
Questions about this package may be posted to the MusicBrainz
|
||||
development mailing list (mb-devel):
|
||||
|
||||
http://musicbrainz.org/doc/Communication/Mailing_Lists
|
||||
|
||||
More information can be found at the package's official homepage:
|
||||
|
||||
http://musicbrainz.org/doc/libdiscid
|
||||
|
@@ -1,486 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2013 Johannes Dewender
|
||||
Copyright (C) 2006-2010 Lukas Lalinsky
|
||||
Copyright (C) 2006 Matthias Friedrich
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
#ifndef MUSICBRAINZ_DISC_ID_H
|
||||
#define MUSICBRAINZ_DISC_ID_H
|
||||
|
||||
#if (defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__))
|
||||
# ifdef libdiscid_EXPORTS
|
||||
# define LIBDISCID_API __declspec(dllexport)
|
||||
# else
|
||||
# define LIBDISCID_API __declspec(dllimport)
|
||||
# endif
|
||||
# define LIBDISCID_INTERNAL
|
||||
#elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
# define LIBDISCID_API
|
||||
# define LIBDISCID_INTERNAL __attribute__((visibility("hidden")))
|
||||
#elif defined(__SUNPRO_C)
|
||||
# define LIBDISCID_API __global
|
||||
# define LIBDISCID_INTERNAL __hidden
|
||||
#else
|
||||
# define LIBDISCID_API
|
||||
# define LIBDISCID_INTERNAL
|
||||
#endif
|
||||
|
||||
#if (defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__))
|
||||
#define LIBDISCID_DEPRECATED __declspec(deprecated)
|
||||
#elif (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) || defined(__clang__)
|
||||
#define LIBDISCID_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define LIBDISCID_DEPRECATED
|
||||
#endif
|
||||
|
||||
#define DISCID_VERSION_MAJOR @libdiscid_MAJOR@
|
||||
#define DISCID_VERSION_MINOR @libdiscid_MINOR@
|
||||
#define DISCID_VERSION_PATCH @libdiscid_PATCH@
|
||||
#define DISCID_VERSION_NUM @libdiscid_VERSION_NUM@
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \mainpage libdiscid
|
||||
* \section intro Introduction
|
||||
*
|
||||
* Libdiscid is a C library for calculating DiscIDs
|
||||
* (<a href="http://musicbrainz.org/doc/Disc ID">MusicBrainz</a>
|
||||
* and <a href="http://freedb.org">freedb</a>)
|
||||
* for Audio CDs.
|
||||
* Additionally the library can extract the MCN/UPC/EAN and the
|
||||
* <a href="http://musicbrainz.org/doc/ISRC">ISRCs</a> from disc.
|
||||
*
|
||||
* The idea is to have an easy to use library without any dependencies
|
||||
* that can be used from scripting languages.
|
||||
*
|
||||
* The API is documented in discid.h.
|
||||
*
|
||||
* \section examples Examples
|
||||
*
|
||||
* This is an example of the most basic usage:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* DiscId *disc = discid_new();
|
||||
*
|
||||
* if ( discid_read_sparse(disc, "/dev/cdrom", 0) == 0 ) {
|
||||
* fprintf(stderr, "Error: %s\n", discid_get_error_msg(disc));
|
||||
* return 1;
|
||||
* }
|
||||
*
|
||||
* printf("DiscID : %s\n", discid_get_id(disc));
|
||||
* printf("Submit via : %s\n", discid_get_submission_url(disc));
|
||||
*
|
||||
* discid_free(disc);
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \section Building
|
||||
*
|
||||
* libdiscid provides a pkg-config script that returns the necessary compiler and linker flags, as well as the
|
||||
* version number. To build a small sample program one would use:
|
||||
*
|
||||
* @par
|
||||
* <tt>gcc libdiscid-test.c \`pkg-config libdiscid --cflags --libs\` -o libdiscid-test</tt>
|
||||
*
|
||||
* \section Contact
|
||||
*
|
||||
* - <a href="http://lists.musicbrainz.org/mailman/listinfo/musicbrainz-devel">MusicBrainz Development Mailing List</a>
|
||||
* - <a href="http://tickets.musicbrainz.org/browse/LIB">MusicBrainz Bug Tracker</a>
|
||||
* - <a href="http://musicbrainz.org/doc/libdiscid">MusicBrainz Documentation</a>
|
||||
* - <a href="https://github.com/metabrainz/libdiscid">Github Repository</a>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A transparent handle for an Audio CD.
|
||||
*
|
||||
* This is returned by discid_new() and has to be passed as the first
|
||||
* parameter to all discid_*() functions.
|
||||
*/
|
||||
typedef void *DiscId;
|
||||
|
||||
|
||||
/**
|
||||
* Return a handle for a new DiscId object.
|
||||
*
|
||||
* If no memory could be allocated, NULL is returned. Don't use the created
|
||||
* DiscId object before calling discid_read() or discid_put().
|
||||
*
|
||||
* @return a DiscId object, or NULL.
|
||||
*/
|
||||
LIBDISCID_API DiscId *discid_new();
|
||||
|
||||
|
||||
/**
|
||||
* Release the memory allocated for the DiscId object.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
*/
|
||||
LIBDISCID_API void discid_free(DiscId *d);
|
||||
|
||||
|
||||
/**
|
||||
* Read all supported features of the disc in the given CD-ROM/DVD-ROM drive.
|
||||
*
|
||||
* This function reads the disc in the drive specified by the given device
|
||||
* identifier. If the device is NULL, the default drive, as returned by
|
||||
* discid_get_default_device() is used.
|
||||
*
|
||||
* If you do not require all features provided by libdiscid, such as MCN
|
||||
* or ISRC reading, you should consider using discid_read_sparse() instead
|
||||
* of discid_read() for performance reasons.
|
||||
*
|
||||
* On error, this function returns false and sets the error message which you
|
||||
* can access using discid_get_error_msg(). In this case, the other functions
|
||||
* won't return meaningful values and should not be used.
|
||||
*
|
||||
* This function may be used multiple times with the same DiscId object.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @param device an operating system dependent device identifier, or NULL
|
||||
* @return true if successful, or false on error.
|
||||
*/
|
||||
LIBDISCID_API int discid_read(DiscId *d, const char *device);
|
||||
|
||||
|
||||
/**
|
||||
* Read the disc in the given CD-ROM/DVD-ROM drive
|
||||
* extracting only the TOC and additionally specified features.
|
||||
*
|
||||
* This function will always read the TOC, but additional features
|
||||
* like ::DISCID_FEATURE_MCN and ::DISCID_FEATURE_ISRC can be set
|
||||
* using the features parameter.
|
||||
* Multiple features can be set using bitwise OR.
|
||||
*
|
||||
* If you only want to generate a disc ID, you only need the TOC,
|
||||
* so set features to 0:
|
||||
* \code
|
||||
* discid_read_sparse(disc, device, 0)
|
||||
* \endcode
|
||||
* This is a bit more verbose, but equivalent since ::DISCID_FEATURE_READ
|
||||
* is always implied:
|
||||
* \code
|
||||
* discid_read_sparse(disc, device, DISCID_FEATURE_READ)
|
||||
* \endcode
|
||||
*
|
||||
* If you want to read all features available, you can use discid_read().
|
||||
*
|
||||
* On error, this function returns false and sets the error message which you
|
||||
* can access using discid_get_error_msg(). In this case, the other functions
|
||||
* won't return meaningful values and should not be used.
|
||||
*
|
||||
* This function may be used multiple times with the same DiscId object.
|
||||
*
|
||||
* \since libdiscid 0.5.0
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @param device an operating system dependent device identifier, or NULL
|
||||
* @param features a list of bit flags from the enum ::discid_feature
|
||||
* @return true if successful, or false on error.
|
||||
*/
|
||||
LIBDISCID_API int discid_read_sparse(DiscId *d, const char *device,
|
||||
unsigned int features);
|
||||
|
||||
#define DISCID_HAVE_SPARSE_READ
|
||||
|
||||
/**
|
||||
* Provides the TOC of a known CD.
|
||||
*
|
||||
* This function may be used if the TOC has been read earlier and you
|
||||
* want to calculate the disc ID afterwards, without accessing the disc
|
||||
* drive. It replaces the discid_read function in this case.
|
||||
*
|
||||
* On error, this function returns false and sets the error message which you
|
||||
* can access using discid_get_error_msg(). In this case, the other functions
|
||||
* won't return meaningful values and should not be used.
|
||||
*
|
||||
* The offsets parameter points to an array which contains the track offsets
|
||||
* for each track. The first element, offsets[0], is the leadout track. It
|
||||
* must contain the total number of sectors on the disc.
|
||||
*
|
||||
* For discs with additional data tracks, the trailing data tracks
|
||||
* should be ignored. offset[0] should then be the last sector of the last
|
||||
* audio track.
|
||||
* Make sure the length of the last audio track as returned by libdiscid
|
||||
* after a put is the same as the length of your last audio track.
|
||||
* Depending on your tools you might need to substract 11400 (2:32 min.).
|
||||
* See also:
|
||||
* <a href="http://musicbrainz.org/doc/Disc_ID_Calculation">Disc ID Calculation</a>
|
||||
*
|
||||
*
|
||||
* @param d a DiscID object created by discid_new()
|
||||
* @param first the number of the first audio track on disc (usually one)
|
||||
* @param last the number of the last audio track on the disc
|
||||
* @param offsets a pointer to an array of 100 track offsets
|
||||
* @return true if the given data was valid, and false on error
|
||||
*/
|
||||
LIBDISCID_API int discid_put(DiscId *d, int first, int last, int *offsets);
|
||||
|
||||
|
||||
/**
|
||||
* Return a human-readable error message.
|
||||
*
|
||||
* This function may only be used if discid_read() failed. The returned
|
||||
* error message is only valid as long as the DiscId object exists.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return a string describing the error that occurred
|
||||
*/
|
||||
LIBDISCID_API char *discid_get_error_msg(DiscId *d);
|
||||
|
||||
|
||||
/**
|
||||
* Return a MusicBrainz DiscID.
|
||||
*
|
||||
* The returned string is only valid as long as the DiscId object exists.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return a string containing a MusicBrainz DiscID
|
||||
*/
|
||||
LIBDISCID_API char *discid_get_id(DiscId *d);
|
||||
|
||||
|
||||
/**
|
||||
* Return a FreeDB DiscID.
|
||||
*
|
||||
* The returned string is only valid as long as the DiscId object exists.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return a string containing a FreeDB DiscID
|
||||
*/
|
||||
LIBDISCID_API char *discid_get_freedb_id(DiscId *d);
|
||||
|
||||
/**
|
||||
* Return a string representing CD Table Of Contents (TOC).
|
||||
*
|
||||
* The string has following values separated by space:
|
||||
* first track number
|
||||
* last track number
|
||||
* total length in sectors
|
||||
* offset of 1st track
|
||||
* offset of 2nd track
|
||||
* ...
|
||||
*
|
||||
* Example:
|
||||
* 1 7 164900 150 22460 50197 80614 100828 133318 144712
|
||||
*
|
||||
* The returned string is only valid as long as the DiscId object exists.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return a string containing TOC information
|
||||
*/
|
||||
LIBDISCID_API char *discid_get_toc_string(DiscId *d);
|
||||
|
||||
/**
|
||||
* Return an URL for submitting the DiscID to MusicBrainz.
|
||||
*
|
||||
* The URL leads to an interactive disc submission wizard that guides the
|
||||
* user through the process of associating this disc's DiscID with a
|
||||
* release in the MusicBrainz database.
|
||||
*
|
||||
* The returned string is only valid as long as the DiscId object exists.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return a string containing an URL
|
||||
*/
|
||||
LIBDISCID_API char *discid_get_submission_url(DiscId *d);
|
||||
|
||||
/**
|
||||
* Return an URL for retrieving CD information from MusicBrainz' web service
|
||||
*
|
||||
* The URL provides the CD information in XML.
|
||||
* See http://musicbrainz.org/development/mmd for details.
|
||||
*
|
||||
* The returned string is only valid as long as the DiscId object exists.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return a string containing an URL
|
||||
*
|
||||
* @deprecated This function is deprecated. Please use libmusicbrainz instead
|
||||
* since this function returns an URL referring the deprecated webservice.
|
||||
*/
|
||||
LIBDISCID_API LIBDISCID_DEPRECATED char *discid_get_webservice_url(DiscId *d);
|
||||
|
||||
/**
|
||||
* Return the name of the default disc drive for this machine.
|
||||
* This isn't constant, but possibly depends on the drives currently
|
||||
* attached, depending on the platform.
|
||||
* For this reason you should call this once and save it
|
||||
* when you want to make sure to use the same drive for
|
||||
* multiple operations.
|
||||
*
|
||||
* The returned string is thread local and owned by libdiscid internally.
|
||||
*
|
||||
* @return a string containing an operating system dependent device identifier
|
||||
*/
|
||||
LIBDISCID_API char *discid_get_default_device(void);
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of the first track on this disc.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return the number of the first track
|
||||
*/
|
||||
LIBDISCID_API int discid_get_first_track_num(DiscId *d);
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of the last audio track on this disc.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return the number of the last track
|
||||
*/
|
||||
LIBDISCID_API int discid_get_last_track_num(DiscId *d);
|
||||
|
||||
|
||||
/**
|
||||
* Return the length of the disc in sectors.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return the length of the disc in sectors
|
||||
*/
|
||||
LIBDISCID_API int discid_get_sectors(DiscId *d);
|
||||
|
||||
|
||||
/**
|
||||
* Return the sector offset of a track.
|
||||
*
|
||||
* Only track numbers between (and including) discid_get_first_track_num()
|
||||
* and discid_get_last_track_num() may be used.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @param track_num the number of a track
|
||||
* @return sector offset of the specified track
|
||||
*/
|
||||
LIBDISCID_API int discid_get_track_offset(DiscId *d, int track_num);
|
||||
|
||||
|
||||
/**
|
||||
* Return the length of a track in sectors.
|
||||
*
|
||||
* Only track numbers between (and including) discid_get_first_track_num()
|
||||
* and discid_get_last_track_num() may be used.
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @param track_num the number of a track
|
||||
* @return length of the specified track
|
||||
*/
|
||||
LIBDISCID_API int discid_get_track_length(DiscId *d, int track_num);
|
||||
|
||||
/**
|
||||
* Return the Media Catalogue Number (MCN) for the disc.
|
||||
*
|
||||
* This is essentially an EAN (= UPC with 0 prefix).
|
||||
*
|
||||
* \since libdiscid 0.3.0
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @return a string containing an Media Catalogue Number of the disk
|
||||
*/
|
||||
LIBDISCID_API char* discid_get_mcn(DiscId *d);
|
||||
|
||||
/**
|
||||
* Return the ISRC for a track.
|
||||
*
|
||||
* Only track numbers between (and including) discid_get_first_track_num()
|
||||
* and discid_get_last_track_num() may be used.
|
||||
*
|
||||
* \since libdiscid 0.3.0
|
||||
*
|
||||
* @param d a DiscId object created by discid_new()
|
||||
* @param track_num the number of a track
|
||||
* @return a string containing an ISRC for the specified track
|
||||
*/
|
||||
LIBDISCID_API char* discid_get_track_isrc(DiscId *d, int track_num);
|
||||
|
||||
|
||||
/**
|
||||
* PLATFORM-DEPENDENT FEATURES
|
||||
*
|
||||
* The platform dependent features are currently:
|
||||
* - "read" read TOC from disc
|
||||
* - "mcn" read MCN from disc
|
||||
* - "isrc" read ISRC from disc
|
||||
*
|
||||
* A table in the
|
||||
* <a href="http://musicbrainz.org/doc/libdiscid">MusicBrainz Documentation</a>
|
||||
* specifies which features are available on which platform in what version.
|
||||
*
|
||||
* In the code you can use discid_get_feature_list() or discid_has_feature()
|
||||
* below to get the features for your platform in this version.
|
||||
*/
|
||||
|
||||
enum discid_feature {
|
||||
DISCID_FEATURE_READ = 1 << 0,
|
||||
DISCID_FEATURE_MCN = 1 << 1,
|
||||
DISCID_FEATURE_ISRC = 1 << 2,
|
||||
};
|
||||
/**
|
||||
* Check if a certain feature is implemented on the current platform.
|
||||
*
|
||||
* This only works for single features, not bit masks with multiple features.
|
||||
*
|
||||
* \since libdiscid 0.4.0
|
||||
*
|
||||
* @param feature as enum ::discid_feature
|
||||
* @return 1 if the feature is implemented and 0 if not.
|
||||
*/
|
||||
LIBDISCID_API int discid_has_feature(enum discid_feature feature);
|
||||
|
||||
#define DISCID_FEATURE_STR_READ "read"
|
||||
#define DISCID_FEATURE_STR_MCN "mcn"
|
||||
#define DISCID_FEATURE_STR_ISRC "isrc"
|
||||
#define DISCID_FEATURE_LENGTH 32
|
||||
/**
|
||||
* Return a list of features supported by the current platform.
|
||||
* The array of length ::DISCID_FEATURE_LENGTH should be allocated by the user.
|
||||
* After the call each element of the array is either NULL
|
||||
* or a pointer to a static string.
|
||||
*
|
||||
* \since libdiscid 0.4.0
|
||||
*
|
||||
* @param[out] features a static string array of length ::DISCID_FEATURE_LENGTH
|
||||
*/
|
||||
LIBDISCID_API void discid_get_feature_list(
|
||||
char *features[DISCID_FEATURE_LENGTH]);
|
||||
|
||||
/**
|
||||
* Return the full version string of this library, including the name.
|
||||
* This can be used for debug output.
|
||||
* Don't use this to test for features, see discid_has_feature().
|
||||
*
|
||||
* \since libdiscid 0.4.0
|
||||
*
|
||||
* @return a string containing the version of libdiscid.
|
||||
*/
|
||||
LIBDISCID_API char *discid_get_version_string(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MUSICBRAINZ_DISC_ID_H */
|
@@ -1,139 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2006 Matthias Friedrich
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
$Id$
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
/*
|
||||
* For internal use only. This header file is not installed.
|
||||
*/
|
||||
#ifndef MUSICBRAINZ_DISC_ID_PRIVATE_H
|
||||
#define MUSICBRAINZ_DISC_ID_PRIVATE_H
|
||||
|
||||
#include "discid/discid.h"
|
||||
|
||||
/* Length of toc string, "xxx+xxx" + 100 tracks 7 bytes each ("+xxxxxx")
|
||||
* The highest possible offset is 90 minutes * 60 seconds/minute * 75 frames/second = 405000.
|
||||
* That is 6 digits plus one plus sign = 7 characters per track.
|
||||
* So 3 + 3 (first and last) + 100*7 (disc length plus 99 tracks) = 706
|
||||
*/
|
||||
#define MB_TOC_STRING_LENGTH (3 + 3 + 100*7)
|
||||
|
||||
/* Length of a MusicBrainz DiscID in bytes (without a trailing '\0'-byte). */
|
||||
#define MB_DISC_ID_LENGTH 32
|
||||
|
||||
/* Length of a FreeDB DiscID in bytes (without a trailing '\0'-byte). */
|
||||
#define FREEDB_DISC_ID_LENGTH 8
|
||||
|
||||
/* The maximum permitted length for an error message (without the '\0'-byte). */
|
||||
#define MB_ERROR_MSG_LENGTH 255
|
||||
|
||||
/* Length of url prefixes */
|
||||
#define MB_URL_PREFIX_LENGTH 300
|
||||
|
||||
/* Maximum length of any url (including query string) */
|
||||
#define MB_MAX_URL_LENGTH (MB_URL_PREFIX_LENGTH + MB_DISC_ID_LENGTH + MB_TOC_STRING_LENGTH)
|
||||
|
||||
/* The URL that can be used for submitting DiscIDs (no parameters yet) */
|
||||
#define MB_SUBMISSION_URL "http://musicbrainz.org/cdtoc/attach"
|
||||
|
||||
/* The URL that can be used for retrieving XML for a CD */
|
||||
#define MB_WEBSERVICE_URL "http://musicbrainz.org/ws/1/release"
|
||||
|
||||
/* Maximum length of a Media Catalogue Number string */
|
||||
#define MCN_STR_LENGTH 13
|
||||
|
||||
/* Maximum length of a ISRC code string */
|
||||
#define ISRC_STR_LENGTH 12
|
||||
|
||||
/* Maximum disc length in frames/sectors
|
||||
* This is already not according to spec, but many players might still work
|
||||
* Spec is 79:59.75 = 360000 + lead-in + lead-out */
|
||||
#define MAX_DISC_LENGTH (90 * 60 * 75)
|
||||
|
||||
/*
|
||||
* This data structure represents an audio disc.
|
||||
*
|
||||
* We use fixed length strings here because that way the user doesn't have to
|
||||
* check for memory exhaustion conditions. As soon as the mb_disc object has
|
||||
* been created, all calls returning strings will be successful.
|
||||
*/
|
||||
typedef struct {
|
||||
int first_track_num;
|
||||
int last_track_num;
|
||||
int track_offsets[100];
|
||||
char id[MB_DISC_ID_LENGTH+1];
|
||||
char freedb_id[FREEDB_DISC_ID_LENGTH+1];
|
||||
char submission_url[MB_MAX_URL_LENGTH+1];
|
||||
char webservice_url[MB_MAX_URL_LENGTH+1];
|
||||
char toc_string[MB_TOC_STRING_LENGTH+1];
|
||||
char error_msg[MB_ERROR_MSG_LENGTH+1];
|
||||
char isrc[100][ISRC_STR_LENGTH+1];
|
||||
char mcn[MCN_STR_LENGTH+1];
|
||||
int success;
|
||||
} mb_disc_private;
|
||||
|
||||
typedef struct {
|
||||
int control;
|
||||
int address;
|
||||
} mb_disc_toc_track;
|
||||
|
||||
typedef struct {
|
||||
int first_track_num;
|
||||
int last_track_num;
|
||||
mb_disc_toc_track tracks[100];
|
||||
} mb_disc_toc;
|
||||
|
||||
/*
|
||||
* This function has to be implemented once per operating system.
|
||||
*
|
||||
* The caller guarantees that both the disc and device parameters are
|
||||
* not NULL.
|
||||
*
|
||||
* Implementors have to set mb_disc_private's first_track_num, last_track_num,
|
||||
* and track_offsets attributes. If there is an error, the error_msg attribute
|
||||
* has to be set to a human-readable error message.
|
||||
*
|
||||
* On error, 0 is returned. On success, 1 is returned.
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_read_unportable(mb_disc_private *disc, const char *device, unsigned int features);
|
||||
|
||||
|
||||
/*
|
||||
* This should return the name of the default/preferred CDROM/DVD device
|
||||
* on this operating system. It has to be in a format usable for the second
|
||||
* parameter of mb_disc_read_unportable().
|
||||
*/
|
||||
LIBDISCID_INTERNAL char *mb_disc_get_default_device_unportable(void);
|
||||
|
||||
/*
|
||||
* This should return 1 if the feature is supported by the platform
|
||||
* and 0 if not.
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_has_feature_unportable(enum discid_feature feature);
|
||||
|
||||
/*
|
||||
* Load data to the mb_disc_private structure based on mb_disc_toc.
|
||||
*
|
||||
* On error, 0 is returned. On success, 1 is returned.
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_load_toc(mb_disc_private *disc, mb_disc_toc *toc);
|
||||
|
||||
#endif /* MUSICBRAINZ_DISC_ID_PRIVATE_H */
|
@@ -1,110 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2000 Robert Kaye
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
$Id$
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Program: RFC-822 routines (originally from SMTP)
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 27 July 1988
|
||||
* Last Edited: 10 September 1998
|
||||
*
|
||||
* Sponsorship: The original version of this work was developed in the
|
||||
* Symbolic Systems Resources Group of the Knowledge Systems
|
||||
* Laboratory at Stanford University in 1987-88, and was funded
|
||||
* by the Biomedical Research Technology Program of the National
|
||||
* Institutes of Health under grant number RR-00785.
|
||||
*
|
||||
* Original version Copyright 1988 by The Leland Stanford Junior University
|
||||
* Copyright 1998 by the University of Washington
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notices appear in all copies and that both the
|
||||
* above copyright notices and this permission notice appear in supporting
|
||||
* documentation, and that the name of the University of Washington or The
|
||||
* Leland Stanford Junior University not be used in advertising or publicity
|
||||
* pertaining to distribution of the software without specific, written prior
|
||||
* permission. This software is made available "as is", and
|
||||
* THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
|
||||
* DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
|
||||
* WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include "base64.h"
|
||||
|
||||
/* NOTE: This is not true RFC822 anymore. The use of the characters
|
||||
'/', '+', and '=' is no bueno when the ID will be used as part of a URL.
|
||||
'_', '.', and '-' have been used instead
|
||||
*/
|
||||
|
||||
/* Convert binary contents to BASE64
|
||||
* Accepts: source
|
||||
* length of source
|
||||
* pointer to return destination length
|
||||
* Returns: destination as BASE64
|
||||
*/
|
||||
|
||||
unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len)
|
||||
{
|
||||
unsigned char *ret,*d;
|
||||
unsigned char *s = (unsigned char *) src;
|
||||
char *v = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
|
||||
unsigned long i = ((srcl + 2) / 3) * 4;
|
||||
*len = i += 2 * ((i / 60) + 1);
|
||||
d = ret = (unsigned char *) malloc ((size_t) ++i);
|
||||
for (i = 0; srcl; s += 3) { /* process tuplets */
|
||||
*d++ = v[s[0] >> 2]; /* byte 1: high 6 bits (1) */
|
||||
/* byte 2: low 2 bits (1), high 4 bits (2) */
|
||||
*d++ = v[((s[0] << 4) + (--srcl ? (s[1] >> 4) : 0)) & 0x3f];
|
||||
/* byte 3: low 4 bits (2), high 2 bits (3) */
|
||||
*d++ = srcl ? v[((s[1] << 2) + (--srcl ? (s[2] >> 6) : 0)) & 0x3f] : '-';
|
||||
/* byte 4: low 6 bits (3) */
|
||||
*d++ = srcl ? v[s[2] & 0x3f] : '-';
|
||||
if (srcl) srcl--; /* count third character if processed */
|
||||
if ((++i) == 15) { /* output 60 characters? */
|
||||
i = 0; /* restart line break count, insert CRLF */
|
||||
*d++ = '\015'; *d++ = '\012';
|
||||
}
|
||||
}
|
||||
*d = '\0'; /* tie off string */
|
||||
|
||||
return ret; /* return the resulting string */
|
||||
}
|
@@ -1,74 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2000 Robert Kaye
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
$Id$
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Program: RFC-822 routines (originally from SMTP)
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 27 July 1988
|
||||
* Last Edited: 10 September 1998
|
||||
*
|
||||
* Sponsorship: The original version of this work was developed in the
|
||||
* Symbolic Systems Resources Group of the Knowledge Systems
|
||||
* Laboratory at Stanford University in 1987-88, and was funded
|
||||
* by the Biomedical Research Technology Program of the National
|
||||
* Institutes of Health under grant number RR-00785.
|
||||
*
|
||||
* Original version Copyright 1988 by The Leland Stanford Junior University
|
||||
* Copyright 1998 by the University of Washington
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notices appear in all copies and that both the
|
||||
* above copyright notices and this permission notice appear in supporting
|
||||
* documentation, and that the name of the University of Washington or The
|
||||
* Leland Stanford Junior University not be used in advertising or publicity
|
||||
* pertaining to distribution of the software without specific, written prior
|
||||
* permission. This software is made available "as is", and
|
||||
* THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
|
||||
* DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
|
||||
* WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
#include "discid/discid.h" /* for LIBDISCID_INTERNAL */
|
||||
|
||||
LIBDISCID_INTERNAL unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len);
|
||||
|
||||
#endif
|
@@ -1,508 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2006 Matthias Friedrich
|
||||
Copyright (C) 2000 Robert Kaye
|
||||
Copyright (C) 1999 Marc E E van Woerkom
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "sha1.h"
|
||||
#include "base64.h"
|
||||
|
||||
#include "discid/discid.h"
|
||||
#include "discid/discid_private.h"
|
||||
|
||||
|
||||
#define TRACK_NUM_IS_VALID(disc, i) \
|
||||
( i >= disc->first_track_num && i <= disc->last_track_num )
|
||||
|
||||
|
||||
static void create_disc_id(mb_disc_private *d, char buf[]);
|
||||
static void create_freedb_disc_id(mb_disc_private *d, char buf[]);
|
||||
static char *create_toc_string(mb_disc_private *d, char *sep);
|
||||
static void create_submission_url(mb_disc_private *d, char buf[]);
|
||||
static void create_webservice_url(mb_disc_private *d, char buf[]);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Implementation of the public interface.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DiscId *discid_new() {
|
||||
/* initializes everything to zero */
|
||||
return calloc(1, sizeof(mb_disc_private));
|
||||
}
|
||||
|
||||
|
||||
void discid_free(DiscId *d) {
|
||||
free(d);
|
||||
}
|
||||
|
||||
|
||||
char *discid_get_error_msg(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
|
||||
return disc->error_msg;
|
||||
}
|
||||
|
||||
|
||||
char *discid_get_id(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return NULL;
|
||||
|
||||
if (strlen(disc->id) == 0)
|
||||
create_disc_id(disc, disc->id);
|
||||
|
||||
return disc->id;
|
||||
}
|
||||
|
||||
|
||||
char *discid_get_freedb_id(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return NULL;
|
||||
|
||||
if (strlen(disc->freedb_id) == 0)
|
||||
create_freedb_disc_id(disc, disc->freedb_id);
|
||||
|
||||
return disc->freedb_id;
|
||||
}
|
||||
|
||||
char *discid_get_toc_string(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert( disc != NULL );
|
||||
assert( disc->success );
|
||||
|
||||
if ( ! disc->success )
|
||||
return NULL;
|
||||
|
||||
if ( strlen(disc->toc_string) == 0 ) {
|
||||
char *toc = create_toc_string(disc, " ");
|
||||
if (toc) {
|
||||
memcpy(disc->toc_string, toc, strlen(toc) + 1);
|
||||
free(toc);
|
||||
}
|
||||
}
|
||||
|
||||
return disc->toc_string;
|
||||
}
|
||||
|
||||
char *discid_get_submission_url(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return NULL;
|
||||
|
||||
if (strlen(disc->submission_url) == 0)
|
||||
create_submission_url(disc, disc->submission_url);
|
||||
|
||||
return disc->submission_url;
|
||||
}
|
||||
|
||||
char *discid_get_webservice_url(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return NULL;
|
||||
|
||||
if (strlen(disc->webservice_url) == 0)
|
||||
create_webservice_url(disc, disc->webservice_url);
|
||||
|
||||
return disc->webservice_url;
|
||||
}
|
||||
|
||||
int discid_read(DiscId *d, const char *device) {
|
||||
return discid_read_sparse(d, device, UINT_MAX);
|
||||
}
|
||||
|
||||
int discid_read_sparse(DiscId *d, const char *device, unsigned int features) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
|
||||
if (device == NULL)
|
||||
device = discid_get_default_device();
|
||||
|
||||
assert(device != NULL);
|
||||
|
||||
/* Necessary, because the disc handle could have been used before. */
|
||||
memset(disc, 0, sizeof(mb_disc_private));
|
||||
|
||||
/* pre-read the TOC to reduce "not-ready" problems
|
||||
* See LIB-44 (issues with multi-session discs)
|
||||
*/
|
||||
if (!mb_disc_read_unportable(disc, device, DISCID_FEATURE_READ)) {
|
||||
return 0;
|
||||
}
|
||||
memset(disc, 0, sizeof(mb_disc_private));
|
||||
|
||||
return disc->success = mb_disc_read_unportable(disc, device, features);
|
||||
}
|
||||
|
||||
int discid_put(DiscId *d, int first, int last, int *offsets) {
|
||||
int i, disc_length;
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
|
||||
/* Necessary, because the disc handle could have been used before. */
|
||||
memset(disc, 0, sizeof(mb_disc_private));
|
||||
|
||||
/* extensive checking of given parameters */
|
||||
if (first > last || first < 1
|
||||
|| first > 99 || last < 1 || last > 99) {
|
||||
|
||||
sprintf(disc->error_msg, "Illegal track limits");
|
||||
return 0;
|
||||
}
|
||||
if (offsets == NULL) {
|
||||
sprintf(disc->error_msg, "No offsets given");
|
||||
return 0;
|
||||
}
|
||||
disc_length = offsets[0];
|
||||
if (disc_length > MAX_DISC_LENGTH) {
|
||||
sprintf(disc->error_msg, "Disc too long");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i <= last; i++) {
|
||||
if (offsets[i] > disc_length) {
|
||||
sprintf(disc->error_msg, "Invalid offset");
|
||||
return 0;
|
||||
}
|
||||
if (i > 1 && offsets[i-1] > offsets[i]) {
|
||||
sprintf(disc->error_msg, "Invalid order");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
disc->first_track_num = first;
|
||||
disc->last_track_num = last;
|
||||
|
||||
memcpy(disc->track_offsets, offsets, sizeof(int) * (last+1));
|
||||
|
||||
disc->success = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char *discid_get_default_device(void) {
|
||||
return mb_disc_get_default_device_unportable();
|
||||
}
|
||||
|
||||
int discid_get_first_track_num(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return -1;
|
||||
else
|
||||
return disc->first_track_num;
|
||||
}
|
||||
|
||||
|
||||
int discid_get_last_track_num(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return -1;
|
||||
else
|
||||
return disc->last_track_num;
|
||||
}
|
||||
|
||||
|
||||
int discid_get_sectors(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return -1;
|
||||
else
|
||||
return disc->track_offsets[0];
|
||||
}
|
||||
|
||||
|
||||
int discid_get_track_offset(DiscId *d, int i) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
assert(TRACK_NUM_IS_VALID(disc, i));
|
||||
|
||||
if (!disc->success || !TRACK_NUM_IS_VALID(disc, i))
|
||||
return -1;
|
||||
else
|
||||
return disc->track_offsets[i];
|
||||
}
|
||||
|
||||
|
||||
int discid_get_track_length(DiscId *d, int i) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
assert(TRACK_NUM_IS_VALID(disc, i));
|
||||
|
||||
if (!disc->success || !TRACK_NUM_IS_VALID(disc, i))
|
||||
return -1;
|
||||
else if (i < disc->last_track_num)
|
||||
return disc->track_offsets[i+1] - disc->track_offsets[i];
|
||||
else
|
||||
return disc->track_offsets[0] - disc->track_offsets[i];
|
||||
}
|
||||
|
||||
char *discid_get_mcn(DiscId *d) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
|
||||
if (!disc->success)
|
||||
return NULL;
|
||||
else
|
||||
return disc->mcn;
|
||||
}
|
||||
|
||||
char* discid_get_track_isrc(DiscId *d, int i) {
|
||||
mb_disc_private *disc = (mb_disc_private *) d;
|
||||
assert(disc != NULL);
|
||||
assert(disc->success);
|
||||
assert(TRACK_NUM_IS_VALID(disc, i));
|
||||
|
||||
if (!disc->success || i == 0 || !TRACK_NUM_IS_VALID(disc, i))
|
||||
return NULL;
|
||||
else
|
||||
return disc->isrc[i];
|
||||
}
|
||||
|
||||
int discid_has_feature(enum discid_feature feature) {
|
||||
return mb_disc_has_feature_unportable(feature);
|
||||
}
|
||||
|
||||
void discid_get_feature_list(char *features[DISCID_FEATURE_LENGTH]) {
|
||||
int i;
|
||||
|
||||
/* for the code, the parameter is actually only a pointer */
|
||||
memset(features, 0, sizeof(char *) * DISCID_FEATURE_LENGTH);
|
||||
i = 0;
|
||||
|
||||
if (discid_has_feature(DISCID_FEATURE_READ)) {
|
||||
features[i++] = DISCID_FEATURE_STR_READ;
|
||||
}
|
||||
if (discid_has_feature(DISCID_FEATURE_MCN)) {
|
||||
features[i++] = DISCID_FEATURE_STR_MCN;
|
||||
}
|
||||
if (discid_has_feature(DISCID_FEATURE_ISRC)) {
|
||||
features[i++] = DISCID_FEATURE_STR_ISRC;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char *discid_get_version_string(void) {
|
||||
#ifdef HAVE_CONFIG_H
|
||||
return PACKAGE_STRING;
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Private utilities, not exported.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a DiscID based on the TOC data found in the DiscId object.
|
||||
* The DiscID is placed in the provided string buffer.
|
||||
*/
|
||||
static void create_disc_id(mb_disc_private *d, char buf[]) {
|
||||
SHA_INFO sha;
|
||||
unsigned char digest[20], *base64;
|
||||
unsigned long size;
|
||||
char tmp[17]; /* for 8 hex digits (16 to avoid trouble) */
|
||||
int i;
|
||||
|
||||
assert(d != NULL);
|
||||
assert(d->success);
|
||||
|
||||
sha_init(&sha);
|
||||
|
||||
sprintf(tmp, "%02X", d->first_track_num);
|
||||
sha_update(&sha, (unsigned char *) tmp, strlen(tmp));
|
||||
|
||||
sprintf(tmp, "%02X", d->last_track_num);
|
||||
sha_update(&sha, (unsigned char *) tmp, strlen(tmp));
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
sprintf(tmp, "%08X", d->track_offsets[i]);
|
||||
sha_update(&sha, (unsigned char *) tmp, strlen(tmp));
|
||||
}
|
||||
|
||||
sha_final(digest, &sha);
|
||||
|
||||
base64 = rfc822_binary(digest, sizeof(digest), &size);
|
||||
|
||||
memcpy(buf, base64, size);
|
||||
buf[size] = '\0';
|
||||
|
||||
free(base64);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a FreeDB DiscID based on the TOC data found in the DiscId object.
|
||||
* The DiscID is placed in the provided string buffer.
|
||||
*/
|
||||
static void create_freedb_disc_id(mb_disc_private *d, char buf[]) {
|
||||
int i, n, m, t;
|
||||
|
||||
assert(d != NULL);
|
||||
assert(d->success);
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < d->last_track_num; i++) {
|
||||
m = d->track_offsets[i + 1] / 75;
|
||||
while (m > 0) {
|
||||
n += m % 10;
|
||||
m /= 10;
|
||||
}
|
||||
}
|
||||
t = d->track_offsets[0] / 75 - d->track_offsets[1] / 75;
|
||||
sprintf(buf, "%08x", ((n % 0xff) << 24 | t << 8 | d->last_track_num));
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a string based on the TOC data found in the mb_disc_private
|
||||
* object. The returned string is allocated, caller has to free() it.
|
||||
* On failure, it returns NULL.
|
||||
*
|
||||
* Format is:
|
||||
* [1st track num][sep][last track num][sep][length in sectors][sep][1st track offset][sep]...
|
||||
*/
|
||||
static char *create_toc_string(mb_disc_private *d, char *sep) {
|
||||
char tmp[16];
|
||||
char *toc;
|
||||
int i, size;
|
||||
|
||||
assert( d != NULL );
|
||||
|
||||
/* number of tracks */
|
||||
size = 1 + d->last_track_num - d->first_track_num;
|
||||
/* first&last track num and total length */
|
||||
size += 3;
|
||||
/* number + separator */
|
||||
size *= (6 + strlen(sep));
|
||||
/* nul */
|
||||
size++;
|
||||
|
||||
toc = calloc(size, sizeof(char));
|
||||
if (!toc) return NULL;
|
||||
|
||||
sprintf(toc, "%d%s%d%s%d",
|
||||
d->first_track_num,
|
||||
sep,
|
||||
d->last_track_num,
|
||||
sep,
|
||||
d->track_offsets[0]);
|
||||
|
||||
for (i = d->first_track_num; i <= d->last_track_num; i++) {
|
||||
sprintf(tmp, "%s%d", sep, d->track_offsets[i]);
|
||||
strcat(toc, tmp);
|
||||
}
|
||||
|
||||
return toc;
|
||||
}
|
||||
|
||||
/* Append &toc=... to buf, calling create_toc_string() */
|
||||
static void cat_toc_param(mb_disc_private *d, char *buf) {
|
||||
char *toc = create_toc_string(d, "+");
|
||||
if (toc) {
|
||||
strcat(buf, "&toc=");
|
||||
strcat(buf, toc);
|
||||
free(toc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a submission URL based on the TOC data found in the mb_disc_private
|
||||
* object. The URL is placed in the provided string buffer.
|
||||
*/
|
||||
static void create_submission_url(mb_disc_private *d, char buf[]) {
|
||||
char tmp[16];
|
||||
|
||||
assert(d != NULL);
|
||||
assert(d->success);
|
||||
|
||||
strcpy(buf, MB_SUBMISSION_URL);
|
||||
|
||||
strcat(buf, "?id=");
|
||||
strcat(buf, discid_get_id((DiscId *) d));
|
||||
|
||||
sprintf(tmp, "&tracks=%d", d->last_track_num);
|
||||
strcat(buf, tmp);
|
||||
|
||||
cat_toc_param(d, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a web service URL based on the TOC data found in the mb_disc_private
|
||||
* object. The URL is placed in the provided string buffer.
|
||||
*/
|
||||
static void create_webservice_url(mb_disc_private *d, char buf[]) {
|
||||
assert(d != NULL);
|
||||
assert(d->success);
|
||||
|
||||
strcpy(buf, MB_WEBSERVICE_URL);
|
||||
|
||||
strcat(buf, "?type=xml&discid=");
|
||||
strcat(buf, discid_get_id((DiscId *) d));
|
||||
|
||||
cat_toc_param(d, buf);
|
||||
}
|
||||
|
||||
/* EOF */
|
@@ -1,194 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2008 Patrick Hurrelmann
|
||||
Copyright (C) 2006 Matthias Friedrich
|
||||
Copyright (C) 2000 Robert Kaye
|
||||
Copyright (C) 1999 Marc E E van Woerkom
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <netinet/in.h> /* for ntohl() */
|
||||
#else
|
||||
#include <util.h> /* for getrawpartition() */
|
||||
#endif
|
||||
|
||||
#include "discid/discid_private.h"
|
||||
#include "unix.h"
|
||||
|
||||
#define MAX_DEV_LEN 15
|
||||
|
||||
static int get_device(int n, char* device_name, size_t device_name_length) {
|
||||
#if !defined(__FreeBSD__) /* /dev/rcdNX, where X is the letter for the raw partition */
|
||||
snprintf(device_name, device_name_length, "/dev/rcd%d%c", n - 1, 'a' + getrawpartition());
|
||||
#else /* on FreeBSD it's just /dev/cdN */
|
||||
snprintf(device_name, device_name_length, "/dev/cd%d", n - 1);
|
||||
#endif
|
||||
return mb_disc_unix_exists(device_name);
|
||||
}
|
||||
|
||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) {
|
||||
struct ioc_toc_header th;
|
||||
struct cd_toc_entry te[100];
|
||||
struct ioc_read_toc_entry rte;
|
||||
int i;
|
||||
|
||||
memset(&th, 0, sizeof th);
|
||||
if (ioctl(fd, CDIOREADTOCHEADER, &th) < 0)
|
||||
return 0; /* error */
|
||||
|
||||
toc->first_track_num = th.starting_track;
|
||||
toc->last_track_num = th.ending_track;
|
||||
|
||||
if (toc->last_track_num == 0)
|
||||
return 1; /* no entries to read */
|
||||
|
||||
/* Read all the TOC entries in one icotl() call */
|
||||
|
||||
memset(&te, 0, sizeof te);
|
||||
memset(&rte, 0, sizeof rte);
|
||||
rte.address_format = CD_LBA_FORMAT;
|
||||
rte.data = &te[0];
|
||||
rte.data_len = sizeof te;
|
||||
rte.starting_track = toc->first_track_num;
|
||||
|
||||
if (ioctl(fd, CDIOREADTOCENTRYS, &rte) < 0)
|
||||
return 0; /* error */
|
||||
|
||||
for (i = toc->first_track_num; i <= toc->last_track_num; ++i) {
|
||||
assert(te[i - toc->first_track_num].track == i);
|
||||
#if defined(__FreeBSD__) /* LBA address is in network byte order */
|
||||
toc->tracks[i].address = ntohl(te[i - toc->first_track_num].addr.lba);
|
||||
#else
|
||||
toc->tracks[i].address = te[i - toc->first_track_num].addr.lba;
|
||||
#endif
|
||||
toc->tracks[i].control = te[i - toc->first_track_num].control;
|
||||
}
|
||||
/* leadout - track number 170 (0xAA) */
|
||||
assert(te[i - toc->first_track_num].track == 0xAA);
|
||||
#if defined(__FreeBSD__) /* LBA address is in network byte order */
|
||||
toc->tracks[0].address = ntohl(te[i - toc->first_track_num].addr.lba);
|
||||
#else
|
||||
toc->tracks[0].address = te[i - toc->first_track_num].addr.lba;
|
||||
#endif
|
||||
toc->tracks[0].control = te[i - toc->first_track_num].control;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) {
|
||||
/* All TOC entries were already read by mb_disc_unix_read_toc_header() */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) {
|
||||
struct cd_sub_channel_info sci;
|
||||
struct ioc_read_subchannel rsc;
|
||||
|
||||
memset(&sci, 0, sizeof sci);
|
||||
memset(&rsc, 0, sizeof rsc);
|
||||
rsc.address_format = CD_LBA_FORMAT; /* not technically relevant */
|
||||
rsc.data_format = CD_MEDIA_CATALOG;
|
||||
rsc.data_len = sizeof sci;
|
||||
rsc.data = &sci;
|
||||
|
||||
if ( ioctl(fd, CDIOCREADSUBCHANNEL, &rsc) < 0 )
|
||||
perror ("Warning: Unable to read the disc's media catalog number");
|
||||
else {
|
||||
if (sci.what.media_catalog.mc_valid)
|
||||
strncpy( disc->mcn,
|
||||
(const char *) sci.what.media_catalog.mc_number,
|
||||
MCN_STR_LENGTH );
|
||||
else
|
||||
memset( disc->mcn, 0, MCN_STR_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) {
|
||||
struct cd_sub_channel_info sci;
|
||||
struct ioc_read_subchannel rsc;
|
||||
|
||||
memset(&sci, 0, sizeof sci);
|
||||
memset(&rsc, 0, sizeof rsc);
|
||||
rsc.address_format = CD_LBA_FORMAT; /* not technically relevant */
|
||||
rsc.data_format = CD_TRACK_INFO;
|
||||
rsc.track = track_num;
|
||||
rsc.data_len = sizeof sci;
|
||||
rsc.data = &sci;
|
||||
|
||||
if ( ioctl(fd, CDIOCREADSUBCHANNEL, &rsc) < 0 )
|
||||
perror ("Warning: Unable to read track info (ISRC)");
|
||||
else {
|
||||
if (sci.what.track_info.ti_valid)
|
||||
strncpy( disc->isrc[track_num],
|
||||
(const char *) sci.what.track_info.ti_number,
|
||||
ISRC_STR_LENGTH );
|
||||
else
|
||||
memset( disc->isrc[track_num], 0, ISRC_STR_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
||||
switch(feature) {
|
||||
case DISCID_FEATURE_READ:
|
||||
case DISCID_FEATURE_MCN:
|
||||
case DISCID_FEATURE_ISRC:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
||||
unsigned int features) {
|
||||
char device_name[MAX_DEV_LEN] = "";
|
||||
int device_number;
|
||||
|
||||
device_number = (int) strtol(device, NULL, 10);
|
||||
|
||||
if (device_number > 0) {
|
||||
if(!get_device(device_number, device_name, MAX_DEV_LEN)) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot find cd device with the number '%d'",
|
||||
device_number);
|
||||
return 0; /* error */
|
||||
}
|
||||
device = device_name;
|
||||
}
|
||||
|
||||
return mb_disc_unix_read(disc, device, features);
|
||||
}
|
||||
|
||||
char *mb_disc_get_default_device_unportable(void) {
|
||||
static char result[MAX_DEV_LEN + 1];
|
||||
/* No error check here, so we always return the appropriate device for cd0 */
|
||||
get_device(1, result, sizeof result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* EOF */
|
@@ -1,242 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2013 Johannes Dewender
|
||||
Copyright (C) 2006 Robert Kaye
|
||||
Copyright (C) 1999 Marc E E van Woerkom
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <paths.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOBSD.h>
|
||||
#include <IOKit/storage/IOCDBlockStorageDevice.h>
|
||||
#include <IOKit/storage/IOCDMediaBSDClient.h>
|
||||
|
||||
#include "discid/discid.h"
|
||||
#include "discid/discid_private.h"
|
||||
#include "unix.h"
|
||||
|
||||
#define MB_DEFAULT_DEVICE "1" /* first disc drive (empty or not) */
|
||||
#define TOC_BUFFER_LEN 2048
|
||||
|
||||
|
||||
static int find_cd_block_devices(io_iterator_t *device_iterator)
|
||||
{
|
||||
mach_port_t master_port;
|
||||
CFMutableDictionaryRef matching_dictionary;
|
||||
|
||||
if (IOMasterPort(MACH_PORT_NULL, &master_port) != KERN_SUCCESS)
|
||||
return 0;
|
||||
|
||||
matching_dictionary = IOServiceMatching(kIOCDBlockStorageDeviceClass);
|
||||
|
||||
if (IOServiceGetMatchingServices(master_port, matching_dictionary,
|
||||
device_iterator) != KERN_SUCCESS)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_device_from_entry(io_registry_entry_t entry,
|
||||
char *device_path, int max_len)
|
||||
{
|
||||
int return_value = 0;
|
||||
size_t dev_path_len;;
|
||||
CFStringRef cf_device_name;;
|
||||
*device_path = '\0';
|
||||
|
||||
cf_device_name = IORegistryEntrySearchCFProperty(entry,
|
||||
kIOServicePlane, CFSTR(kIOBSDNameKey),
|
||||
kCFAllocatorDefault, kIORegistryIterateRecursively);
|
||||
|
||||
if (cf_device_name) {
|
||||
strcpy(device_path, _PATH_DEV);
|
||||
/* Add "r" before the device name to use the raw disk node
|
||||
* without the buffering cache. */
|
||||
strcat(device_path, "r");
|
||||
dev_path_len = strlen(device_path);
|
||||
if (CFStringGetCString(cf_device_name,
|
||||
device_path + dev_path_len,
|
||||
max_len - dev_path_len - 1,
|
||||
kCFStringEncodingASCII))
|
||||
return_value = 1;
|
||||
|
||||
CFRelease(cf_device_name);
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static int get_device_from_number(int device_number,
|
||||
char * buffer, int buffer_len) {
|
||||
int return_value = 0;
|
||||
int index = 0;
|
||||
io_iterator_t device_iterator;
|
||||
io_object_t device_object = IO_OBJECT_NULL;
|
||||
|
||||
if (!find_cd_block_devices(&device_iterator))
|
||||
return 0;
|
||||
|
||||
while (index < device_number
|
||||
&& (device_object = IOIteratorNext(device_iterator)))
|
||||
index++;
|
||||
|
||||
if (index != device_number) {
|
||||
return_value = 0;
|
||||
} else {
|
||||
return_value = get_device_from_entry(device_object,
|
||||
buffer, buffer_len);
|
||||
}
|
||||
|
||||
IOObjectRelease(device_object);
|
||||
IOObjectRelease(device_iterator);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc)
|
||||
{
|
||||
dk_cd_read_mcn_t cd_read_mcn;
|
||||
bzero(&cd_read_mcn, sizeof(cd_read_mcn));
|
||||
|
||||
if(ioctl(fd, DKIOCCDREADMCN, &cd_read_mcn) == -1) {
|
||||
fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n");
|
||||
} else {
|
||||
strncpy( disc->mcn, cd_read_mcn.mcn, MCN_STR_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track)
|
||||
{
|
||||
dk_cd_read_isrc_t cd_read_isrc;
|
||||
bzero(&cd_read_isrc, sizeof(cd_read_isrc));
|
||||
cd_read_isrc.track = track;
|
||||
|
||||
if(ioctl(fd, DKIOCCDREADISRC, &cd_read_isrc) == -1) {
|
||||
fprintf(stderr, "Warning: Unable to read the international standard recording code (ISRC) for track %i\n", track);
|
||||
return;
|
||||
} else {
|
||||
strncpy( disc->isrc[track], cd_read_isrc.isrc, ISRC_STR_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
||||
switch(feature) {
|
||||
case DISCID_FEATURE_READ:
|
||||
case DISCID_FEATURE_MCN:
|
||||
case DISCID_FEATURE_ISRC:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *mb_disc_get_default_device_unportable(void)
|
||||
{
|
||||
return MB_DEFAULT_DEVICE;
|
||||
}
|
||||
|
||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *mb_toc) {
|
||||
dk_cd_read_toc_t toc;
|
||||
CDTOC *cdToc;
|
||||
mb_disc_toc_track *track;
|
||||
int i, numDesc;
|
||||
int track_num, min_track, max_track;
|
||||
|
||||
memset(&toc, 0, sizeof(toc));
|
||||
toc.format = kCDTOCFormatTOC;
|
||||
toc.formatAsTime = 0;
|
||||
toc.buffer = (char *)malloc(TOC_BUFFER_LEN);
|
||||
toc.bufferLength = TOC_BUFFER_LEN;
|
||||
if (ioctl(fd, DKIOCCDREADTOC, &toc) < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (toc.bufferLength < sizeof(CDTOC)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cdToc = (CDTOC *)toc.buffer;
|
||||
numDesc = CDTOCGetDescriptorCount(cdToc);
|
||||
min_track = -1;
|
||||
max_track = -1;
|
||||
for(i = 0; i < numDesc; i++) {
|
||||
CDTOCDescriptor *desc = &cdToc->descriptors[i];
|
||||
track = NULL;
|
||||
|
||||
/* A2 is the code for the lead-out position in the lead-in */
|
||||
if (desc->point == 0xA2 && desc->adr == 1) {
|
||||
track = &mb_toc->tracks[0];
|
||||
}
|
||||
|
||||
/* actual track data, (adr 2-3 are for MCN and ISRC data) */
|
||||
if (desc->point <= 99 && desc->adr == 1) {
|
||||
track_num = desc->point;
|
||||
track = &mb_toc->tracks[track_num];
|
||||
if (min_track < 0 || min_track > track_num) {
|
||||
min_track = track_num;
|
||||
}
|
||||
if (max_track < track_num) {
|
||||
max_track = track_num;
|
||||
}
|
||||
}
|
||||
|
||||
if (track) {
|
||||
track->address = CDConvertMSFToLBA(desc->p);
|
||||
track->control = desc->control;
|
||||
}
|
||||
}
|
||||
|
||||
mb_toc->first_track_num = min_track;
|
||||
mb_toc->last_track_num = max_track;
|
||||
|
||||
free(toc.buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *toc) {
|
||||
/* On Darwin the tracks are already filled along with the header */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
||||
unsigned int features) {
|
||||
int device_number;
|
||||
char device_name[MAXPATHLEN] = "\0";
|
||||
|
||||
device_number = (int) strtol(device, NULL, 10);
|
||||
if (device_number > 0) {
|
||||
if (!get_device_from_number(device_number,
|
||||
device_name, MAXPATHLEN)) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"no disc in drive number: %d", device_number);
|
||||
return 0;
|
||||
} else {
|
||||
return mb_disc_unix_read(disc, device_name, features);
|
||||
}
|
||||
} else {
|
||||
return mb_disc_unix_read(disc, device, features);
|
||||
}
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2013 Johannes Dewender
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
#include <stdio.h>
|
||||
|
||||
#include "discid/discid.h"
|
||||
#include "discid/discid_private.h"
|
||||
|
||||
|
||||
char *mb_disc_get_default_device_unportable(void) {
|
||||
return "/dev/null";
|
||||
}
|
||||
|
||||
|
||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device, unsigned int features) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"disc reading not implemented on this platform");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
@@ -1,275 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2013 Johannes Dewender
|
||||
Copyright (C) 2006 Matthias Friedrich
|
||||
Copyright (C) 2000 Robert Kaye
|
||||
Copyright (C) 1999 Marc E E van Woerkom
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <scsi/sg.h>
|
||||
|
||||
|
||||
#include "discid/discid.h"
|
||||
#include "discid/discid_private.h"
|
||||
#include "unix.h"
|
||||
|
||||
|
||||
/* timeout better shouldn't happen for scsi commands -> device is reset */
|
||||
#define DEFAULT_TIMEOUT 30000 /* in ms */
|
||||
|
||||
#ifndef SG_MAX_SENSE
|
||||
#define SG_MAX_SENSE 16
|
||||
#endif
|
||||
|
||||
#define MB_DEFAULT_DEVICE "/dev/cdrom"
|
||||
#define MAX_DEV_LEN 50
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
# define THREAD_LOCAL __thread
|
||||
#else
|
||||
# define THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
static THREAD_LOCAL char default_device[MAX_DEV_LEN] = "";
|
||||
|
||||
|
||||
static int get_device(int number, char *device, int device_len) {
|
||||
FILE *proc_file;
|
||||
char *current_device;
|
||||
char *lineptr = NULL;
|
||||
char *saveptr = NULL;
|
||||
size_t bufflen;
|
||||
int i, count, counter;
|
||||
int return_value = 0;
|
||||
|
||||
proc_file = fopen("/proc/sys/dev/cdrom/info", "r");
|
||||
if (proc_file != NULL) {
|
||||
/* skip to line containing device names */
|
||||
do {
|
||||
if (getline(&lineptr, &bufflen, proc_file) < 0) {
|
||||
return 0;
|
||||
}
|
||||
} while (strstr(lineptr, "drive name:") == NULL);
|
||||
|
||||
/* count number of devices = number of tabs - 1*/
|
||||
count = -1;
|
||||
for (i = 0; i < strlen(lineptr); i++) {
|
||||
if (lineptr[i] == '\t') count++;
|
||||
}
|
||||
|
||||
/* go through devices, they are in reverse order */
|
||||
current_device = strtok_r(lineptr, "\t", &saveptr);
|
||||
/* skip column title */
|
||||
current_device = strtok_r(NULL, "\t", &saveptr);
|
||||
counter = count;
|
||||
while (current_device != NULL && counter >= number) {
|
||||
if (counter == number) {
|
||||
snprintf(device, device_len,
|
||||
"/dev/%s", current_device);
|
||||
return_value = 1;
|
||||
}
|
||||
/* go to next in list */
|
||||
current_device = strtok_r(NULL, "\t", &saveptr);
|
||||
counter--;
|
||||
}
|
||||
|
||||
/* trim the trailing \n for the last entry = first device */
|
||||
if (return_value && device[strlen(device)-1] == '\n') {
|
||||
device[strlen(device)-1] = '\0';
|
||||
}
|
||||
free(lineptr);
|
||||
fclose(proc_file);
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) {
|
||||
struct cdrom_tochdr th;
|
||||
|
||||
int ret = ioctl(fd, CDROMREADTOCHDR, &th);
|
||||
|
||||
if ( ret < 0 )
|
||||
return 0; /* error */
|
||||
|
||||
toc->first_track_num = th.cdth_trk0;
|
||||
toc->last_track_num = th.cdth_trk1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) {
|
||||
struct cdrom_tocentry te;
|
||||
int ret;
|
||||
|
||||
te.cdte_track = track_num;
|
||||
te.cdte_format = CDROM_LBA;
|
||||
|
||||
ret = ioctl(fd, CDROMREADTOCENTRY, &te);
|
||||
assert( te.cdte_format == CDROM_LBA );
|
||||
|
||||
if ( ret < 0 )
|
||||
return 0; /* error */
|
||||
|
||||
track->address = te.cdte_addr.lba;
|
||||
track->control = te.cdte_ctrl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *mb_disc_get_default_device_unportable(void) {
|
||||
/* prefer the default device symlink to the internal names */
|
||||
if (mb_disc_unix_exists(MB_DEFAULT_DEVICE)) {
|
||||
return MB_DEFAULT_DEVICE;
|
||||
} else {
|
||||
if (get_device(1, default_device, MAX_DEV_LEN)) {
|
||||
return default_device;
|
||||
} else {
|
||||
return MB_DEFAULT_DEVICE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) {
|
||||
struct cdrom_mcn mcn;
|
||||
memset(&mcn, 0, sizeof mcn);
|
||||
|
||||
if(ioctl(fd, CDROM_GET_MCN, &mcn) == -1) {
|
||||
fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n");
|
||||
} else {
|
||||
strncpy( disc->mcn,
|
||||
(const char *)mcn.medium_catalog_number,
|
||||
MCN_STR_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a scsi command and receive data. */
|
||||
static int scsi_cmd(int fd, unsigned char *cmd, int cmd_len,
|
||||
unsigned char *data, int data_len) {
|
||||
unsigned char sense_buffer[SG_MAX_SENSE]; /* for "error situations" */
|
||||
sg_io_hdr_t io_hdr;
|
||||
|
||||
memset(&io_hdr, 0, sizeof io_hdr);
|
||||
|
||||
assert(cmd_len <= 16);
|
||||
|
||||
io_hdr.interface_id = 'S'; /* must always be 'S' (SCSI generic) */
|
||||
io_hdr.cmd_len = cmd_len;
|
||||
io_hdr.cmdp = cmd;
|
||||
io_hdr.timeout = DEFAULT_TIMEOUT; /* timeout in ms */
|
||||
io_hdr.sbp = sense_buffer;/* only used when status is CHECK_CONDITION */
|
||||
io_hdr.mx_sb_len = sizeof sense_buffer;
|
||||
io_hdr.flags = SG_FLAG_DIRECT_IO;
|
||||
|
||||
io_hdr.dxferp = (void*)data;
|
||||
io_hdr.dxfer_len = data_len;
|
||||
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
|
||||
if (ioctl(fd, SG_IO, &io_hdr) != 0) {
|
||||
return errno;
|
||||
} else {
|
||||
return io_hdr.status; /* 0 = success */
|
||||
}
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) {
|
||||
int i;
|
||||
unsigned char cmd[10];
|
||||
unsigned char data[24];
|
||||
char buffer[ISRC_STR_LENGTH+1];
|
||||
|
||||
memset(cmd, 0, sizeof cmd);
|
||||
memset(data, 0, sizeof data);
|
||||
memset(buffer, 0, sizeof buffer);
|
||||
|
||||
/* data read from the last appropriate sector encountered
|
||||
* by a current or previous media access operation.
|
||||
* The Logical Unit accesses the media when there is/was no access.
|
||||
* TODO: force access at a specific block? -> no duplicate ISRCs?
|
||||
*/
|
||||
cmd[0] = 0x42; /* READ SUB-CHANNEL */
|
||||
/* cmd[1] reserved / MSF bit (unused) */
|
||||
cmd[2] = 1 << 6; /* 6th bit set (SUBQ) -> get sub-channel data */
|
||||
cmd[3] = 0x03; /* get ISRC (ADR 3, Q sub-channel Mode-3) */
|
||||
/* 4+5 reserved */
|
||||
cmd[6] = track_num;
|
||||
/* cmd[7] = upper byte of the transfer length */
|
||||
cmd[8] = sizeof data; /* transfer length in bytes (4 header, 20 data)*/
|
||||
/* cmd[9] = control byte */
|
||||
|
||||
if (scsi_cmd(fd, cmd, sizeof cmd, data, sizeof data) != 0) {
|
||||
fprintf(stderr, "Warning: Cannot get ISRC code for track %d\n",
|
||||
track_num);
|
||||
return;
|
||||
}
|
||||
|
||||
/* data[1:4] = sub-q channel data header (audio status, data length) */
|
||||
if (data[8] & (1 << 7)) { /* TCVAL is set -> ISRCs valid */
|
||||
for (i = 0; i < ISRC_STR_LENGTH; i++) {
|
||||
buffer[i] = data[9 + i];
|
||||
}
|
||||
buffer[ISRC_STR_LENGTH] = 0;
|
||||
strncpy(disc->isrc[track_num], buffer, ISRC_STR_LENGTH);
|
||||
}
|
||||
/* data[21:23] = zero, AFRAME, reserved */
|
||||
}
|
||||
|
||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
||||
switch(feature) {
|
||||
case DISCID_FEATURE_READ:
|
||||
case DISCID_FEATURE_MCN:
|
||||
case DISCID_FEATURE_ISRC:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
||||
unsigned int features) {
|
||||
char device_name[MAX_DEV_LEN] = "";
|
||||
int device_number;
|
||||
|
||||
device_number = (int) strtol(device, NULL, 10);
|
||||
if (device_number > 0) {
|
||||
if(!get_device(device_number, device_name, MAX_DEV_LEN)) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot find cd device with the number '%d'",
|
||||
device_number);
|
||||
return 0;
|
||||
} else {
|
||||
return mb_disc_unix_read(disc, device_name, features);
|
||||
}
|
||||
} else {
|
||||
return mb_disc_unix_read(disc, device, features);
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
@@ -1,108 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2009 Shunsuke Kuroda
|
||||
Copyright (C) 2006 Matthias Friedrich
|
||||
Copyright (C) 2000 Robert Kaye
|
||||
Copyright (C) 1999 Marc E E van Woerkom
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/cdio.h>
|
||||
|
||||
|
||||
#include "discid/discid.h"
|
||||
#include "discid/discid_private.h"
|
||||
#include "unix.h"
|
||||
|
||||
#define NUM_CANDIDATES 2
|
||||
|
||||
static char *device_candidates[NUM_CANDIDATES] = {"/vol/dev/aliases/cdrom0",
|
||||
"/volumes/dev/aliases/cdrom0"};
|
||||
|
||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) {
|
||||
struct cdrom_tochdr th;
|
||||
|
||||
int ret = ioctl(fd, CDROMREADTOCHDR, &th);
|
||||
|
||||
if ( ret < 0 )
|
||||
return ret; /* error */
|
||||
|
||||
toc->first_track_num = th.cdth_trk0;
|
||||
toc->last_track_num = th.cdth_trk1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) {
|
||||
struct cdrom_tocentry te;
|
||||
int ret;
|
||||
|
||||
memset(&te, 0, sizeof te);
|
||||
te.cdte_track = track_num;
|
||||
te.cdte_format = CDROM_LBA;
|
||||
|
||||
ret = ioctl(fd, CDROMREADTOCENTRY, &te);
|
||||
|
||||
if ( ret < 0 )
|
||||
return 0; /* error */
|
||||
|
||||
assert( te.cdte_format == CDROM_LBA );
|
||||
track->address = te.cdte_addr.lba;
|
||||
track->control = te.cdte_ctrl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) {
|
||||
return;
|
||||
}
|
||||
|
||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *mb_disc_get_default_device_unportable(void) {
|
||||
return mb_disc_unix_find_device(device_candidates, NUM_CANDIDATES);
|
||||
}
|
||||
|
||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
||||
switch(feature) {
|
||||
case DISCID_FEATURE_READ:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
||||
unsigned int features) {
|
||||
return mb_disc_unix_read(disc, device, features);
|
||||
}
|
||||
|
||||
/* EOF */
|
@@ -1,247 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2007-2008 Lukas Lalinsky
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#if (_MSC_VER < 1900)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
#include <ntddcdrm.h>
|
||||
#elif defined(__MINGW32__)
|
||||
#include <ddk/ntddcdrm.h>
|
||||
#else
|
||||
#include "ntddcdrm.h"
|
||||
#endif
|
||||
|
||||
#include "discid/discid.h"
|
||||
#include "discid/discid_private.h"
|
||||
|
||||
|
||||
#define MB_DEFAULT_DEVICE "D:"
|
||||
#define MAX_DEV_LEN 3
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define THREAD_LOCAL __declspec(thread)
|
||||
#elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
# define THREAD_LOCAL __thread
|
||||
#else
|
||||
# define THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
static THREAD_LOCAL char default_device[MAX_DEV_LEN] = "\0";
|
||||
|
||||
static int address_to_sectors(UCHAR address[4]) {
|
||||
return address[1] * 4500 + address[2] * 75 + address[3];
|
||||
}
|
||||
|
||||
static HANDLE create_device_handle(mb_disc_private *disc, const char *device) {
|
||||
HANDLE hDevice;
|
||||
char filename[128];
|
||||
const char* colon;
|
||||
size_t len;
|
||||
|
||||
strcpy(filename, "\\\\.\\");
|
||||
len = strlen(device);
|
||||
colon = strchr(device, ':');
|
||||
if (colon) {
|
||||
len = colon - device + 1;
|
||||
}
|
||||
strncat(filename, device, len > 120 ? 120 : len);
|
||||
|
||||
hDevice = CreateFile(filename, GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot open the CD audio device '%s'", device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hDevice;
|
||||
}
|
||||
|
||||
static void read_disc_mcn(HANDLE hDevice, mb_disc_private *disc) {
|
||||
DWORD dwReturned;
|
||||
BOOL bResult;
|
||||
CDROM_SUB_Q_DATA_FORMAT format;
|
||||
SUB_Q_CHANNEL_DATA data;
|
||||
|
||||
format.Track = 0;
|
||||
format.Format = IOCTL_CDROM_MEDIA_CATALOG;
|
||||
bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_Q_CHANNEL,
|
||||
&format, sizeof(format),
|
||||
&data, sizeof(data),
|
||||
&dwReturned, NULL);
|
||||
if (bResult == FALSE) {
|
||||
fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n");
|
||||
} else {
|
||||
strncpy(disc->mcn, (char *) data.MediaCatalog.MediaCatalog,
|
||||
MCN_STR_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void read_disc_isrc(HANDLE hDevice, mb_disc_private *disc, int track) {
|
||||
DWORD dwReturned;
|
||||
BOOL bResult;
|
||||
CDROM_SUB_Q_DATA_FORMAT format;
|
||||
SUB_Q_CHANNEL_DATA data;
|
||||
|
||||
format.Track = track;
|
||||
format.Format = IOCTL_CDROM_TRACK_ISRC;
|
||||
bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_Q_CHANNEL,
|
||||
&format, sizeof(format),
|
||||
&data, sizeof(data),
|
||||
&dwReturned, NULL);
|
||||
if (bResult == FALSE) {
|
||||
fprintf(stderr, "Warning: Unable to read the international standard recording code (ISRC) for track %i\n", track);
|
||||
} else {
|
||||
strncpy(disc->isrc[track], (char *) data.TrackIsrc.TrackIsrc,
|
||||
ISRC_STR_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
static int get_nth_device(int number, char* device, int device_length) {
|
||||
int i, counter = 0;
|
||||
char tmpDevice[MAX_DEV_LEN];
|
||||
DWORD mask = GetLogicalDrives();
|
||||
|
||||
for (i = 0; i <= 25; i++) {
|
||||
if (mask >> i & 1) {
|
||||
snprintf(tmpDevice, MAX_DEV_LEN, "%c:", i + 'A');
|
||||
if (GetDriveType(tmpDevice) == DRIVE_CDROM) {
|
||||
counter++;
|
||||
if (counter == number) {
|
||||
strncpy(device, tmpDevice, device_length);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char *mb_disc_get_default_device_unportable(void) {
|
||||
if (!get_nth_device(1, default_device, MAX_DEV_LEN)) {
|
||||
return MB_DEFAULT_DEVICE;
|
||||
}
|
||||
|
||||
return default_device;
|
||||
}
|
||||
|
||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
||||
switch(feature) {
|
||||
case DISCID_FEATURE_READ:
|
||||
case DISCID_FEATURE_MCN:
|
||||
case DISCID_FEATURE_ISRC:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int mb_disc_winnt_read_toc(HANDLE device, mb_disc_private *disc, mb_disc_toc *toc) {
|
||||
DWORD dwReturned;
|
||||
BOOL bResult;
|
||||
CDROM_TOC cd;
|
||||
int i;
|
||||
|
||||
bResult = DeviceIoControl(device, IOCTL_CDROM_READ_TOC,
|
||||
NULL, 0,
|
||||
&cd, sizeof(cd),
|
||||
&dwReturned, NULL);
|
||||
if (bResult == FALSE) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"error while reading the CD TOC");
|
||||
return 0;
|
||||
}
|
||||
|
||||
toc->first_track_num = cd.FirstTrack;
|
||||
toc->last_track_num = cd.LastTrack;
|
||||
|
||||
/* Get info about all tracks */
|
||||
for (i = toc->first_track_num; i <= toc->last_track_num; i++) {
|
||||
toc->tracks[i].address = address_to_sectors(cd.TrackData[i - 1].Address) - 150;
|
||||
toc->tracks[i].control = cd.TrackData[i - 1].Control;
|
||||
}
|
||||
|
||||
/* Lead-out is stored after the last track */
|
||||
toc->tracks[0].address = address_to_sectors(cd.TrackData[toc->last_track_num].Address) - 150;
|
||||
toc->tracks[0].control = cd.TrackData[toc->last_track_num].Control;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
||||
unsigned int features) {
|
||||
mb_disc_toc toc;
|
||||
char tmpDevice[MAX_DEV_LEN];
|
||||
HANDLE hDevice;
|
||||
int i, device_number;
|
||||
|
||||
device_number = (int) strtol(device, NULL, 10);
|
||||
|
||||
if (device_number > 0) {
|
||||
if (!get_nth_device(device_number, tmpDevice, MAX_DEV_LEN)) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot find the CD audio device '%i'", device_number);
|
||||
return 0;
|
||||
}
|
||||
device = tmpDevice;
|
||||
}
|
||||
|
||||
hDevice = create_device_handle(disc, device);
|
||||
if (hDevice == 0)
|
||||
return 0;
|
||||
|
||||
if (!mb_disc_winnt_read_toc(hDevice, disc, &toc)) {
|
||||
CloseHandle(hDevice);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mb_disc_load_toc(disc, &toc)) {
|
||||
CloseHandle(hDevice);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (features & DISCID_FEATURE_MCN) {
|
||||
read_disc_mcn(hDevice, disc);
|
||||
}
|
||||
|
||||
for (i = disc->first_track_num; i <= disc->last_track_num; i++) {
|
||||
if (features & DISCID_FEATURE_ISRC) {
|
||||
read_disc_isrc(hDevice, disc, i);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hDevice);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* EOF */
|
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* ntddcdrm.h
|
||||
*
|
||||
* CDROM IOCTL interface.
|
||||
*
|
||||
* This file is part of the w32api package.
|
||||
*
|
||||
* Contributors:
|
||||
* Created by Casper S. Hornstrup <chorns@users.sourceforge.net>
|
||||
*
|
||||
* THIS SOFTWARE IS NOT COPYRIGHTED
|
||||
*
|
||||
* This source code is offered for use in the public domain. You may
|
||||
* use, modify or distribute it freely.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful but
|
||||
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
|
||||
* DISCLAIMED. This includes but is not limited to warranties of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NTDDCDRM_H
|
||||
#define __NTDDCDRM_H
|
||||
|
||||
#if __GNUC__ >=3
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma pack(push,4)
|
||||
|
||||
#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
|
||||
|
||||
#define IOCTL_CDROM_CHECK_VERIFY \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_FIND_NEW_DEVICES \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_CONTROL \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_LAST_SESSION \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_VOLUME \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_PAUSE_AUDIO \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_PLAY_AUDIO_MSF \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_RAW_READ \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_READ_Q_CHANNEL \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_READ_TOC \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_READ_TOC_EX \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_RESUME_AUDIO \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_SEEK_AUDIO_MSF \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_SET_VOLUME \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_SIMBAD \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_STOP_AUDIO \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
|
||||
#define MAXIMUM_NUMBER_TRACKS 100
|
||||
#define MAXIMUM_CDROM_SIZE 804
|
||||
#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2
|
||||
|
||||
typedef struct _TRACK_DATA {
|
||||
UCHAR Reserved;
|
||||
UCHAR Control : 4;
|
||||
UCHAR Adr : 4;
|
||||
UCHAR TrackNumber;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Address[4];
|
||||
} TRACK_DATA, *PTRACK_DATA;
|
||||
|
||||
/* CDROM_DISK_DATA.DiskData flags */
|
||||
#define CDROM_DISK_AUDIO_TRACK 0x00000001
|
||||
#define CDROM_DISK_DATA_TRACK 0x00000002
|
||||
|
||||
typedef struct _CDROM_DISK_DATA {
|
||||
ULONG DiskData;
|
||||
} CDROM_DISK_DATA, *PCDROM_DISK_DATA;
|
||||
|
||||
typedef struct _CDROM_PLAY_AUDIO_MSF {
|
||||
UCHAR StartingM;
|
||||
UCHAR StartingS;
|
||||
UCHAR StartingF;
|
||||
UCHAR EndingM;
|
||||
UCHAR EndingS;
|
||||
UCHAR EndingF;
|
||||
} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF;
|
||||
|
||||
/* CDROM_READ_TOC_EX.Format constants */
|
||||
#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00
|
||||
#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01
|
||||
#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02
|
||||
#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03
|
||||
#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04
|
||||
#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05
|
||||
|
||||
typedef struct _CDROM_READ_TOC_EX {
|
||||
UCHAR Format : 4;
|
||||
UCHAR Reserved1 : 3;
|
||||
UCHAR Msf : 1;
|
||||
UCHAR SessionTrack;
|
||||
UCHAR Reserved2;
|
||||
UCHAR Reserved3;
|
||||
} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX;
|
||||
|
||||
typedef struct _CDROM_SEEK_AUDIO_MSF {
|
||||
UCHAR M;
|
||||
UCHAR S;
|
||||
UCHAR F;
|
||||
} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF;
|
||||
|
||||
/* CDROM_SUB_Q_DATA_FORMAT.Format constants */
|
||||
#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00
|
||||
#define IOCTL_CDROM_CURRENT_POSITION 0x01
|
||||
#define IOCTL_CDROM_MEDIA_CATALOG 0x02
|
||||
#define IOCTL_CDROM_TRACK_ISRC 0x03
|
||||
|
||||
typedef struct _CDROM_SUB_Q_DATA_FORMAT {
|
||||
UCHAR Format;
|
||||
UCHAR Track;
|
||||
} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT;
|
||||
|
||||
typedef struct _CDROM_TOC {
|
||||
UCHAR Length[2];
|
||||
UCHAR FirstTrack;
|
||||
UCHAR LastTrack;
|
||||
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS];
|
||||
} CDROM_TOC, *PCDROM_TOC;
|
||||
|
||||
#define CDROM_TOC_SIZE sizeof(CDROM_TOC)
|
||||
|
||||
typedef struct _CDROM_TOC_ATIP_DATA_BLOCK {
|
||||
UCHAR CdrwReferenceSpeed : 3;
|
||||
UCHAR Reserved3 : 1;
|
||||
UCHAR WritePower : 3;
|
||||
UCHAR True1 : 1;
|
||||
UCHAR Reserved4 : 6;
|
||||
UCHAR UnrestrictedUse : 1;
|
||||
UCHAR Reserved5 : 1;
|
||||
UCHAR A3Valid : 1;
|
||||
UCHAR A2Valid : 1;
|
||||
UCHAR A1Valid : 1;
|
||||
UCHAR Reserved6 : 3;
|
||||
UCHAR IsCdrw : 1;
|
||||
UCHAR True2 : 1;
|
||||
UCHAR Reserved7;
|
||||
UCHAR LeadInMsf[3];
|
||||
UCHAR Reserved8;
|
||||
UCHAR LeadOutMsf[3];
|
||||
UCHAR Reserved9;
|
||||
UCHAR A1Values[3];
|
||||
UCHAR Reserved10;
|
||||
UCHAR A2Values[3];
|
||||
UCHAR Reserved11;
|
||||
UCHAR A3Values[3];
|
||||
UCHAR Reserved12;
|
||||
} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK;
|
||||
|
||||
/* CDROM_TOC_CD_TEXT_DATA_BLOCK.PackType constants */
|
||||
#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80
|
||||
#define CDROM_CD_TEXT_PACK_PERFORMER 0x81
|
||||
#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82
|
||||
#define CDROM_CD_TEXT_PACK_COMPOSER 0x83
|
||||
#define CDROM_CD_TEXT_PACK_ARRANGER 0x84
|
||||
#define CDROM_CD_TEXT_PACK_MESSAGES 0x85
|
||||
#define CDROM_CD_TEXT_PACK_DISC_ID 0x86
|
||||
#define CDROM_CD_TEXT_PACK_GENRE 0x87
|
||||
#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88
|
||||
#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89
|
||||
#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e
|
||||
#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f
|
||||
|
||||
typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK {
|
||||
UCHAR PackType;
|
||||
UCHAR TrackNumber : 7;
|
||||
UCHAR ExtensionFlag : 1;
|
||||
UCHAR SequenceNumber;
|
||||
UCHAR CharacterPosition : 4;
|
||||
UCHAR BlockNumber : 3;
|
||||
UCHAR Unicode : 1;
|
||||
union {
|
||||
UCHAR Text[12];
|
||||
WCHAR WText[6];
|
||||
};
|
||||
UCHAR CRC[2];
|
||||
} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK;
|
||||
|
||||
/* CDROM_TOC_FULL_TOC_DATA_BLOCK.Adr constants */
|
||||
#define ADR_NO_MODE_INFORMATION 0x0
|
||||
#define ADR_ENCODES_CURRENT_POSITION 0x1
|
||||
#define ADR_ENCODES_MEDIA_CATALOG 0x2
|
||||
#define ADR_ENCODES_ISRC 0x3
|
||||
|
||||
typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK {
|
||||
UCHAR SessionNumber;
|
||||
UCHAR Control : 4;
|
||||
UCHAR Adr : 4;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Point;
|
||||
UCHAR MsfExtra[3];
|
||||
UCHAR Zero;
|
||||
UCHAR Msf[3];
|
||||
} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK;
|
||||
|
||||
/* SUB_Q_HEADER.AudioStatus constants */
|
||||
#define AUDIO_STATUS_NOT_SUPPORTED 0x00
|
||||
#define AUDIO_STATUS_IN_PROGRESS 0x11
|
||||
#define AUDIO_STATUS_PAUSED 0x12
|
||||
#define AUDIO_STATUS_PLAY_COMPLETE 0x13
|
||||
#define AUDIO_STATUS_PLAY_ERROR 0x14
|
||||
#define AUDIO_STATUS_NO_STATUS 0x15
|
||||
|
||||
typedef struct _SUB_Q_HEADER {
|
||||
UCHAR Reserved;
|
||||
UCHAR AudioStatus;
|
||||
UCHAR DataLength[2];
|
||||
} SUB_Q_HEADER, *PSUB_Q_HEADER;
|
||||
|
||||
typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Reserved[3];
|
||||
UCHAR Reserved1 : 7;
|
||||
UCHAR Mcval :1;
|
||||
UCHAR MediaCatalog[15];
|
||||
} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER;
|
||||
|
||||
typedef struct _SUB_Q_TRACK_ISRC {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Reserved0;
|
||||
UCHAR Track;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2 : 7;
|
||||
UCHAR Tcval : 1;
|
||||
UCHAR TrackIsrc[15];
|
||||
} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC;
|
||||
|
||||
typedef struct _SUB_Q_CURRENT_POSITION {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Control : 4;
|
||||
UCHAR ADR : 4;
|
||||
UCHAR TrackNumber;
|
||||
UCHAR IndexNumber;
|
||||
UCHAR AbsoluteAddress[4];
|
||||
UCHAR TrackRelativeAddress[4];
|
||||
} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION;
|
||||
|
||||
typedef union _SUB_Q_CHANNEL_DATA {
|
||||
SUB_Q_CURRENT_POSITION CurrentPosition;
|
||||
SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog;
|
||||
SUB_Q_TRACK_ISRC TrackIsrc;
|
||||
} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA;
|
||||
|
||||
/* CDROM_AUDIO_CONTROL.LbaFormat constants */
|
||||
#define AUDIO_WITH_PREEMPHASIS 0x1
|
||||
#define DIGITAL_COPY_PERMITTED 0x2
|
||||
#define AUDIO_DATA_TRACK 0x4
|
||||
#define TWO_FOUR_CHANNEL_AUDIO 0x8
|
||||
|
||||
typedef struct _CDROM_AUDIO_CONTROL {
|
||||
UCHAR LbaFormat;
|
||||
USHORT LogicalBlocksPerSecond;
|
||||
} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL;
|
||||
|
||||
typedef struct _VOLUME_CONTROL {
|
||||
UCHAR PortVolume[4];
|
||||
} VOLUME_CONTROL, *PVOLUME_CONTROL;
|
||||
|
||||
typedef enum _TRACK_MODE_TYPE {
|
||||
YellowMode2,
|
||||
XAForm2,
|
||||
CDDA
|
||||
} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE;
|
||||
|
||||
typedef struct __RAW_READ_INFO {
|
||||
LARGE_INTEGER DiskOffset;
|
||||
ULONG SectorCount;
|
||||
TRACK_MODE_TYPE TrackMode;
|
||||
} RAW_READ_INFO, *PRAW_READ_INFO;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NTDDCDRM_H */
|
@@ -1,329 +0,0 @@
|
||||
/* (PD) 2001 The Bitzi Corporation
|
||||
* Please see file COPYING or http://bitzi.com/publicdomain
|
||||
* for more info.
|
||||
*
|
||||
* NIST Secure Hash Algorithm
|
||||
* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu>
|
||||
* from Peter C. Gutmann's implementation as found in
|
||||
* Applied Cryptography by Bruce Schneier
|
||||
* Further modifications to include the "UNRAVEL" stuff, below
|
||||
*
|
||||
* This code is in the public domain
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "sha1.h"
|
||||
|
||||
/* UNRAVEL should be fastest & biggest */
|
||||
/* UNROLL_LOOPS should be just as big, but slightly slower */
|
||||
/* both undefined should be smallest and slowest */
|
||||
|
||||
#define UNRAVEL
|
||||
/* #define UNROLL_LOOPS */
|
||||
|
||||
/* SHA f()-functions */
|
||||
|
||||
#define f1(x,y,z) ((x & y) | (~x & z))
|
||||
#define f2(x,y,z) (x ^ y ^ z)
|
||||
#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
|
||||
#define f4(x,y,z) (x ^ y ^ z)
|
||||
|
||||
/* SHA constants */
|
||||
|
||||
#define CONST1 0x5a827999L
|
||||
#define CONST2 0x6ed9eba1L
|
||||
#define CONST3 0x8f1bbcdcL
|
||||
#define CONST4 0xca62c1d6L
|
||||
|
||||
/* truncate to 32 bits -- should be a null op on 32-bit machines */
|
||||
|
||||
#define T32(x) ((x) & 0xffffffffL)
|
||||
|
||||
/* 32-bit rotate */
|
||||
|
||||
#define R32(x,n) T32(((x << n) | (x >> (32 - n))))
|
||||
|
||||
/* the generic case, for when the overall rotation is not unraveled */
|
||||
|
||||
#define FG(n) \
|
||||
T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \
|
||||
E = D; D = C; C = R32(B,30); B = A; A = T
|
||||
|
||||
/* specific cases, for when the overall rotation is unraveled */
|
||||
|
||||
#define FA(n) \
|
||||
T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
|
||||
|
||||
#define FB(n) \
|
||||
E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
|
||||
|
||||
#define FC(n) \
|
||||
D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
|
||||
|
||||
#define FD(n) \
|
||||
C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
|
||||
|
||||
#define FE(n) \
|
||||
B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
|
||||
|
||||
#define FT(n) \
|
||||
A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
|
||||
|
||||
/* do SHA transformation */
|
||||
|
||||
static void sha_transform(SHA_INFO *sha_info)
|
||||
{
|
||||
int i;
|
||||
SHA_BYTE *dp;
|
||||
SHA_LONG T, A, B, C, D, E, W[80], *WP;
|
||||
|
||||
dp = sha_info->data;
|
||||
|
||||
/*
|
||||
the following makes sure that at least one code block below is
|
||||
traversed or an error is reported, without the necessity for nested
|
||||
preprocessor if/else/endif blocks, which are a great pain in the
|
||||
nether regions of the anatomy...
|
||||
*/
|
||||
#undef SWAP_DONE
|
||||
|
||||
#if (SHA_BYTE_ORDER == 1234)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; ++i) {
|
||||
T = *((SHA_LONG *) dp);
|
||||
dp += 4;
|
||||
W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
||||
}
|
||||
#endif /* SHA_BYTE_ORDER == 1234 */
|
||||
|
||||
#if (SHA_BYTE_ORDER == 4321)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; ++i) {
|
||||
T = *((SHA_LONG *) dp);
|
||||
dp += 4;
|
||||
W[i] = T32(T);
|
||||
}
|
||||
#endif /* SHA_BYTE_ORDER == 4321 */
|
||||
|
||||
#if (SHA_BYTE_ORDER == 12345678)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; i += 2) {
|
||||
T = *((SHA_LONG *) dp);
|
||||
dp += 8;
|
||||
W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
||||
T >>= 32;
|
||||
W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
||||
}
|
||||
#endif /* SHA_BYTE_ORDER == 12345678 */
|
||||
|
||||
#if (SHA_BYTE_ORDER == 87654321)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; i += 2) {
|
||||
T = *((SHA_LONG *) dp);
|
||||
dp += 8;
|
||||
W[i] = T32(T >> 32);
|
||||
W[i+1] = T32(T);
|
||||
}
|
||||
#endif /* SHA_BYTE_ORDER == 87654321 */
|
||||
|
||||
#ifndef SWAP_DONE
|
||||
#error Unknown byte order -- you need to add code here
|
||||
#endif /* SWAP_DONE */
|
||||
|
||||
for (i = 16; i < 80; ++i) {
|
||||
W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
|
||||
#if (SHA_VERSION == 1)
|
||||
W[i] = R32(W[i], 1);
|
||||
#endif /* SHA_VERSION */
|
||||
}
|
||||
A = sha_info->digest[0];
|
||||
B = sha_info->digest[1];
|
||||
C = sha_info->digest[2];
|
||||
D = sha_info->digest[3];
|
||||
E = sha_info->digest[4];
|
||||
WP = W;
|
||||
#ifdef UNRAVEL
|
||||
FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
|
||||
FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
|
||||
FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
|
||||
FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
|
||||
FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
|
||||
FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
|
||||
FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
|
||||
FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
|
||||
sha_info->digest[0] = T32(sha_info->digest[0] + E);
|
||||
sha_info->digest[1] = T32(sha_info->digest[1] + T);
|
||||
sha_info->digest[2] = T32(sha_info->digest[2] + A);
|
||||
sha_info->digest[3] = T32(sha_info->digest[3] + B);
|
||||
sha_info->digest[4] = T32(sha_info->digest[4] + C);
|
||||
#else /* !UNRAVEL */
|
||||
#ifdef UNROLL_LOOPS
|
||||
FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
|
||||
FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
|
||||
FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
|
||||
FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
|
||||
FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
|
||||
FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
|
||||
FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
|
||||
FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
|
||||
#else /* !UNROLL_LOOPS */
|
||||
for (i = 0; i < 20; ++i) { FG(1); }
|
||||
for (i = 20; i < 40; ++i) { FG(2); }
|
||||
for (i = 40; i < 60; ++i) { FG(3); }
|
||||
for (i = 60; i < 80; ++i) { FG(4); }
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
sha_info->digest[0] = T32(sha_info->digest[0] + A);
|
||||
sha_info->digest[1] = T32(sha_info->digest[1] + B);
|
||||
sha_info->digest[2] = T32(sha_info->digest[2] + C);
|
||||
sha_info->digest[3] = T32(sha_info->digest[3] + D);
|
||||
sha_info->digest[4] = T32(sha_info->digest[4] + E);
|
||||
#endif /* !UNRAVEL */
|
||||
}
|
||||
|
||||
/* initialize the SHA digest */
|
||||
|
||||
void sha_init(SHA_INFO *sha_info)
|
||||
{
|
||||
sha_info->digest[0] = 0x67452301L;
|
||||
sha_info->digest[1] = 0xefcdab89L;
|
||||
sha_info->digest[2] = 0x98badcfeL;
|
||||
sha_info->digest[3] = 0x10325476L;
|
||||
sha_info->digest[4] = 0xc3d2e1f0L;
|
||||
sha_info->count_lo = 0L;
|
||||
sha_info->count_hi = 0L;
|
||||
sha_info->local = 0;
|
||||
}
|
||||
|
||||
/* update the SHA digest */
|
||||
|
||||
void sha_update(SHA_INFO *sha_info, SHA_BYTE *buffer, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
SHA_LONG clo;
|
||||
|
||||
clo = T32(sha_info->count_lo + ((SHA_LONG) count << 3));
|
||||
if (clo < sha_info->count_lo) {
|
||||
++sha_info->count_hi;
|
||||
}
|
||||
sha_info->count_lo = clo;
|
||||
sha_info->count_hi += (SHA_LONG) count >> 29;
|
||||
if (sha_info->local) {
|
||||
i = SHA_BLOCKSIZE - sha_info->local;
|
||||
if (i > count) {
|
||||
i = count;
|
||||
}
|
||||
memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
|
||||
count -= i;
|
||||
buffer += i;
|
||||
sha_info->local += i;
|
||||
if (sha_info->local == SHA_BLOCKSIZE) {
|
||||
sha_transform(sha_info);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (count >= SHA_BLOCKSIZE) {
|
||||
memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
|
||||
buffer += SHA_BLOCKSIZE;
|
||||
count -= SHA_BLOCKSIZE;
|
||||
sha_transform(sha_info);
|
||||
}
|
||||
memcpy(sha_info->data, buffer, count);
|
||||
sha_info->local = count;
|
||||
}
|
||||
|
||||
/* finish computing the SHA digest */
|
||||
|
||||
void sha_final(unsigned char digest[20], SHA_INFO *sha_info)
|
||||
{
|
||||
int count;
|
||||
SHA_LONG lo_bit_count, hi_bit_count;
|
||||
|
||||
lo_bit_count = sha_info->count_lo;
|
||||
hi_bit_count = sha_info->count_hi;
|
||||
count = (int) ((lo_bit_count >> 3) & 0x3f);
|
||||
((SHA_BYTE *) sha_info->data)[count++] = 0x80;
|
||||
if (count > SHA_BLOCKSIZE - 8) {
|
||||
memset(((SHA_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
|
||||
sha_transform(sha_info);
|
||||
memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
|
||||
} else {
|
||||
memset(((SHA_BYTE *) sha_info->data) + count, 0,
|
||||
SHA_BLOCKSIZE - 8 - count);
|
||||
}
|
||||
sha_info->data[56] = (unsigned char) ((hi_bit_count >> 24) & 0xff);
|
||||
sha_info->data[57] = (unsigned char) ((hi_bit_count >> 16) & 0xff);
|
||||
sha_info->data[58] = (unsigned char) ((hi_bit_count >> 8) & 0xff);
|
||||
sha_info->data[59] = (unsigned char) ((hi_bit_count >> 0) & 0xff);
|
||||
sha_info->data[60] = (unsigned char) ((lo_bit_count >> 24) & 0xff);
|
||||
sha_info->data[61] = (unsigned char) ((lo_bit_count >> 16) & 0xff);
|
||||
sha_info->data[62] = (unsigned char) ((lo_bit_count >> 8) & 0xff);
|
||||
sha_info->data[63] = (unsigned char) ((lo_bit_count >> 0) & 0xff);
|
||||
sha_transform(sha_info);
|
||||
digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
|
||||
digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
|
||||
digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
|
||||
digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
|
||||
digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
|
||||
digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
|
||||
digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
|
||||
digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
|
||||
digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
|
||||
digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
|
||||
digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
|
||||
digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
|
||||
digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
|
||||
digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
|
||||
digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
|
||||
digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
|
||||
digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
|
||||
digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
|
||||
digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
|
||||
digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
|
||||
}
|
||||
|
||||
/* compute the SHA digest of a FILE stream */
|
||||
|
||||
#define BLOCK_SIZE 8192
|
||||
|
||||
void sha_stream(unsigned char digest[20], SHA_INFO *sha_info, FILE *fin)
|
||||
{
|
||||
size_t i;
|
||||
SHA_BYTE data[BLOCK_SIZE];
|
||||
|
||||
sha_init(sha_info);
|
||||
while ((i = fread(data, 1, BLOCK_SIZE, fin)) > 0) {
|
||||
sha_update(sha_info, data, i);
|
||||
}
|
||||
sha_final(digest, sha_info);
|
||||
}
|
||||
|
||||
/* print a SHA digest */
|
||||
|
||||
void sha_print(unsigned char digest[20])
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < 5; ++j) {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
printf("%02x", *digest++);
|
||||
}
|
||||
printf("%c", (j < 4) ? ' ' : '\n');
|
||||
}
|
||||
}
|
||||
|
||||
char *sha_version(void)
|
||||
{
|
||||
#if (SHA_VERSION == 1)
|
||||
static char *version = "SHA-1";
|
||||
#else
|
||||
static char *version = "SHA";
|
||||
#endif
|
||||
return(version);
|
||||
}
|
||||
|
@@ -1,63 +0,0 @@
|
||||
/* NIST Secure Hash Algorithm */
|
||||
/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
|
||||
/* from Peter C. Gutmann's implementation as found in */
|
||||
/* Applied Cryptography by Bruce Schneier */
|
||||
/* This code is in the public domain */
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef SHA_H
|
||||
#define SHA_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "discid/discid.h" /* for LIBDISCID_INTERNAL */
|
||||
|
||||
/* Useful defines & typedefs */
|
||||
typedef unsigned char SHA_BYTE; /* 8-bit quantity */
|
||||
typedef unsigned long SHA_LONG; /* 32-or-more-bit quantity */
|
||||
|
||||
#define SHA_BLOCKSIZE 64
|
||||
#define SHA_DIGESTSIZE 20
|
||||
|
||||
typedef struct {
|
||||
SHA_LONG digest[5]; /* message digest */
|
||||
SHA_LONG count_lo, count_hi; /* 64-bit bit count */
|
||||
SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
|
||||
size_t local; /* unprocessed amount in data */
|
||||
} SHA_INFO;
|
||||
|
||||
LIBDISCID_INTERNAL void sha_init(SHA_INFO *);
|
||||
LIBDISCID_INTERNAL void sha_update(SHA_INFO *, SHA_BYTE *, size_t);
|
||||
LIBDISCID_INTERNAL void sha_final(unsigned char [20], SHA_INFO *);
|
||||
|
||||
LIBDISCID_INTERNAL void sha_stream(unsigned char [20], SHA_INFO *, FILE *);
|
||||
LIBDISCID_INTERNAL void sha_print(unsigned char [20]);
|
||||
LIBDISCID_INTERNAL char *sha_version(void);
|
||||
|
||||
#define SHA_VERSION 1
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# if SIZEOF_LONG == 4
|
||||
# define SHA_BYTE_ORDER 4321
|
||||
# elif SIZEOF_LONG == 8
|
||||
# define SHA_BYTE_ORDER 87654321
|
||||
# endif
|
||||
#else
|
||||
# if SIZEOF_LONG == 4
|
||||
# define SHA_BYTE_ORDER 1234
|
||||
# elif SIZEOF_LONG == 8
|
||||
# define SHA_BYTE_ORDER 12345678
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define SHA_BYTE_ORDER 1234
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SHA_H */
|
@@ -1,116 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2006 Lukas Lalinsky
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#if (_MSC_VER < 1900)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "discid/discid_private.h"
|
||||
|
||||
#define XA_INTERVAL ((60 + 90 + 2) * 75)
|
||||
#define DATA_TRACK 0x04
|
||||
|
||||
|
||||
int mb_disc_load_toc(mb_disc_private *disc, mb_disc_toc *toc) {
|
||||
int first_audio_track, last_audio_track, i;
|
||||
mb_disc_toc_track *track;
|
||||
|
||||
if (toc->first_track_num < 1) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"invalid CD TOC - first track number must be 1 or higher");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (toc->last_track_num < 1) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"invalid CD TOC - last track number must be 99 or lower");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we can't just skip data tracks at the front
|
||||
* releases are always expected to start with track 1 by MusicBrainz
|
||||
*/
|
||||
first_audio_track = toc->first_track_num;
|
||||
last_audio_track = -1;
|
||||
/* scan the TOC for audio tracks */
|
||||
for (i = toc->first_track_num; i <= toc->last_track_num; i++) {
|
||||
track = &toc->tracks[i];
|
||||
if ( !(track->control & DATA_TRACK) ) {
|
||||
last_audio_track = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (last_audio_track < 0) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"no actual audio tracks on disc: CDROM or DVD?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
disc->first_track_num = first_audio_track;
|
||||
disc->last_track_num = last_audio_track;
|
||||
|
||||
/* get offsets for all found data tracks */
|
||||
for (i = first_audio_track; i <= last_audio_track; i++) {
|
||||
track = &toc->tracks[i];
|
||||
if (track->address > 0) {
|
||||
disc->track_offsets[i] = track->address + 150;
|
||||
} else {
|
||||
/* this seems to happen on "copy-protected" discs */
|
||||
disc->track_offsets[i] = 150;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the last audio track is not the last track on the CD,
|
||||
* use the offset of the next data track as the "lead-out" offset */
|
||||
if (last_audio_track < toc->last_track_num) {
|
||||
track = &toc->tracks[last_audio_track + 1];
|
||||
disc->track_offsets[0] = track->address - XA_INTERVAL + 150;
|
||||
} else {
|
||||
/* use the regular lead-out track */
|
||||
track = &toc->tracks[0];
|
||||
disc->track_offsets[0] = track->address + 150;
|
||||
}
|
||||
|
||||
/* as long as the lead-out isn't actually bigger than
|
||||
* the position of the last track, the last track is invalid.
|
||||
* This happens on "copy-protected"/invalid discs.
|
||||
* The track is then neither a valid audio track, nor data track.
|
||||
*/
|
||||
while (disc->track_offsets[0] < disc->track_offsets[last_audio_track]) {
|
||||
disc->last_track_num = --last_audio_track;
|
||||
disc->track_offsets[last_audio_track + 1] = 0;
|
||||
track = &toc->tracks[last_audio_track + 1];
|
||||
disc->track_offsets[0] = track->address - XA_INTERVAL + 150;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* EOF */
|
@@ -1,151 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2006 Matthias Friedrich
|
||||
Copyright (C) 2000 Robert Kaye
|
||||
Copyright (C) 1999 Marc E E van Woerkom
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "discid/discid_private.h"
|
||||
#include "unix.h"
|
||||
|
||||
|
||||
int mb_disc_unix_exists(const char *device) {
|
||||
int fd;
|
||||
fd = open(device, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
/* we only check for existance, access should fail later on */
|
||||
if (errno == ENOENT) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *mb_disc_unix_find_device(char *candidates[], int num_candidates) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_candidates; i++) {
|
||||
if (mb_disc_unix_exists(candidates[i])) {
|
||||
return candidates[i];
|
||||
}
|
||||
}
|
||||
/* use the first name for the error message later on */
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
int mb_disc_unix_open(mb_disc_private *disc, const char *device) {
|
||||
int fd;
|
||||
|
||||
fd = open(device, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot open device `%s'", device);
|
||||
}
|
||||
/* fd < 0 check needs to be made by caller */
|
||||
return fd;
|
||||
}
|
||||
|
||||
int mb_disc_unix_read_toc(int fd, mb_disc_private *disc, mb_disc_toc *toc) {
|
||||
int i;
|
||||
|
||||
/* Find the numbers of the first track (usually 1) and the last track. */
|
||||
if ( !mb_disc_unix_read_toc_header(fd, toc) ) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot read table of contents");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* basic error checking */
|
||||
if ( toc->last_track_num == 0 ) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"this disc has no tracks");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the TOC entry for every track.
|
||||
*/
|
||||
for (i = toc->first_track_num; i <= toc->last_track_num; i++) {
|
||||
if ( !mb_disc_unix_read_toc_entry(fd, i, &toc->tracks[i]) ) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot read TOC entry for track %d", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if ( !mb_disc_unix_read_toc_entry(fd, 0xAA, &toc->tracks[0]) ) {
|
||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
||||
"cannot read TOC entry for lead-out");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mb_disc_unix_read(mb_disc_private *disc, const char *device,
|
||||
unsigned int features) {
|
||||
mb_disc_toc toc;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
fd = mb_disc_unix_open(disc, device);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
|
||||
if ( !mb_disc_unix_read_toc(fd, disc, &toc) ) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( !mb_disc_load_toc(disc, &toc) ) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read in the media catalog number */
|
||||
if (features & DISCID_FEATURE_MCN
|
||||
&& mb_disc_has_feature_unportable(DISCID_FEATURE_MCN)) {
|
||||
mb_disc_unix_read_mcn(fd, disc);
|
||||
}
|
||||
|
||||
/* Read the ISRC for the track */
|
||||
if (features & DISCID_FEATURE_ISRC
|
||||
&& mb_disc_has_feature_unportable(DISCID_FEATURE_ISRC)) {
|
||||
for (i = disc->first_track_num; i <= disc->last_track_num; i++) {
|
||||
mb_disc_unix_read_isrc(fd, disc, i);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* EOF */
|
@@ -1,103 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
|
||||
MusicBrainz -- The Internet music metadatabase
|
||||
|
||||
Copyright (C) 2013 Johannes Dewender
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
|
||||
#include "discid/discid_private.h"
|
||||
|
||||
|
||||
/*
|
||||
* required functions
|
||||
* ------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read the TOC header from disc
|
||||
*
|
||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc);
|
||||
|
||||
/*
|
||||
* Read a TOC entry for a certain track from disc
|
||||
*
|
||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_unix_read_toc_entry(int fd, int track_num,
|
||||
mb_disc_toc_track *track);
|
||||
|
||||
/*
|
||||
* Read the MCN from the disc
|
||||
*
|
||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
||||
*/
|
||||
LIBDISCID_INTERNAL void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc);
|
||||
|
||||
/*
|
||||
* Read the ISRC for a certain track from disc
|
||||
*
|
||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
||||
*/
|
||||
LIBDISCID_INTERNAL void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc,
|
||||
int track_num);
|
||||
|
||||
|
||||
/*
|
||||
* provided functions
|
||||
* ------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function is implemented in unix.c and can be used
|
||||
* for most platforms to implement mb_disc_read_unportable
|
||||
* after the above functions are implemented on the platform.
|
||||
* Returns 1 on success and 0 on failure.
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_unix_read(mb_disc_private *disc,
|
||||
const char *device, unsigned int features);
|
||||
|
||||
/*
|
||||
* This function is implemented in unix.c and can be used
|
||||
* after the above functions are implemented on the platform.
|
||||
* This uses mb_disc_unix_read_toc_* and adds some error checking.
|
||||
* Returns 1 on success and 0 on failure.
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_unix_read_toc(int fd, mb_disc_private *disc,
|
||||
mb_disc_toc *toc);
|
||||
|
||||
/*
|
||||
* utility function to find an existing device from a candidate list
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_unix_exists(const char *device);
|
||||
|
||||
/*
|
||||
* utility function to find an existing device from a candidate list
|
||||
*/
|
||||
LIBDISCID_INTERNAL char *mb_disc_unix_find_device(char *candidates[],
|
||||
int num_candidates);
|
||||
|
||||
/*
|
||||
* utility function to try opening the device with open()
|
||||
* returns a non-negative file descriptor on success.
|
||||
* On failure a negative integer is returned and error_msg filled
|
||||
* with an appropriate string.
|
||||
*/
|
||||
LIBDISCID_INTERNAL int mb_disc_unix_open(mb_disc_private *disc,
|
||||
const char *device);
|