-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjango.pl
executable file
·140 lines (130 loc) · 3.85 KB
/
jango.pl
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
134
135
136
137
138
139
140
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use LWP::UserAgent;
use HTTP::Request::Common;
use JSON;
use POSIX 'strftime';
use Term::ReadKey;
use File::Basename;
my $HELP = basename($0) . "
Commands:
-h | --help Displays this help message
<station id> Plays the given station
<artist name> Finds a station for the artist, and plays it
Input:
p Toggles pause on the current song
n Starts playing the next song
q Quits the player
e Quits the player after the current song finishes
";
my $station;
# Commandline argument parsing
# Checks for a station id. Artist searching is handled later.
if ($#ARGV == -1) {
print $HELP;
exit 1;
} elsif ($#ARGV == 0) {
for ($ARGV[0]) {
/^[\d]+$/ and do {
$station = $_;
last;
};
/^-h$/ or /^--help$/ and do {
print $HELP;
exit 0;
};
}
}
my $UA = LWP::UserAgent->new;
$UA->cookie_jar({});
my $playing = 1;
my ($player, $pid);
my ($url, $tags);
# Downloads a webpage via HTTP get, and die if the request fails
# (used to avoid duplicating error checking code)
# returns the webserver's result if successful
sub get {
my $response = $UA->request(GET shift);
$response->is_success or do {
my $message = shift;
if (defined $message) {
die $message . ': ' . $response->status_line . '\n';
} else {
die $response->status_line . '\n';
}
};
return $response->decoded_content;
}
# Preloads the next song's details to minimise load times
sub prepare_song {
# get next song
$url = decode_json(get 'http://www.jango.com/streams/' . $station, 'Failed to retrieve stream')->{'url'};
# get song details
($tags) = ((get 'http://www.jango.com/players/usd?ver=7', 'Failed to retrieve song details') =~ /_jm\.song_info[\s]*=(.*);/i);
$tags = decode_json $tags;
}
# Plays a song, and preloads the next song
# IMPORTANT: Must only be called after the previous player has died
# (or bad things will happen)
sub play_song {
print((strftime '%Y-%m-%d %H:%M', localtime), ' | ', $tags->{'artist'}, ' - ', $tags->{'song'}, "\n");
$pid = open $player, '| mplayer -really-quiet ' . $url . ' 2>/dev/null';
# Enable unbuffered output to the player so we can control it
my $previous_fh = select($player);
$| = 1;
select($previous_fh);
prepare_song;
}
# When the song ends (or is skipped), start the next song
$SIG{CHLD} = sub {
close $player;
if ($playing) {
play_song;
} else {
exit 0;
}
};
# If we don't have a station to play, we must have been given an artist name to search
unless (defined $station) {
my $artist = join '+', @ARGV;
$artist =~ s/[\s]+/+/g;
my $html = get 'http://www.jango.com/music/' . $artist, 'Failed to retrieve station list';
$html =~ s/\n//g;
($station, my $title) = ($html =~ /<a href="\/stations\/([\d]+)\/play".*?>([^<]*Radio).*?<\/a>/mi) or die 'No results found for ' . $artist . "\n";
print "Found station ", $station, " - ", $title, "\n";
};
# Connect to jango in order to get cookies
get 'http://www.jango.com/stations/' . $station, 'Failed to connect to jango';
prepare_song;
play_song;
# Enable unbuffered user input
ReadMode 3;
# Handle user input
while (1) {
my $key = ReadKey 0;
for ($key) {
if ($playing) {
/^n$/ and do {
print $player 'q';
last;
};
/^e$/ and do {
$playing = 0;
print "Exiting after song finishes\n";
last;
};
}
/^p$/ and do {
print $player 'p';
last;
};
/^q$/ and do {
$playing = 0;
print $player 'q';
waitpid $pid, 0;
last;
};
}
}