123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 |
- #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;
- }
|