307 lines
6.2 KiB
C
307 lines
6.2 KiB
C
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* (C) copyright Fraunhofer - IIS (1998)
|
||
|
* All Rights Reserved
|
||
|
*
|
||
|
* filename: giofile.h
|
||
|
* project : MPEG Decoder
|
||
|
* author : Martin Sieler
|
||
|
* date : 1998-02-11
|
||
|
* contents/description: HEADER - file I/O class for MPEG Decoder
|
||
|
*
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
|
||
|
#ifndef _GIOFILE_H
|
||
|
#define _GIOFILE_H
|
||
|
|
||
|
/* ------------------------ includes --------------------------------------*/
|
||
|
#include <windows.h>
|
||
|
|
||
|
#include "CVbriHeader.h"
|
||
|
#include "jnetlib/jnetlib.h"
|
||
|
|
||
|
#include "../vlb/dataio.h"
|
||
|
#include "ID3v2.h"
|
||
|
#include "LAMEInfo.h"
|
||
|
#include "../nu/RingBuffer.h"
|
||
|
#include "../apev2/tag.h"
|
||
|
#include "ifc_mpeg_stream_reader.h"
|
||
|
|
||
|
/*-------------------------- defines --------------------------------------*/
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
|
||
|
class CGioFile : public DataIOControl, public ifc_mpeg_stream_reader
|
||
|
{
|
||
|
public:
|
||
|
CGioFile();
|
||
|
virtual ~CGioFile();
|
||
|
|
||
|
int Open(const wchar_t *pszName, int maxbufsizek);
|
||
|
int Close();
|
||
|
int Read(void *pBuffer, int cbToRead, int *pcbRead);
|
||
|
int Peek(void *pBuffer, int cbToRead, int *pcbRead);
|
||
|
|
||
|
//dataiocontrol interface
|
||
|
int IO(void *buf, int size, int count)
|
||
|
{
|
||
|
int l=0;
|
||
|
Read(buf,count,&l);
|
||
|
return l;
|
||
|
}
|
||
|
int Seek(long offset, int origin)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
//int Close() { return 0; }
|
||
|
int EndOf(void)
|
||
|
{
|
||
|
return IsEof();
|
||
|
}
|
||
|
int DICGetLastError()
|
||
|
{
|
||
|
return DATA_IO_ERROR_NONE;
|
||
|
}
|
||
|
int DICGetDirection()
|
||
|
{
|
||
|
return DATA_IO_READ;
|
||
|
}
|
||
|
|
||
|
unsigned int GetAvgVBRBitrate(void)
|
||
|
{
|
||
|
if (m_vbr_ms && m_vbr_frames)
|
||
|
{
|
||
|
if (m_vbr_bytes && encodingMethod != ENCODING_METHOD_CBR)
|
||
|
return (unsigned int)(m_vbr_bytes * 8 / m_vbr_ms);
|
||
|
else
|
||
|
return (unsigned int)(mpeg_length * 8 / m_vbr_ms);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
bool IsEof() const;
|
||
|
bool lengthVerified;
|
||
|
bool isSeekReset()
|
||
|
{
|
||
|
|
||
|
if (m_is_stream && m_seek_reset && m_is_stream_seek)
|
||
|
{
|
||
|
m_seek_reset = false;
|
||
|
m_is_stream_seek = false;
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool IsStreamSeekable()
|
||
|
{
|
||
|
return m_is_stream_seekable;
|
||
|
}
|
||
|
|
||
|
int GetHeaderOffset();
|
||
|
|
||
|
int PercentAvailable()
|
||
|
{
|
||
|
if (!m_is_stream) return 0;
|
||
|
if (!recvbuffersize) return 0;
|
||
|
if (!m_connection) return 0;
|
||
|
if (constate != 5) return 0;
|
||
|
uint64_t bytes_100 = jnl_connection_receive_bytes_available(m_connection)*100;
|
||
|
bytes_100 /= recvbuffersize;
|
||
|
return (int)bytes_100;
|
||
|
}
|
||
|
|
||
|
int RunStream()
|
||
|
{
|
||
|
if (m_is_stream && m_connection)
|
||
|
{
|
||
|
if (constate != 5) Read(NULL,0,NULL);
|
||
|
else jnl_connection_run(m_connection, -1, -1, NULL, NULL);
|
||
|
int p=jnl_connection_get_state(m_connection);
|
||
|
if (p==JNL_CONNECTION_STATE_ERROR||
|
||
|
p==JNL_CONNECTION_STATE_CLOSED)
|
||
|
return 2;
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
int IsStream()
|
||
|
{
|
||
|
return m_is_stream;
|
||
|
}
|
||
|
void GetStreamInfo(wchar_t *, size_t len);
|
||
|
|
||
|
DWORD GetContentLength(void) const;
|
||
|
DWORD GetCurrentPosition(void) const;
|
||
|
void SetCurrentPosition(long dwPos, int How);
|
||
|
|
||
|
enum { GIO_FILE_BEGIN, GIO_FILE_CURRENT, GIO_FILE_END };
|
||
|
|
||
|
uint64_t mpeg_length; /* length of valid audio data */
|
||
|
uint64_t mpeg_position; /* starting position of first valid decodable non-header MPEG frame */
|
||
|
uint64_t file_position; /* position within the MPEG data that we've read so far */
|
||
|
|
||
|
uint64_t m_vbr_bytes;
|
||
|
int m_vbr_frames, m_vbr_ms;
|
||
|
int encodingMethod;
|
||
|
uint64_t m_vbr_samples;
|
||
|
int prepad, postpad;
|
||
|
void Seek(int posms, int br);
|
||
|
bool IsSeekable();
|
||
|
|
||
|
unsigned char id3v1_data[128];
|
||
|
|
||
|
char stream_url[256];
|
||
|
char stream_name[256];
|
||
|
char stream_genre[256];
|
||
|
char stream_current_title[256];
|
||
|
|
||
|
char *m_content_type;
|
||
|
int uvox_last_message;
|
||
|
char *uvox_3901;
|
||
|
char *uvox_3902;
|
||
|
|
||
|
typedef struct {
|
||
|
char *uvox_stream_artwork;
|
||
|
int uvox_stream_artwork_len;
|
||
|
int uvox_stream_artwork_type;
|
||
|
char *uvox_playing_artwork;
|
||
|
int uvox_playing_artwork_len;
|
||
|
int uvox_playing_artwork_type;
|
||
|
} UVOX_ARTWORK;
|
||
|
UVOX_ARTWORK uvox_artwork;
|
||
|
|
||
|
ID3v2 info;
|
||
|
float GetGain();
|
||
|
unsigned char m_vbr_toc[100];
|
||
|
int m_vbr_frame_len;
|
||
|
int m_vbr_flag;
|
||
|
CVbriHeader *m_vbr_hdr;
|
||
|
|
||
|
FILETIME last_write_time;
|
||
|
|
||
|
void *GetID3v1()
|
||
|
{
|
||
|
if (m_id3v1_len == 128)
|
||
|
return id3v1_data;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void *GetID3v2(uint32_t *len)
|
||
|
{
|
||
|
if (stream_id3v2_buf)
|
||
|
{
|
||
|
*len = stream_id3v2_read;
|
||
|
return stream_id3v2_buf;
|
||
|
}
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void *GetLyrics3(uint32_t *len)
|
||
|
{
|
||
|
if (lyrics3_data)
|
||
|
{
|
||
|
*len = lyrics3_size;
|
||
|
return lyrics3_data;
|
||
|
}
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void *GetAPEv2(uint32_t *len)
|
||
|
{
|
||
|
if (apev2_data)
|
||
|
{
|
||
|
*len = m_apev2_len;
|
||
|
return apev2_data;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
void ReadiTunesGaps();
|
||
|
private:
|
||
|
/* ID3v2 */
|
||
|
int m_id3v1_len;
|
||
|
|
||
|
/* ID3v2 */
|
||
|
uint32_t stream_id3v2_read;
|
||
|
char *stream_id3v2_buf;
|
||
|
int m_id3v2_len;
|
||
|
|
||
|
/* Lyrics3 */
|
||
|
uint32_t lyrics3_size;
|
||
|
char *lyrics3_data;
|
||
|
|
||
|
/* APEv2 */
|
||
|
uint32_t m_apev2_len;
|
||
|
char *apev2_data;
|
||
|
APEv2::Tag apev2;
|
||
|
|
||
|
int m_is_stream;
|
||
|
jnl_dns_t m_dns;
|
||
|
jnl_connection_t m_connection;
|
||
|
char last_full_url[4096];
|
||
|
int is_stream_seek;
|
||
|
char *host;
|
||
|
char *proxy_host;
|
||
|
char *req;
|
||
|
unsigned short port;
|
||
|
char *lpinfo;
|
||
|
char *proxy_lp;
|
||
|
char *request;
|
||
|
int constate;
|
||
|
char save_filename[256];
|
||
|
char server_name[128];
|
||
|
int recvbuffersize;
|
||
|
|
||
|
int64_t stream_bytes_read;
|
||
|
int64_t stream_metabytes_read;
|
||
|
unsigned int timeout_start;
|
||
|
char force_lpinfo[256];
|
||
|
unsigned char *m_full_buffer;
|
||
|
int is_uvox;
|
||
|
int uvox_stream_data_len;
|
||
|
int uvox_message_cnt, uvox_desyncs;
|
||
|
int uvox_sid,uvox_maxbr, uvox_avgbr,uvox_maxmsg;
|
||
|
|
||
|
unsigned char *uvox_stream_data;
|
||
|
|
||
|
char *uvox_meta[2][32];
|
||
|
int meta_interval,meta_pos;
|
||
|
uint64_t m_full_buffer_pos/*,m_full_buffer_len*/;
|
||
|
char stream_title_save[580];
|
||
|
char last_title_sent[256];
|
||
|
|
||
|
RingBuffer peekBuffer;
|
||
|
//unsigned char m_peekbuf[8192];
|
||
|
//int m_peekbuf_used;
|
||
|
bool no_peek_hack;
|
||
|
|
||
|
int doConnect(const char *str, int start_offset);
|
||
|
void processMetaData(char *data, int lent, int msgId = 0);
|
||
|
|
||
|
int m_redircnt;
|
||
|
int m_auth_tries;
|
||
|
|
||
|
HANDLE hFile;
|
||
|
bool fEof;
|
||
|
|
||
|
|
||
|
char dlg_realm[256];
|
||
|
static INT_PTR CALLBACK httpDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
||
|
int m_http_response;
|
||
|
bool m_seek_reset;
|
||
|
bool m_is_stream_seek;
|
||
|
bool m_is_stream_seekable;
|
||
|
bool m_useaproxy;
|
||
|
RECVS_DISPATCH;
|
||
|
};
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
#endif
|