aboutsummaryrefslogtreecommitdiff
path: root/watch.c
blob: 09cc154393b5d54e7c36cb3888a048cd4b0bb5fa (plain)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32)
#error Systems other than Windows are not supported.
#endif

#include <windows.h>
#include <signal.h>

#include <shellapi.h>
#pragma comment(lib, "Shell32")
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

#include <stdio.h>

#define err(code, string) do { fprintf(stderr, "%s: %s: %s\n", string, strerror(errno)); exit(code); } while (0)
#define die(...) do { fprintf(stderr, __VA_ARGS__); system("pause"); exit(1); } while (0)
#define bool int
#define true 1
#define false 0

#define MAX_PATH 260
#define SR_ERR_NOASSOC (HINSTANCE)31
#define USAGE "usage: %s [/c argument-string] URL\n", argv[0]

char out[MAX_PATH];

void sigbreak(int sig) {
  /* open playlist */
  if (ShellExecute(NULL, "open", out, NULL, NULL, 5) <= (HINSTANCE)32)
    die("failed to open %s\n", out);
  exit(0);
}

int main(int argc, char *argv[]) {
  bool new, title;
  char *cmd, *extra, temp[MAX_PATH], *url;
  FILE *f, *p;
  HINSTANCE r;
  int c, i, linecount;
  ULONGLONG last;
  
  signal(SIGBREAK, sigbreak);
  
  /* construct temporary playlist file path */
  
  if (GetTempPath(1 + MAX_PATH, temp) > 0 && strlen(temp) + 1 + 16 <= MAX_PATH) {
    strcpy(out, temp);
    if (temp[strlen(temp)-1] != '\\') strcat(out, "\\");
  }
  strcat(out, "watch.tmp.mpcpl");
  
  if (argc == 1) goto open; /* open previous link */
  
  if (argv[1][0] == '/') {
    if (argv[1][1] != 'c' || argc != 4) die(USAGE);
    extra = argv[2];
    url = argv[3];
  } else {
    if (argc != 2) die(USAGE);
    extra = NULL;
    url = argv[1];
  }
  
  if (strncmp(url, "watch:", 6) == 0) /* support watch: urls */
    url += 6;
  
  for (i = 0; i < strlen(url); i++)
    if (url[i] == '"') die("URL cannot contain quotes (\")\n");
  
  /* start youtube-dl */
  
  if (extra != NULL) {
    cmd = malloc(sizeof("youtube-dl -eg --youtube-skip-dash-manifest  \"\"") + (strlen(url) + strlen(extra)) * sizeof(char));
    if (cmd == NULL) err(1, "malloc");
    if (sprintf(cmd, "youtube-dl -eg --youtube-skip-dash-manifest %s \"%s\"", extra, url) < 0) err(1, "sprintf");
  } else {
    cmd = malloc(sizeof("youtube-dl -eg --youtube-skip-dash-manifest \"\"") + strlen(url) * sizeof(char));
    if (cmd == NULL) err(1, "malloc");
    if (sprintf(cmd, "youtube-dl -eg --youtube-skip-dash-manifest \"%s\"", url) < 0) err(1, "sprintf");
  }
  
  p = _popen(cmd, "r");
  if (p == NULL) err(1, "popen");
  
  /* open temporary playlist file */
  
  f = fopen(out, "w");
  if (f == NULL) err(1, "fopen");
  
  /* read/write stream urls */
  
  linecount = 0;
  new = true;
  title = false;
  last = GetTickCount();
  
  c = fgetc(p);
  if (c == EOF) goto end;
  fprintf(f, "MPCPLAYLIST\n");
  goto loop;
  
  while ((c = fgetc(p)) != EOF) {
loop:
    if (new) {
      new = false;
      /* if new line immediately follows last one, it belongs to the same video */
      if (GetTickCount() - last > 20) { /* new video */
        title = true;
        linecount++;
        fprintf(stderr, "Retrieving video #%d\n", linecount);
        fprintf(f, "%d,type,0\n", linecount);
        fprintf(f, "%d,label,", linecount);
      } else
        fprintf(f, "%d,filename,", linecount);
    }
    fputc(c, f);
    if (c == '\n') {
      last = GetTickCount();
      new = true;
    }
  }
  
end:
  if (i = _pclose(p))
    if (i != -1073741510) /* Ctrl-Break */
      die("youtube-dl exited with %d\n", i);
  
  /* open playlist */
open:
  if (ShellExecute(NULL, "open", out, NULL, NULL, 5) <= (HINSTANCE)32)
    die("failed to open %s\n", out);
  return 0;
}