2 * Copyright (C) Joey Parrish
4 * This file is part of MPlayer.
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * MPlayer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * If you have a tivo with the vstream server installed, (and most tivo
23 * hackers do,) then you can connect to it and stream ty files using
24 * this module. The url syntax is tivo://host/fsid or tivo://host/list
25 * to list the available recordings and their fsid's.
26 * This module depends on libvstream-client, which is available from
27 * http://armory.nicewarrior.org/projects/vstream-client .
34 #include <sys/types.h>
52 #include <vstream-client.h>
54 void vstream_error(const char *format
, ...) {
58 vsnprintf(buf
, 1024, format
, va
);
60 mp_msg(MSGT_STREAM
, MSGL_ERR
, buf
);
63 static struct stream_priv_s
{
66 } stream_priv_dflts
= {
71 #define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
73 static const m_option_t stream_opts_fields
[] = {
74 {"hostname", ST_OFF(host
), CONF_TYPE_STRING
, 0, 0 ,0, NULL
},
75 {"filename", ST_OFF(fsid
), CONF_TYPE_STRING
, 0, 0 ,0, NULL
},
76 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
79 static const struct m_struct_st stream_opts
= {
81 sizeof(struct stream_priv_s
),
86 static int fill_buffer(stream_t
*s
, char* buffer
, int max_len
){
87 struct stream_priv_s
* p
= (struct stream_priv_s
*)s
->priv
;
88 int len
= vstream_load_chunk(p
->fsid
, buffer
, max_len
, s
->pos
);
89 if (len
<= 0) return 0;
93 static int seek(stream_t
*s
,off_t newpos
) {
98 static int control(struct stream_st
*s
,int cmd
,void* arg
) {
99 return STREAM_UNSUPPORTED
;
102 static void close_s(struct stream_st
*s
) {
105 static int open_s(stream_t
*stream
, int mode
, void* opts
, int* file_format
) {
107 struct stream_priv_s
* p
= (struct stream_priv_s
*)opts
;
109 if(mode
!= STREAM_READ
)
110 return STREAM_UNSUPPORTED
;
113 mp_msg(MSGT_OPEN
, MSGL_ERR
, "We need a host name (ex: tivo://hostname/fsid)\n");
114 m_struct_free(&stream_opts
, opts
);
118 if(!p
->fsid
|| strlen(p
->fsid
) == 0) {
119 mp_msg(MSGT_OPEN
, MSGL_ERR
, "We need an fsid (ex: tivo://hostname/fsid)\n");
120 m_struct_free(&stream_opts
, opts
);
124 f
= connect2Server(p
->host
, VSERVER_PORT
, 1);
127 mp_msg(MSGT_OPEN
, MSGL_ERR
, "Connection to %s failed\n", p
->host
);
128 m_struct_free(&stream_opts
, opts
);
133 vstream_set_socket_fd(f
);
135 if (!strcmp(p
->fsid
, "list")) {
136 vstream_list_streams(0);
138 } else if (!strcmp(p
->fsid
, "llist")) {
139 vstream_list_streams(1);
143 if (vstream_start()) {
144 mp_msg(MSGT_OPEN
, MSGL_ERR
, "Cryptic internal error #1\n");
145 m_struct_free(&stream_opts
, opts
);
148 if (vstream_startstream(p
->fsid
)) {
149 mp_msg(MSGT_OPEN
, MSGL_ERR
, "Cryptic internal error #2\n");
150 m_struct_free(&stream_opts
, opts
);
154 stream
->start_pos
= 0;
155 stream
->end_pos
= vstream_streamsize();
156 mp_msg(MSGT_OPEN
, MSGL_DBG2
, "Tivo stream size is %d\n", stream
->end_pos
);
159 stream
->fill_buffer
= fill_buffer
;
160 stream
->control
= control
;
162 stream
->close
= close_s
;
163 stream
->type
= STREAMTYPE_VSTREAM
;
168 const stream_info_t stream_info_vstream
= {
176 1 // Url is an option string