| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
#ifdef HAVE_CONFIG_H |
|---|
| 29 |
# include "config.h" |
|---|
| 30 |
#endif |
|---|
| 31 |
|
|---|
| 32 |
#include <vlc_common.h> |
|---|
| 33 |
#include <vlc_plugin.h> |
|---|
| 34 |
|
|---|
| 35 |
#include <errno.h> |
|---|
| 36 |
|
|---|
| 37 |
#include <vlc_access.h> |
|---|
| 38 |
#include <vlc_charset.h> |
|---|
| 39 |
#include <vlc_input.h> |
|---|
| 40 |
|
|---|
| 41 |
#include <unistd.h> |
|---|
| 42 |
|
|---|
| 43 |
#ifdef WIN32 |
|---|
| 44 |
# include <direct.h> |
|---|
| 45 |
#endif |
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
static int Open ( vlc_object_t * ); |
|---|
| 51 |
static void Close( vlc_object_t * ); |
|---|
| 52 |
|
|---|
| 53 |
#define GRANULARITY_TEXT N_("Timeshift granularity") |
|---|
| 54 |
|
|---|
| 55 |
#define GRANULARITY_LONGTEXT N_( "This is the size of the temporary files " \ |
|---|
| 56 |
"that will be used to store the timeshifted streams." ) |
|---|
| 57 |
#define DIR_TEXT N_("Timeshift directory") |
|---|
| 58 |
#define DIR_LONGTEXT N_( "Directory used to store the timeshift temporary " \ |
|---|
| 59 |
"files." ) |
|---|
| 60 |
#define FORCE_TEXT N_("Force use of the timeshift module") |
|---|
| 61 |
#define FORCE_LONGTEXT N_("Force use of the timeshift module even if the " \ |
|---|
| 62 |
"access declares that it can control pace or pause." ) |
|---|
| 63 |
|
|---|
| 64 |
vlc_module_begin(); |
|---|
| 65 |
set_shortname( N_("Timeshift") ); |
|---|
| 66 |
set_description( N_("Timeshift") ); |
|---|
| 67 |
set_category( CAT_INPUT ); |
|---|
| 68 |
set_subcategory( SUBCAT_INPUT_ACCESS_FILTER ); |
|---|
| 69 |
set_capability( "access_filter", 0 ); |
|---|
| 70 |
add_shortcut( "timeshift" ); |
|---|
| 71 |
set_callbacks( Open, Close ); |
|---|
| 72 |
|
|---|
| 73 |
add_integer( "timeshift-granularity", 50, NULL, GRANULARITY_TEXT, |
|---|
| 74 |
GRANULARITY_LONGTEXT, true ); |
|---|
| 75 |
add_directory( "timeshift-dir", 0, 0, DIR_TEXT, DIR_LONGTEXT, false ); |
|---|
| 76 |
add_bool( "timeshift-force", false, NULL, FORCE_TEXT, FORCE_LONGTEXT, |
|---|
| 77 |
false ); |
|---|
| 78 |
vlc_module_end(); |
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
static int Seek( access_t *, int64_t ); |
|---|
| 85 |
static block_t *Block ( access_t *p_access ); |
|---|
| 86 |
static int Control( access_t *, int i_query, va_list args ); |
|---|
| 87 |
static void* Thread ( vlc_object_t *p_this ); |
|---|
| 88 |
static int WriteBlockToFile( access_t *p_access, block_t *p_block ); |
|---|
| 89 |
static block_t *ReadBlockFromFile( access_t *p_access ); |
|---|
| 90 |
static char *GetTmpFilePath( access_t *p_access ); |
|---|
| 91 |
|
|---|
| 92 |
#define TIMESHIFT_FIFO_MAX (10*1024*1024) |
|---|
| 93 |
#define TIMESHIFT_FIFO_MIN (TIMESHIFT_FIFO_MAX/4) |
|---|
| 94 |
#define TMP_FILE_MAX 256 |
|---|
| 95 |
|
|---|
| 96 |
typedef struct ts_entry_t |
|---|
| 97 |
{ |
|---|
| 98 |
FILE *file; |
|---|
| 99 |
struct ts_entry_t *p_next; |
|---|
| 100 |
|
|---|
| 101 |
} ts_entry_t; |
|---|
| 102 |
|
|---|
| 103 |
struct access_sys_t |
|---|
| 104 |
{ |
|---|
| 105 |
block_fifo_t *p_fifo; |
|---|
| 106 |
|
|---|
| 107 |
unsigned i_files; |
|---|
| 108 |
unsigned i_file_size; |
|---|
| 109 |
unsigned i_write_size; |
|---|
| 110 |
|
|---|
| 111 |
ts_entry_t *p_read_list; |
|---|
| 112 |
ts_entry_t **pp_read_last; |
|---|
| 113 |
ts_entry_t *p_write_list; |
|---|
| 114 |
ts_entry_t **pp_write_last; |
|---|
| 115 |
|
|---|
| 116 |
char *psz_filename_base; |
|---|
| 117 |
char *psz_filename; |
|---|
| 118 |
|
|---|
| 119 |
int64_t i_data; |
|---|
| 120 |
}; |
|---|
| 121 |
|
|---|
| 122 |
|
|---|
| 123 |
|
|---|
| 124 |
|
|---|
| 125 |
static int Open( vlc_object_t *p_this ) |
|---|
| 126 |
{ |
|---|
| 127 |
access_t *p_access = (access_t*)p_this; |
|---|
| 128 |
access_t *p_src = p_access->p_source; |
|---|
| 129 |
access_sys_t *p_sys; |
|---|
| 130 |
bool b_bool; |
|---|
| 131 |
|
|---|
| 132 |
var_Create( p_access, "timeshift-force", VLC_VAR_BOOL|VLC_VAR_DOINHERIT ); |
|---|
| 133 |
if( var_GetBool( p_access, "timeshift-force" ) ) |
|---|
| 134 |
{ |
|---|
| 135 |
msg_Dbg( p_access, "Forcing use of timeshift even if access can control pace or pause" ); |
|---|
| 136 |
} |
|---|
| 137 |
else |
|---|
| 138 |
{ |
|---|
| 139 |
|
|---|
| 140 |
if( access_Control( p_src, ACCESS_CAN_CONTROL_PACE, &b_bool ) || |
|---|
| 141 |
b_bool ) |
|---|
| 142 |
{ |
|---|
| 143 |
msg_Dbg( p_src, "ACCESS_CAN_CONTROL_PACE: timeshift useless" ); |
|---|
| 144 |
return VLC_EGENERIC; |
|---|
| 145 |
} |
|---|
| 146 |
|
|---|
| 147 |
if( access_Control( p_src, ACCESS_CAN_PAUSE, &b_bool ) || b_bool ) |
|---|
| 148 |
{ |
|---|
| 149 |
msg_Dbg( p_src, "ACCESS_CAN_PAUSE: timeshift useless" ); |
|---|
| 150 |
return VLC_EGENERIC; |
|---|
| 151 |
} |
|---|
| 152 |
} |
|---|
| 153 |
|
|---|
| 154 |
|
|---|
| 155 |
p_access->pf_read = NULL; |
|---|
| 156 |
p_access->pf_block = Block; |
|---|
| 157 |
p_access->pf_seek = Seek; |
|---|
| 158 |
p_access->pf_control = Control; |
|---|
| 159 |
p_access->info = p_src->info; |
|---|
| 160 |
|
|---|
| 161 |
p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) ); |
|---|
| 162 |
if( !p_sys ) |
|---|
| 163 |
return VLC_ENOMEM; |
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
p_sys->p_fifo = block_FifoNew(); |
|---|
| 167 |
p_sys->i_write_size = 0; |
|---|
| 168 |
p_sys->i_files = 0; |
|---|
| 169 |
p_sys->i_data = 0; |
|---|
| 170 |
|
|---|
| 171 |
p_sys->p_read_list = NULL; |
|---|
| 172 |
p_sys->pp_read_last = &p_sys->p_read_list; |
|---|
| 173 |
p_sys->p_write_list = NULL; |
|---|
| 174 |
p_sys->pp_write_last = &p_sys->p_write_list; |
|---|
| 175 |
|
|---|
| 176 |
var_Create( p_access, "timeshift-dir", |
|---|
| 177 |
VLC_VAR_DIRECTORY | VLC_VAR_DOINHERIT ); |
|---|
| 178 |
var_Create( p_access, "timeshift-granularity", |
|---|
| 179 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 180 |
p_sys->i_file_size = var_GetInteger( p_access, "timeshift-granularity" ); |
|---|
| 181 |
if( p_sys->i_file_size < 1 ) p_sys->i_file_size = 1; |
|---|
| 182 |
p_sys->i_file_size *= 1024 * 1024; |
|---|
| 183 |
|
|---|
| 184 |
p_sys->psz_filename_base = GetTmpFilePath( p_access ); |
|---|
| 185 |
p_sys->psz_filename = malloc( strlen( p_sys->psz_filename_base ) + 1000 ); |
|---|
| 186 |
|
|---|
| 187 |
if( vlc_thread_create( p_access, "timeshift thread", Thread, |
|---|
| 188 |
VLC_THREAD_PRIORITY_LOW, false ) ) |
|---|
| 189 |
{ |
|---|
| 190 |
Close( p_this ); |
|---|
| 191 |
msg_Err( p_access, "cannot spawn timeshift access thread" ); |
|---|
| 192 |
return VLC_EGENERIC; |
|---|
| 193 |
} |
|---|
| 194 |
|
|---|
| 195 |
return VLC_SUCCESS; |
|---|
| 196 |
} |
|---|
| 197 |
|
|---|
| 198 |
|
|---|
| 199 |
|
|---|
| 200 |
|
|---|
| 201 |
static void Close( vlc_object_t *p_this ) |
|---|
| 202 |
{ |
|---|
| 203 |
access_t *p_access = (access_t*)p_this; |
|---|
| 204 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 205 |
ts_entry_t *p_entry; |
|---|
| 206 |
unsigned i; |
|---|
| 207 |
|
|---|
| 208 |
msg_Dbg( p_access, "timeshift close called" ); |
|---|
| 209 |
vlc_thread_join( p_access ); |
|---|
| 210 |
|
|---|
| 211 |
for( p_entry = p_sys->p_write_list; p_entry; ) |
|---|
| 212 |
{ |
|---|
| 213 |
ts_entry_t *p_next = p_entry->p_next; |
|---|
| 214 |
fclose( p_entry->file ); |
|---|
| 215 |
free( p_entry ); |
|---|
| 216 |
p_entry = p_next; |
|---|
| 217 |
} |
|---|
| 218 |
for( p_entry = p_sys->p_read_list; p_entry; ) |
|---|
| 219 |
{ |
|---|
| 220 |
ts_entry_t *p_next = p_entry->p_next; |
|---|
| 221 |
fclose( p_entry->file ); |
|---|
| 222 |
free( p_entry ); |
|---|
| 223 |
p_entry = p_next; |
|---|
| 224 |
} |
|---|
| 225 |
for( i = 0; i < p_sys->i_files; i++ ) |
|---|
| 226 |
{ |
|---|
| 227 |
sprintf( p_sys->psz_filename, "%s%i.dat", |
|---|
| 228 |
p_sys->psz_filename_base, i ); |
|---|
| 229 |
unlink( p_sys->psz_filename ); |
|---|
| 230 |
} |
|---|
| 231 |
|
|---|
| 232 |
free( p_sys->psz_filename ); |
|---|
| 233 |
free( p_sys->psz_filename_base ); |
|---|
| 234 |
block_FifoRelease( p_sys->p_fifo ); |
|---|
| 235 |
free( p_sys ); |
|---|
| 236 |
} |
|---|
| 237 |
|
|---|
| 238 |
|
|---|
| 239 |
|
|---|
| 240 |
|
|---|
| 241 |
static block_t *Block( access_t *p_access ) |
|---|
| 242 |
{ |
|---|
| 243 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 244 |
access_t *p_src = p_access->p_source; |
|---|
| 245 |
block_t *p_block = NULL; |
|---|
| 246 |
|
|---|
| 247 |
|
|---|
| 248 |
if( p_src->info.i_update & INPUT_UPDATE_META ) |
|---|
| 249 |
{ |
|---|
| 250 |
p_src->info.i_update &= ~INPUT_UPDATE_META; |
|---|
| 251 |
p_access->info.i_update |= INPUT_UPDATE_META; |
|---|
| 252 |
} |
|---|
| 253 |
|
|---|
| 254 |
|
|---|
| 255 |
if( !p_access->info.b_eof ) |
|---|
| 256 |
p_block = block_FifoGet( p_sys->p_fifo ); |
|---|
| 257 |
|
|---|
| 258 |
if( p_block && !p_block->i_buffer ) |
|---|
| 259 |
{ block_Release( p_block ); p_block = 0; } |
|---|
| 260 |
|
|---|
| 261 |
if( p_block ) |
|---|
| 262 |
{ |
|---|
| 263 |
p_sys->i_data -= p_block->i_buffer; |
|---|
| 264 |
return p_block; |
|---|
| 265 |
} |
|---|
| 266 |
|
|---|
| 267 |
p_access->info.b_eof = p_src->info.b_eof; |
|---|
| 268 |
return NULL; |
|---|
| 269 |
} |
|---|
| 270 |
|
|---|
| 271 |
|
|---|
| 272 |
|
|---|
| 273 |
|
|---|
| 274 |
static void* Thread( vlc_object_t* p_this ) |
|---|
| 275 |
{ |
|---|
| 276 |
access_t *p_access = (access_t*)p_this; |
|---|
| 277 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 278 |
access_t *p_src = p_access->p_source; |
|---|
| 279 |
block_t *p_block; |
|---|
| 280 |
|
|---|
| 281 |
int canc = vlc_savecancel (); |
|---|
| 282 |
while( vlc_object_alive (p_access) ) |
|---|
| 283 |
{ |
|---|
| 284 |
|
|---|
| 285 |
if( p_src->pf_block ) |
|---|
| 286 |
{ |
|---|
| 287 |
p_block = p_src->pf_block( p_src ); |
|---|
| 288 |
} |
|---|
| 289 |
else |
|---|
| 290 |
{ |
|---|
| 291 |
int i_read; |
|---|
| 292 |
|
|---|
| 293 |
if( ( p_block = block_New( p_access, 2048 ) ) == NULL ) break; |
|---|
| 294 |
|
|---|
| 295 |
i_read = p_src->pf_read( p_src, p_block->p_buffer, 2048 ); |
|---|
| 296 |
if( i_read <= 0 ) |
|---|
| 297 |
{ |
|---|
| 298 |
block_Release( p_block ); |
|---|
| 299 |
p_block = NULL; |
|---|
| 300 |
} |
|---|
| 301 |
p_block->i_buffer = i_read; |
|---|
| 302 |
} |
|---|
| 303 |
|
|---|
| 304 |
if( p_block == NULL ) |
|---|
| 305 |
{ |
|---|
| 306 |
if( p_src->info.b_eof ) break; |
|---|
| 307 |
msleep( 10000 ); |
|---|
| 308 |
continue; |
|---|
| 309 |
} |
|---|
| 310 |
|
|---|
| 311 |
p_sys->i_data += p_block->i_buffer; |
|---|
| 312 |
|
|---|
| 313 |
|
|---|
| 314 |
if( !p_sys->p_write_list && !p_sys->p_read_list && |
|---|
| 315 |
block_FifoSize( p_sys->p_fifo ) < TIMESHIFT_FIFO_MAX ) |
|---|
| 316 |
{ |
|---|
| 317 |
|
|---|
| 318 |
|
|---|
| 319 |
block_FifoPut( p_sys->p_fifo, p_block ); |
|---|
| 320 |
continue; |
|---|
| 321 |
} |
|---|
| 322 |
|
|---|
| 323 |
WriteBlockToFile( p_access, p_block ); |
|---|
| 324 |
block_Release( p_block ); |
|---|
| 325 |
|
|---|
| 326 |
|
|---|
| 327 |
while( block_FifoSize( p_sys->p_fifo ) < TIMESHIFT_FIFO_MIN && |
|---|
| 328 |
vlc_object_alive (p_access) ) |
|---|
| 329 |
{ |
|---|
| 330 |
p_block = ReadBlockFromFile( p_access ); |
|---|
| 331 |
if( !p_block ) break; |
|---|
| 332 |
|
|---|
| 333 |
block_FifoPut( p_sys->p_fifo, p_block ); |
|---|
| 334 |
} |
|---|
| 335 |
} |
|---|
| 336 |
|
|---|
| 337 |
msg_Dbg( p_access, "timeshift: no more input data" ); |
|---|
| 338 |
|
|---|
| 339 |
while( vlc_object_alive (p_access) && |
|---|
| 340 |
(p_sys->p_read_list || block_FifoSize( p_sys->p_fifo ) ) ) |
|---|
| 341 |
{ |
|---|
| 342 |
|
|---|
| 343 |
while( block_FifoSize( p_sys->p_fifo ) < TIMESHIFT_FIFO_MIN && |
|---|
| 344 |
vlc_object_alive (p_access) && p_sys->p_read_list ) |
|---|
| 345 |
{ |
|---|
| 346 |
p_block = ReadBlockFromFile( p_access ); |
|---|
| 347 |
if( !p_block ) break; |
|---|
| 348 |
|
|---|
| 349 |
block_FifoPut( p_sys->p_fifo, p_block ); |
|---|
| 350 |
} |
|---|
| 351 |
|
|---|
| 352 |
msleep( 100000 ); |
|---|
| 353 |
} |
|---|
| 354 |
|
|---|
| 355 |
msg_Dbg( p_access, "timeshift: EOF" ); |
|---|
| 356 |
p_src->info.b_eof = true; |
|---|
| 357 |
|
|---|
| 358 |
|
|---|
| 359 |
block_FifoPut( p_sys->p_fifo, block_New( p_access, 0 ) ); |
|---|
| 360 |
vlc_restorecancel (canc); |
|---|
| 361 |
return NULL; |
|---|
| 362 |
} |
|---|
| 363 |
|
|---|
| 364 |
|
|---|
| 365 |
|
|---|
| 366 |
|
|---|
| 367 |
static void NextFileWrite( access_t *p_access ) |
|---|
| 368 |
{ |
|---|
| 369 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 370 |
ts_entry_t *p_next; |
|---|
| 371 |
|
|---|
| 372 |
if( !p_sys->p_write_list ) |
|---|
| 373 |
{ |
|---|
| 374 |
p_sys->i_write_size = 0; |
|---|
| 375 |
return; |
|---|
| 376 |
} |
|---|
| 377 |
|
|---|
| 378 |
p_next = p_sys->p_write_list->p_next; |
|---|
| 379 |
|
|---|
| 380 |
|
|---|
| 381 |
if( p_sys->i_write_size < p_sys->i_file_size ) |
|---|
| 382 |
ftruncate( fileno( p_sys->p_write_list->file ), p_sys->i_write_size ); |
|---|
| 383 |
|
|---|
| 384 |
fseek( p_sys->p_write_list->file, 0, SEEK_SET ); |
|---|
| 385 |
*p_sys->pp_read_last = p_sys->p_write_list; |
|---|
| 386 |
p_sys->pp_read_last = &p_sys->p_write_list->p_next; |
|---|
| 387 |
p_sys->p_write_list->p_next = 0; |
|---|
| 388 |
|
|---|
| 389 |
|
|---|
| 390 |
p_sys->p_write_list = p_next; |
|---|
| 391 |
if( !p_sys->p_write_list ) p_sys->pp_write_last = &p_sys->p_write_list; |
|---|
| 392 |
|
|---|
| 393 |
p_sys->i_write_size = 0; |
|---|
| 394 |
} |
|---|
| 395 |
|
|---|
| 396 |
|
|---|
| 397 |
|
|---|
| 398 |
|
|---|
| 399 |
static void NextFileRead( access_t *p_access ) |
|---|
| 400 |
{ |
|---|
| 401 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 402 |
ts_entry_t *p_next; |
|---|
| 403 |
|
|---|
| 404 |
if( !p_sys->p_read_list ) return; |
|---|
| 405 |
|
|---|
| 406 |
p_next = p_sys->p_read_list->p_next; |
|---|
| 407 |
|
|---|
| 408 |
|
|---|
| 409 |
fseek( p_sys->p_read_list->file, 0, SEEK_SET ); |
|---|
| 410 |
*p_sys->pp_write_last = p_sys->p_read_list; |
|---|
| 411 |
p_sys->pp_write_last = &p_sys->p_read_list->p_next; |
|---|
| 412 |
p_sys->p_read_list->p_next = 0; |
|---|
| 413 |
|
|---|
| 414 |
|
|---|
| 415 |
p_sys->p_read_list = p_next; |
|---|
| 416 |
if( !p_sys->p_read_list ) p_sys->pp_read_last = &p_sys->p_read_list; |
|---|
| 417 |
} |
|---|
| 418 |
|
|---|
| 419 |
|
|---|
| 420 |
|
|---|
| 421 |
|
|---|
| 422 |
static int WriteBlockToFile( access_t *p_access, block_t *p_block ) |
|---|
| 423 |
{ |
|---|
| 424 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 425 |
int i_write, i_buffer; |
|---|
| 426 |
|
|---|
| 427 |
if( p_sys->i_write_size == p_sys->i_file_size ) NextFileWrite( p_access ); |
|---|
| 428 |
|
|---|
| 429 |
|
|---|
| 430 |
if( !p_sys->p_write_list ) |
|---|
| 431 |
{ |
|---|
| 432 |
FILE *file; |
|---|
| 433 |
|
|---|
| 434 |
sprintf( p_sys->psz_filename, "%s%u.dat", |
|---|
| 435 |
p_sys->psz_filename_base, p_sys->i_files ); |
|---|
| 436 |
file = utf8_fopen( p_sys->psz_filename, "w+b" ); |
|---|
| 437 |
|
|---|
| 438 |
if( !file && p_sys->i_files < 2 ) |
|---|
| 439 |
{ |
|---|
| 440 |
|
|---|
| 441 |
msg_Err( p_access, "cannot open temporary file '%s' (%m)", |
|---|
| 442 |
p_sys->psz_filename ); |
|---|
| 443 |
return VLC_EGENERIC; |
|---|
| 444 |
} |
|---|
| 445 |
else if( !file ) return VLC_EGENERIC; |
|---|
| 446 |
|
|---|
| 447 |
p_sys->p_write_list = malloc( sizeof(ts_entry_t) ); |
|---|
| 448 |
p_sys->p_write_list->p_next = 0; |
|---|
| 449 |
p_sys->p_write_list->file = file; |
|---|
| 450 |
p_sys->pp_write_last = &p_sys->p_write_list->p_next; |
|---|
| 451 |
|
|---|
| 452 |
p_sys->i_files++; |
|---|
| 453 |
} |
|---|
| 454 |
|
|---|
| 455 |
|
|---|
| 456 |
i_buffer = __MIN( p_block->i_buffer, |
|---|
| 457 |
p_sys->i_file_size - p_sys->i_write_size ); |
|---|
| 458 |
|
|---|
| 459 |
i_write = fwrite( p_block->p_buffer, 1, i_buffer, |
|---|
| 460 |
p_sys->p_write_list->file ); |
|---|
| 461 |
|
|---|
| 462 |
if( i_write > 0 ) p_sys->i_write_size += i_write; |
|---|
| 463 |
|
|---|
| 464 |
|
|---|
| 465 |
|
|---|
| 466 |
|
|---|
| 467 |
if( i_write < i_buffer ) |
|---|
| 468 |
{ |
|---|
| 469 |
|
|---|
| 470 |
|
|---|
| 471 |
if( !p_sys->p_write_list->p_next ) |
|---|
| 472 |
{ |
|---|
| 473 |
msg_Warn( p_access, "no more space, overwritting old data" ); |
|---|
| 474 |
NextFileRead( p_access ); |
|---|
| 475 |
NextFileRead( p_access ); |
|---|
| 476 |
} |
|---|
| 477 |
|
|---|
| 478 |
|
|---|
| 479 |
p_sys->i_write_size = p_sys->i_file_size; |
|---|
| 480 |
} |
|---|
| 481 |
|
|---|
| 482 |
p_block->p_buffer += i_write; |
|---|
| 483 |
p_block->i_buffer -= i_write; |
|---|
| 484 |
|
|---|
| 485 |
|
|---|
| 486 |
if( p_block->i_buffer ) return WriteBlockToFile( p_access, p_block ); |
|---|
| 487 |
|
|---|
| 488 |
return VLC_SUCCESS; |
|---|
| 489 |
} |
|---|
| 490 |
|
|---|
| 491 |
|
|---|
| 492 |
|
|---|
| 493 |
|
|---|
| 494 |
static block_t *ReadBlockFromFile( access_t *p_access ) |
|---|
| 495 |
{ |
|---|
| 496 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 497 |
block_t *p_block; |
|---|
| 498 |
|
|---|
| 499 |
if( !p_sys->p_read_list && p_sys->p_write_list ) |
|---|
| 500 |
{ |
|---|
| 501 |
|
|---|
| 502 |
|
|---|
| 503 |
NextFileWrite( p_access ); |
|---|
| 504 |
} |
|---|
| 505 |
|
|---|
| 506 |
if( !p_sys->p_read_list ) return 0; |
|---|
| 507 |
|
|---|
| 508 |
p_block = block_New( p_access, 4096 ); |
|---|
| 509 |
p_block->i_buffer = fread( p_block->p_buffer, 1, 4096, |
|---|
| 510 |
p_sys->p_read_list->file ); |
|---|
| 511 |
|
|---|
| 512 |
if( p_block->i_buffer == 0 ) NextFileRead( p_access ); |
|---|
| 513 |
|
|---|
| 514 |
|
|---|
| 515 |
|
|---|
| 516 |
|
|---|
| 517 |
return p_block; |
|---|
| 518 |
} |
|---|
| 519 |
|
|---|
| 520 |
|
|---|
| 521 |
|
|---|
| 522 |
|
|---|
| 523 |
static int Seek( access_t *p_access, int64_t i_pos ) |
|---|
| 524 |
{ |
|---|
| 525 |
|
|---|
| 526 |
(void)p_access; |
|---|
| 527 |
(void)i_pos; |
|---|
| 528 |
return VLC_SUCCESS; |
|---|
| 529 |
} |
|---|
| 530 |
|
|---|
| 531 |
|
|---|
| 532 |
|
|---|
| 533 |
|
|---|
| 534 |
static int Control( access_t *p_access, int i_query, va_list args ) |
|---|
| 535 |
{ |
|---|
| 536 |
bool *pb_bool; |
|---|
| 537 |
int *pi_int; |
|---|
| 538 |
|
|---|
| 539 |
switch( i_query ) |
|---|
| 540 |
{ |
|---|
| 541 |
case ACCESS_CAN_SEEK: |
|---|
| 542 |
case ACCESS_CAN_FASTSEEK: |
|---|
| 543 |
pb_bool = (bool*)va_arg( args, bool* ); |
|---|
| 544 |
*pb_bool = true; |
|---|
| 545 |
break; |
|---|
| 546 |
|
|---|
| 547 |
case ACCESS_CAN_CONTROL_PACE: |
|---|
| 548 |
case ACCESS_CAN_PAUSE: |
|---|
| 549 |
pb_bool = (bool*)va_arg( args, bool* ); |
|---|
| 550 |
*pb_bool = true; |
|---|
| 551 |
break; |
|---|
| 552 |
|
|---|
| 553 |
case ACCESS_GET_MTU: |
|---|
| 554 |
pi_int = (int*)va_arg( args, int * ); |
|---|
| 555 |
*pi_int = 0; |
|---|
| 556 |
break; |
|---|
| 557 |
|
|---|
| 558 |
case ACCESS_SET_PAUSE_STATE: |
|---|
| 559 |
break; |
|---|
| 560 |
|
|---|
| 561 |
|
|---|
| 562 |
default: |
|---|
| 563 |
return access_vaControl( p_access->p_source, i_query, args ); |
|---|
| 564 |
} |
|---|
| 565 |
return VLC_SUCCESS; |
|---|
| 566 |
} |
|---|
| 567 |
|
|---|
| 568 |
|
|---|
| 569 |
|
|---|
| 570 |
|
|---|
| 571 |
#ifdef WIN32 |
|---|
| 572 |
#define getpid() (int)GetCurrentProcessId() |
|---|
| 573 |
#endif |
|---|
| 574 |
static char *GetTmpFilePath( access_t *p_access ) |
|---|
| 575 |
{ |
|---|
| 576 |
char *psz_dir = var_GetNonEmptyString( p_access, "timeshift-dir" ); |
|---|
| 577 |
char *psz_filename_base; |
|---|
| 578 |
|
|---|
| 579 |
if( psz_dir == NULL ) |
|---|
| 580 |
{ |
|---|
| 581 |
#ifdef WIN32 |
|---|
| 582 |
DWORD ret = GetTempPathW (0, NULL); |
|---|
| 583 |
wchar_t wdir[ret + 3]; |
|---|
| 584 |
const wchar_t *pwdir = wdir; |
|---|
| 585 |
wchar_t *pwdir_free = NULL; |
|---|
| 586 |
|
|---|
| 587 |
if (GetTempPathW (ret + 1, wdir) == 0) |
|---|
| 588 |
{ |
|---|
| 589 |
pwdir_free = pwdir = _wgetcwd (NULL, 0); |
|---|
| 590 |
if (pwdir == NULL) |
|---|
| 591 |
pwdir = L"C:"; |
|---|
| 592 |
} |
|---|
| 593 |
|
|---|
| 594 |
psz_dir = FromWide (pwdir); |
|---|
| 595 |
if (pwdir_free != NULL) |
|---|
| 596 |
free (pwdir_free); |
|---|
| 597 |
|
|---|
| 598 |
|
|---|
| 599 |
if (psz_dir[strlen (psz_dir) - 1] == '\\') |
|---|
| 600 |
psz_dir[strlen (psz_dir) - 1] = '\0'; |
|---|
| 601 |
#else |
|---|
| 602 |
psz_dir = strdup( "/tmp" ); |
|---|
| 603 |
#endif |
|---|
| 604 |
} |
|---|
| 605 |
|
|---|
| 606 |
if( asprintf( &psz_filename_base, "%s/vlc-timeshift-%d-%p-", |
|---|
| 607 |
psz_dir, getpid(), p_access ) == -1 ) |
|---|
| 608 |
psz_filename_base = NULL; |
|---|
| 609 |
free( psz_dir ); |
|---|
| 610 |
|
|---|
| 611 |
return psz_filename_base; |
|---|
| 612 |
} |
|---|