I am trying to create a Graphical User Interface for a Vorbis Player under MS Visual C++ 6.0 I was initially trting to use the code from decoder_example.c but I keep getting linker errors. I have set up my project as told to by James Boer on this mailing list. This is as follows: This document was prepared from an email received from James Boer on the Ogg Vorbis mailing list. It gives a walkthrough on how to compile an example file supplied with the Ogg Vorbis source code. The method will be needed when code is developed which relies on the Ogg Vorbis source code. 1. The files extracted from the vorbis-sdk-1.0rc3.zip <http://www.vorbis.com/files/rc3/windows/vorbis-sdk-1.0rc3.zip> should be stored in a known location so that Visual C++ can locate the files. For the purposes of this document it is assumed that they are installed at c:\vorbis_sdk 2. To specify the locations of these files in Visual C++ goto Tools -> Options and select the directories tab. Select Include Files from the Show directories for: drop down menu. Add an entry which points to c:\vorbis_sdk\include. Change to Library Files and add an entry which points to c:\vorbis_sdk\lib. 3. Create a new Visual C++ Project and workspace. Goto File->New and select Win32 Console Application. Give this an appropriate name and location. When prompted ask for an Empty Project. 4. Copy the file vorbisfile_example.c to the new project directory. Select Project->Add to Project->Add Files.... Select vorbisfile_example.c from the list. 5. The program must now be linked to the vorbis libraries. The Library types are given below: Ogg.lib Base library used for ogg projects Vorbis.lib Low-level Vorbis decoding library Vorbisenc.lib Low-level Vorbis encoding library Vorbisfile.lib High-level Vorbis file reading library The static versions of the libraries can be used instead of the dll's. This is achieved by adding _static to the name of the library file. The debug versions have a _d appended to their name. To add the libraries to the project:Select Project->Settings. Click the Link tab. Under the Object/library modules section append ogg_d.lib, vorbis_d.lib and vorbisfile_d.lib to the end of the list. In the Settings For: dropdown menu select Win32 Release. In the same way as previously add ogg.lib, vorbis.lib and vorbisfile.lib to the end of the list. Add _static before .lib for Release version if using static libraries. If compilation with static libraries is required then the following should also be carried out. Select Project->Settings and select the C/C++ tab. Select Code Generation from the category list. From the Use run-time library: dropdown list select Debug Multithreaded DLL for the Debug Project, and Multithreaded DLL for Release. 6. Copy the Vorbis dll's to the project directory. This is not necessary if the project was compiled with static libraries. 7. Now Build the project. <p>For my GUI I created a MFCAppWizard(exe) Project. I then created some buttons. Initially I just want te press of a button to start the decoder_example code. My code looks like this: <p><p>// GUIDlg.cpp : implementation file // #include "stdafx.h" #include "GUI.h" #include "GUIDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif <p>//************************************************************************** ** //Ogg Vorbis Stuff #include <stdio.h> #include <stdlib.h> #include <math.h> #include <vorbis/codec.h> /* NB vorbisfile.h not included - GK */ #ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */ #include <io.h> #include <fcntl.h> #endif #if defined(macintosh) && defined(__MWERKS__) #include <console.h> /* CodeWarrior's Mac "command-line" support */ #endif ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */ int convsize=4096; <p>//************************************************************************** * <p><p>//////////////////////////////////////////////////////////////////////////// / // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() //////////////////////////////////////////////////////////////////////////// / // CGUIDlg dialog CGUIDlg::CGUIDlg(CWnd* pParent /*=NULL*/) : CDialog(CGUIDlg::IDD, pParent) { //{{AFX_DATA_INIT(CGUIDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CGUIDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CGUIDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CGUIDlg, CDialog) //{{AFX_MSG_MAP(CGUIDlg) ON_WM_SYSCOMMAND() ON_WM_DESTROY() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_PLAY, OnPlay) //}}AFX_MSG_MAP END_MESSAGE_MAP() //////////////////////////////////////////////////////////////////////////// / // CGUIDlg message handlers BOOL CGUIDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } void CGUIDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } void CGUIDlg::OnDestroy() { WinHelp(0L, HELP_QUIT); CDialog::OnDestroy(); } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CGUIDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CGUIDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CGUIDlg::OnPlay() { ogg_sync_state oy; /* sync and verify incoming physical bitstream */ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ vorbis_comment vc; /* struct that stores all the bitstream user comments */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ char *buffer; int bytes; /* Read from file : GK */ FILE * myFile = fopen("h:/Project/Downloads/Ogg/keoki_passiton.ogg","rb"); FILE * outputFile = fopen("h:/Project/Visual C++/output.txt", "w"); fprintf(outputFile, "File read OK.\n"); /* end modification : GK */ #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ /* Beware the evil ifdef. We avoid these where we can, but this one we cannot. Don't add any more, you'll probably go to hell if you do. */ _setmode( _fileno( stdin ), _O_BINARY ); _setmode( _fileno( stdout ), _O_BINARY ); #endif #if defined(macintosh) && defined(__MWERKS__) { int argc; char **argv; argc=ccommand(&argv); /* get a "command line" from the Mac user */ /* this also lets the user set stdin and stdout */ } #endif /********** Decode setup ************/ ogg_sync_init(&oy); /* Now we can read pages */ while(1){ /* we repeat if the bitstream is chained */ int eos=0; int i; /* grab some data at the head of the stream. We want the first page (which is guaranteed to be small and only contain the Vorbis stream initial header) We need the first page to get the stream serialno. */ /* submit a 4k block to libvorbis' Ogg layer */ buffer=ogg_sync_buffer(&oy,4096); /* changed from stdin to myFile in next line - GK*/ bytes=fread(buffer,1,4096,myFile); /* added the following line - GK */ printf("%d bytes read successfully\n",bytes); ogg_sync_wrote(&oy,bytes); /* Get the first page. */ if(ogg_sync_pageout(&oy,&og)!=1){ /* have we simply run out of data? If so, we're done. */ if(bytes<4096)break; /* error case. Must not be Vorbis data */ fprintf(outputFile,"Input does not appear to be an Ogg bitstream.\n"); exit(1); } /* Get the serial number and set up the rest of decode. */ /* serialno first; use it to set up a logical stream */ ogg_stream_init(&os,ogg_page_serialno(&og)); /* extract the initial header from the first page and verify that the Ogg bitstream is in fact Vorbis data */ /* I handle the initial header first instead of just having the code read all three Vorbis headers at once because reading the initial header is an easy way to identify a Vorbis bitstream and it's useful to see that functionality seperated out. */ vorbis_info_init(&vi); vorbis_comment_init(&vc); if(ogg_stream_pagein(&os,&og)<0){ /* error; stream version mismatch perhaps */ fprintf(outputFile,"Error reading first page of Ogg bitstream data.\n"); exit(1); } if(ogg_stream_packetout(&os,&op)!=1){ /* no page? must not be vorbis */ fprintf(outputFile,"Error reading initial header packet.\n"); exit(1); } if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ /* error case; not a vorbis header */ fprintf(outputFile,"This Ogg bitstream does not contain Vorbis " "audio data.\n"); exit(1); } printf("We're sure we're Vorbis.\n"); /* At this point, we're sure we're Vorbis. We've set up the logical (Ogg) bitstream decoder. Get the comment and codebook headers and set up the Vorbis decoder */ /* The next two packets in order are the comment and codebook headers. They're likely large and may span multiple pages. Thus we reead and submit data until we get our two pacakets, watching that no pages are missing. If a page is missing, error out; losing a header page is the only place where missing data is fatal. */ i=0; while(i<2){ while(i<2){ int result=ogg_sync_pageout(&oy,&og); if(result==0)break; /* Need more data */ /* Don't complain about missing or corrupt data yet. We'll catch it at the packet output phase */ if(result==1){ ogg_stream_pagein(&os,&og); /* we can ignore any errors here as they'll also become apparent at packetout */ while(i<2){ result=ogg_stream_packetout(&os,&op); if(result==0)break; if(result<0){ /* Uh oh; data at some point was corrupted or missing! We can't tolerate that in a header. Die. */ fprintf(outputFile,"Corrupt secondary header. Exiting.\n"); exit(1); } vorbis_synthesis_headerin(&vi,&vc,&op); i++; } } } /* no harm in not checking before adding more */ buffer=ogg_sync_buffer(&oy,4096); /* changed from stdin to myFile in next line - GK */ bytes=fread(buffer,1,4096,myFile); if(bytes==0 && i<2){ fprintf(outputFile,"End of file before finding all Vorbis headers!\n"); exit(1); } ogg_sync_wrote(&oy,bytes); } /* Throw the comments plus a few lines about the bitstream we're decoding */ { char **ptr=vc.user_comments; while(*ptr){ fprintf(outputFile,"%s\n",*ptr); ++ptr; } fprintf(outputFile,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate); fprintf(outputFile,"Encoded by: %s\n\n",vc.vendor); } convsize=4096/vi.channels; /* OK, got and parsed all three headers. Initialize the Vorbis packet->PCM decoder. */ vorbis_synthesis_init(&vd,&vi); /* central decode state */ vorbis_block_init(&vd,&vb); /* local state for most of the decode so multiple block decodes can proceed in parallel. We could init multiple vorbis_block structures for vd here */ /* The rest is just a straight decode loop until end of stream */ while(!eos){ while(!eos){ int result=ogg_sync_pageout(&oy,&og); if(result==0)break; /* need more data */ if(result<0){ /* missing or corrupt data at this page position */ fprintf(outputFile,"Corrupt or missing data in bitstream; " "continuing...\n"); }else{ ogg_stream_pagein(&os,&og); /* can safely ignore errors at this point */ while(1){ result=ogg_stream_packetout(&os,&op); if(result==0)break; /* need more data */ if(result<0){ /* missing or corrupt data at this page position */ /* no reason to complain; already complained above */ }else{ /* we have a packet. Decode it */ float **pcm; int samples; if(vorbis_synthesis(&vb,&op)==0) /* test for success! */ vorbis_synthesis_blockin(&vd,&vb); /* **pcm is a multichannel float vector. In stereo, for example, pcm[0] is left, and pcm[1] is right. samples is the size of each channel. Convert the float values (-1.<=range<=1.) to whatever PCM format and write it out */ while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){ int j; int clipflag=0; int bout=(samples<convsize?samples:convsize); /* convert floats to 16 bit signed ints (host order) and interleave */ for(i=0;i<vi.channels;i++){ ogg_int16_t *ptr=convbuffer+i; float *mono=pcm[i]; for(j=0;j<bout;j++){ #if 1 int val=mono[j]*32767.f; #else /* optional dither */ int val=mono[j]*32767.f+drand48()-0.5f; #endif /* might as well guard against clipping */ if(val>32767){ val=32767; clipflag=1; } if(val<-32768){ val=-32768; clipflag=1; } *ptr=val; ptr+=vi.channels; } } if(clipflag) fprintf(outputFile,"Clipping in frame %ld\n",(long)(vd.sequence)); /* commented out next line - GK */ // fwrite(convbuffer,2*vi.channels,bout,stdout); vorbis_synthesis_read(&vd,bout); /* tell libvorbis how many samples we actually consumed */ } } } if(ogg_page_eos(&og))eos=1; } } if(!eos){ buffer=ogg_sync_buffer(&oy,4096); /* changed from stdin to myFile in next line - GK */ bytes=fread(buffer,1,4096,myFile); ogg_sync_wrote(&oy,bytes); if(bytes==0)eos=1; } } /* clean up this logical bitstream; before exit we see if we're followed by another [chained] */ ogg_stream_clear(&os); /* ogg_page and ogg_packet structs always point to storage in libvorbis. They're never freed or manipulated directly */ vorbis_block_clear(&vb); vorbis_dsp_clear(&vd); vorbis_comment_clear(&vc); vorbis_info_clear(&vi); /* must be called last */ } /* OK, clean up the framer */ ogg_sync_clear(&oy); fprintf(outputFile,"Done.\n"); // TODO: Add your control notification handler code here } <p>I changed the input from stdin to a file. When I build the project I get --------------------Configuration: GUI - Win32 Debug-------------------- Linking... LINK : fatal error LNK1104: cannot open file "ogg_d.lib" Error executing link.exe. GUI.exe - 1 error(s), 0 warning(s) Can anybody explain why this is? Thanks in advance Paul <p><p><p><p><p><p>--- >8 ---- List archives: http://www.xiph.org/archives/ Ogg project homepage: http://www.xiph.org/ogg/ To unsubscribe from this list, send a message to 'vorbis-dev-request@xiph.org' containing only the word 'unsubscribe' in the body. No subject is needed. Unsubscribe messages sent to the list will be ignored/filtered.