douban.fm 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +41 -3
 - data/bin/douban.fm +170 -85
 - data/lib/douban.fm/douban_fm.rb +63 -6
 - data/lib/douban.fm/version.rb +1 -1
 - metadata +6 -6
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            Play music from douban.fm.
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            __Note that this project is still on-going, so I  
     | 
| 
      
 5 
     | 
    
         
            +
            __Note that this project is still on-going, so I will only try my best to stablize the interface.__
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            ## Installation
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
         @@ -20,9 +20,47 @@ Or install it yourself as: 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            ## Usage
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 23 
     | 
    
         
            +
            <pre>
         
     | 
| 
      
 24 
     | 
    
         
            +
            $ douban.fm -h
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
            Usage: douban.fm [OPTIONS]
         
     | 
| 
      
 27 
     | 
    
         
            +
                -u, --user email                 douban.fm account name, normally an email address
         
     | 
| 
      
 28 
     | 
    
         
            +
                                                 if not provided, will play anonymous playlist
         
     | 
| 
      
 29 
     | 
    
         
            +
                -p, --password [password]        douban.fm account password
         
     | 
| 
      
 30 
     | 
    
         
            +
                                                 if not provided, will be asked
         
     | 
| 
      
 31 
     | 
    
         
            +
                -m, --mpd                        do not play by it own, send playlist to Music Player Daemon
         
     | 
| 
      
 32 
     | 
    
         
            +
                -c, --channel channel            which channel to play
         
     | 
| 
      
 33 
     | 
    
         
            +
                                                 if not provided, channel 0 will be selected but who knows what it is
         
     | 
| 
      
 34 
     | 
    
         
            +
                -l, --list                       list all available channels
         
     | 
| 
      
 35 
     | 
    
         
            +
                -v, --verbose                    verbose mode
         
     | 
| 
      
 36 
     | 
    
         
            +
                -h, --help                       show this message
         
     | 
| 
      
 37 
     | 
    
         
            +
            </pre>
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            Basically there are two ways to play music
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            * to play direclty by `mpg123`
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                Under this mode, music will be played by forking `mpg123` directly. Sorry currently there is no way to configure which music player to use.
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                * `douban.fm` will play anonymous playlist of channel 0
         
     | 
| 
      
 46 
     | 
    
         
            +
                * `douban.fm -c 1` will play channel 1
         
     | 
| 
      
 47 
     | 
    
         
            +
                * `douban.fm -u xxx@xxx.com -p xxx` will play private playlist
         
     | 
| 
      
 48 
     | 
    
         
            +
                * `douban.fm -u xxx@xxx.com -p xxx -c 1` will play channel 1 but with your account signed in
         
     | 
| 
      
 49 
     | 
    
         
            +
                * `douban.fm -u xxx@xx.com -p` will play private playlist but will ask for your password to sign in
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            * to play by [Music Player Daemon](http://mpd.wikia.com/wiki/Music_Player_Daemon_Wiki)
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                Under this mode, URL of music will be sent to MPD which will actually play. Whenever there are less than _10_ songs in MPD playlist, more will be retrieved from douban.fm.
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                It is fantastic to use MPD since there are quite many [clients](http://mpd.wikia.com/wiki/Clients) to use. I am now just use my iPhone with [MPoD2](http://mpd.wikia.com/wiki/Client:MPoD2).
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                Thanks for @tdsparrow pointing out MPD, otherwise I might have been doing some really stupid things.
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                * `douban.fm -m` will play anonymous playlist of channel 0
         
     | 
| 
      
 60 
     | 
    
         
            +
                * `douban.fm -m -c 1` will play channel 1
         
     | 
| 
      
 61 
     | 
    
         
            +
                * `douban.fm -m -u xxx@xxx.com -p xxx` will play private playlist
         
     | 
| 
      
 62 
     | 
    
         
            +
                * `douban.fm -m -u xxx@xxx.com -p xxx -c 1` will play channel 1 but with your account signed in
         
     | 
| 
      
 63 
     | 
    
         
            +
                * `douban.fm -m -u xxx@xx.com -p` will play private playlist but will ask for your password to sign in
         
     | 
| 
       26 
64 
     | 
    
         | 
| 
       27 
65 
     | 
    
         
             
            ## Contributing
         
     | 
| 
       28 
66 
     | 
    
         | 
    
        data/bin/douban.fm
    CHANGED
    
    | 
         @@ -4,128 +4,213 @@ require 'douban.fm' 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'optparse'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'ostruct'
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
               
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
            class DoubanFMCLI
         
     | 
| 
      
 8 
     | 
    
         
            +
              def parse
         
     | 
| 
      
 9 
     | 
    
         
            +
                options = OpenStruct.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                options.verbose = false
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                opts = OptionParser.new do |opts|
         
     | 
| 
      
 13 
     | 
    
         
            +
                  opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [OPTIONS]"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  opts.on('-u', '--user email',
         
     | 
| 
      
 16 
     | 
    
         
            +
                          'douban.fm account name, normally an email address',
         
     | 
| 
      
 17 
     | 
    
         
            +
                          'if not provided, will play anonymous playlist') do |email|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    options.email = email
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
       10 
20 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
                  opts.on('-p', '--password [password]',
         
     | 
| 
      
 22 
     | 
    
         
            +
                          'douban.fm account password',
         
     | 
| 
      
 23 
     | 
    
         
            +
                          'if not provided, will be asked') do |password|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    options.password = password
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
       13 
26 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                  options.email = email
         
     | 
| 
       18 
     | 
    
         
            -
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  opts.on('-m', '--mpd', 'do not play by it own, send playlist to Music Player Daemon') do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    options.mpd = true
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
       19 
30 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 31 
     | 
    
         
            +
                  opts.on('-r', '--remote remote', 'mpd remote host, in format of <IP>:<Port>') do |remote|
         
     | 
| 
      
 32 
     | 
    
         
            +
                    parts = remote.split(':')
         
     | 
| 
      
 33 
     | 
    
         
            +
                    if parts.length != 2
         
     | 
| 
      
 34 
     | 
    
         
            +
                      puts opts
         
     | 
| 
      
 35 
     | 
    
         
            +
                      exit
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
       25 
37 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
                    options.remote_host = parts[0]
         
     | 
| 
      
 39 
     | 
    
         
            +
                    options.remote_port = parts[1].to_i
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
       29 
41 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 42 
     | 
    
         
            +
                  opts.on('-c', '--channel channel',
         
     | 
| 
      
 43 
     | 
    
         
            +
                          'which channel to play',
         
     | 
| 
      
 44 
     | 
    
         
            +
                          'if not provided, channel 0 will be selected but who knows what it is') do |channel|
         
     | 
| 
      
 45 
     | 
    
         
            +
                    options.channel = channel
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
       35 
47 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
      
 48 
     | 
    
         
            +
                  opts.on('-l', '--list', 'list all available channels') do
         
     | 
| 
      
 49 
     | 
    
         
            +
                    options.list = true
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  opts.on('-i', '--interaction', 'start an http server for interaction') do
         
     | 
| 
      
 53 
     | 
    
         
            +
                    options.interaction = true
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  opts.on('-v', '--verbose', 'verbose mode') do
         
     | 
| 
      
 57 
     | 
    
         
            +
                    options.verbose = true
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
       39 
59 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
      
 60 
     | 
    
         
            +
                  opts.on_tail('-h', '--help', 'show this message') do
         
     | 
| 
      
 61 
     | 
    
         
            +
                    puts opts
         
     | 
| 
      
 62 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
       42 
64 
     | 
    
         
             
                end
         
     | 
| 
       43 
65 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                opts. 
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 66 
     | 
    
         
            +
                opts.parse!
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                options
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              def main
         
     | 
| 
      
 72 
     | 
    
         
            +
                options = parse
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                if not options.interaction.nil? and options.mpd.nil?
         
     | 
| 
      
 75 
     | 
    
         
            +
                  puts 'only mpd mode supports interaction'
         
     | 
| 
       46 
76 
     | 
    
         
             
                  exit
         
     | 
| 
       47 
77 
     | 
    
         
             
                end
         
     | 
| 
       48 
     | 
    
         
            -
              end
         
     | 
| 
       49 
78 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
      
 79 
     | 
    
         
            +
                if options.verbose
         
     | 
| 
      
 80 
     | 
    
         
            +
                  logger = DoubanFM::ConsoleLogger.new
         
     | 
| 
      
 81 
     | 
    
         
            +
                else
         
     | 
| 
      
 82 
     | 
    
         
            +
                  logger = DoubanFM::DummyLogger.new
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
       51 
84 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
      
 85 
     | 
    
         
            +
                if options.list
         
     | 
| 
      
 86 
     | 
    
         
            +
                  @@douban_fm = DoubanFM::DoubanFM.new(logger)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  @@douban_fm.fetch_channels
         
     | 
| 
      
 88 
     | 
    
         
            +
                  @@douban_fm.channels['channels'].sort_by { |i| i['channel_id'] }.each do |channel|
         
     | 
| 
      
 89 
     | 
    
         
            +
                    channel_id = channel['channel_id']
         
     | 
| 
      
 90 
     | 
    
         
            +
                    puts "#{channel_id}.#{' ' * (4 - channel_id.to_s.length)}#{channel['name']}"
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
       57 
92 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                douban_fm = DoubanFM::DoubanFM.new(logger)
         
     | 
| 
       60 
     | 
    
         
            -
                douban_fm.fetch_channels
         
     | 
| 
       61 
     | 
    
         
            -
                douban_fm.channels['channels'].sort_by { |i| i['channel_id'] }.each do |channel|
         
     | 
| 
       62 
     | 
    
         
            -
                  channel_id = channel['channel_id']
         
     | 
| 
       63 
     | 
    
         
            -
                  puts "#{channel_id}.#{' ' * (4 - channel_id.to_s.length)}#{channel['name']}"
         
     | 
| 
      
 93 
     | 
    
         
            +
                  exit
         
     | 
| 
       64 
94 
     | 
    
         
             
                end
         
     | 
| 
       65 
95 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                 
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
      
 96 
     | 
    
         
            +
                if options.channel.nil?
         
     | 
| 
      
 97 
     | 
    
         
            +
                  options.channel = 0
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
       68 
99 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
      
 100 
     | 
    
         
            +
                if options.email.nil?
         
     | 
| 
      
 101 
     | 
    
         
            +
                  @@douban_fm = DoubanFM::DoubanFM.new(logger)
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  logger.log('play anonymous playlist')
         
     | 
| 
      
 104 
     | 
    
         
            +
                else
         
     | 
| 
      
 105 
     | 
    
         
            +
                  if options.password.nil? or options.password.empty?
         
     | 
| 
      
 106 
     | 
    
         
            +
                    require 'highline/import'
         
     | 
| 
      
 107 
     | 
    
         
            +
                    options.password = ask("Enter password: ") { |q| q.echo = false }
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
       72 
109 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
      
 110 
     | 
    
         
            +
                  @@douban_fm = DoubanFM::DoubanFM.new(logger, options.email, options.password)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  @@douban_fm.login
         
     | 
| 
       75 
112 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
              else
         
     | 
| 
       78 
     | 
    
         
            -
                if options.password.nil? or options.password.empty?
         
     | 
| 
       79 
     | 
    
         
            -
                  require 'highline/import'
         
     | 
| 
       80 
     | 
    
         
            -
                  options.password = ask("Enter password: ") { |q| q.echo = false }
         
     | 
| 
      
 113 
     | 
    
         
            +
                  logger.log("login as user [#{options.email}]")
         
     | 
| 
       81 
114 
     | 
    
         
             
                end
         
     | 
| 
       82 
115 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                douban_fm 
     | 
| 
       84 
     | 
    
         
            -
                douban_fm.login
         
     | 
| 
      
 116 
     | 
    
         
            +
                @@douban_fm.select_channel(options.channel)
         
     | 
| 
       85 
117 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
                logger.log(" 
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
      
 118 
     | 
    
         
            +
                logger.log("select channel #{options.channel}")
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                if options.mpd.nil?
         
     | 
| 
      
 121 
     | 
    
         
            +
                  play_proc = proc do |waiting|
         
     | 
| 
      
 122 
     | 
    
         
            +
                    if waiting
         
     | 
| 
      
 123 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 124 
     | 
    
         
            +
                        logger.log('fetch next playlist')
         
     | 
| 
       88 
125 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
      
 126 
     | 
    
         
            +
                        @@douban_fm.fetch_next_playlist
         
     | 
| 
      
 127 
     | 
    
         
            +
                      rescue
         
     | 
| 
      
 128 
     | 
    
         
            +
                        logger.log('session expired, relogin')
         
     | 
| 
       90 
129 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
      
 130 
     | 
    
         
            +
                        @@douban_fm.login
         
     | 
| 
       92 
131 
     | 
    
         | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
                play_proc = proc do |waiting|
         
     | 
| 
       95 
     | 
    
         
            -
                  if waiting
         
     | 
| 
       96 
     | 
    
         
            -
                    begin
         
     | 
| 
       97 
     | 
    
         
            -
                      logger.log('fetch next playlist')
         
     | 
| 
      
 132 
     | 
    
         
            +
                        logger.log('fetch next playlist')
         
     | 
| 
       98 
133 
     | 
    
         | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                      logger.log('session expired, relogin')
         
     | 
| 
      
 134 
     | 
    
         
            +
                        @@douban_fm.fetch_next_playlist
         
     | 
| 
      
 135 
     | 
    
         
            +
                      end
         
     | 
| 
       102 
136 
     | 
    
         | 
| 
       103 
     | 
    
         
            -
                       
     | 
| 
      
 137 
     | 
    
         
            +
                      logger.log('play current playlist')
         
     | 
| 
       104 
138 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
                       
     | 
| 
      
 139 
     | 
    
         
            +
                      @@douban_fm.play do |waiting|
         
     | 
| 
      
 140 
     | 
    
         
            +
                        play_proc.call(waiting)
         
     | 
| 
      
 141 
     | 
    
         
            +
                      end
         
     | 
| 
      
 142 
     | 
    
         
            +
                    end
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
       106 
144 
     | 
    
         | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
      
 145 
     | 
    
         
            +
                  play_proc.call(true)
         
     | 
| 
      
 146 
     | 
    
         
            +
                else
         
     | 
| 
      
 147 
     | 
    
         
            +
                  unless options.interaction.nil?
         
     | 
| 
      
 148 
     | 
    
         
            +
                    require 'webrick'
         
     | 
| 
      
 149 
     | 
    
         
            +
                    require 'webrick/httpstatus'
         
     | 
| 
      
 150 
     | 
    
         
            +
                    require 'json'
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                    servletClass = Class.new(WEBrick::HTTPServlet::AbstractServlet) do
         
     | 
| 
      
 153 
     | 
    
         
            +
                      class << self
         
     | 
| 
      
 154 
     | 
    
         
            +
                        def remote_host=(host)
         
     | 
| 
      
 155 
     | 
    
         
            +
                          @@remote_host = host
         
     | 
| 
      
 156 
     | 
    
         
            +
                        end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                        def remote_port=(port)
         
     | 
| 
      
 159 
     | 
    
         
            +
                          @@remote_port = port
         
     | 
| 
      
 160 
     | 
    
         
            +
                        end
         
     | 
| 
      
 161 
     | 
    
         
            +
                      end
         
     | 
| 
      
 162 
     | 
    
         
            +
                      @@remote_host = nil
         
     | 
| 
      
 163 
     | 
    
         
            +
                      @@remote_port = nil
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                      def do_GET request, response
         
     | 
| 
      
 166 
     | 
    
         
            +
                        path = request.path[1..-1].split('/')
         
     | 
| 
      
 167 
     | 
    
         
            +
                        case path[0]
         
     | 
| 
      
 168 
     | 
    
         
            +
                        when 'channels'
         
     | 
| 
      
 169 
     | 
    
         
            +
                          @@douban_fm.fetch_channels
         
     | 
| 
      
 170 
     | 
    
         
            +
                          response.body = JSON.generate(@@douban_fm.channels)
         
     | 
| 
      
 171 
     | 
    
         
            +
                          raise WEBrick::HTTPStatus::OK
         
     | 
| 
      
 172 
     | 
    
         
            +
                        when 'channel'
         
     | 
| 
      
 173 
     | 
    
         
            +
                          unless path[1].nil?
         
     | 
| 
      
 174 
     | 
    
         
            +
                            # there is a race but not a big deal
         
     | 
| 
      
 175 
     | 
    
         
            +
                            @@douban_fm.select_channel(path[1].to_i)
         
     | 
| 
      
 176 
     | 
    
         
            +
                            @@douban_fm.clear_mpd_playlist(@@remote_host, @@remote_port)
         
     | 
| 
      
 177 
     | 
    
         
            +
                            raise WEBrick::HTTPStatus::OK
         
     | 
| 
      
 178 
     | 
    
         
            +
                          else
         
     | 
| 
      
 179 
     | 
    
         
            +
                            raise WEBrick::HTTPStatus::NotFound
         
     | 
| 
      
 180 
     | 
    
         
            +
                          end
         
     | 
| 
      
 181 
     | 
    
         
            +
                        else
         
     | 
| 
      
 182 
     | 
    
         
            +
                          raise WEBrick::HTTPStatus::NotFound
         
     | 
| 
      
 183 
     | 
    
         
            +
                        end
         
     | 
| 
      
 184 
     | 
    
         
            +
                      end
         
     | 
| 
       108 
185 
     | 
    
         
             
                    end
         
     | 
| 
       109 
186 
     | 
    
         | 
| 
       110 
     | 
    
         
            -
                     
     | 
| 
      
 187 
     | 
    
         
            +
                    servletClass.remote_host = options.remote_host
         
     | 
| 
      
 188 
     | 
    
         
            +
                    servletClass.remote_port = options.remote_port
         
     | 
| 
       111 
189 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                     
     | 
| 
       113 
     | 
    
         
            -
                       
     | 
| 
      
 190 
     | 
    
         
            +
                    Thread.new do
         
     | 
| 
      
 191 
     | 
    
         
            +
                      server = WEBrick::HTTPServer.new(:Port => 3000)
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                      %w[INT TERM].each do |signal|
         
     | 
| 
      
 194 
     | 
    
         
            +
                        trap(signal) do
         
     | 
| 
      
 195 
     | 
    
         
            +
                          server.shutdown
         
     | 
| 
      
 196 
     | 
    
         
            +
                          Thread.main.kill # die hard
         
     | 
| 
      
 197 
     | 
    
         
            +
                        end
         
     | 
| 
      
 198 
     | 
    
         
            +
                      end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                      server.mount("/", servletClass)
         
     | 
| 
      
 201 
     | 
    
         
            +
                      server.start
         
     | 
| 
       114 
202 
     | 
    
         
             
                    end
         
     | 
| 
       115 
203 
     | 
    
         
             
                  end
         
     | 
| 
       116 
     | 
    
         
            -
                end
         
     | 
| 
       117 
204 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
                   
     | 
| 
       124 
     | 
    
         
            -
                  sleep 10
         
     | 
| 
      
 205 
     | 
    
         
            +
                  # there are a lot more chances to get stack overflow in this mode,
         
     | 
| 
      
 206 
     | 
    
         
            +
                  # so can't use the proc way
         
     | 
| 
      
 207 
     | 
    
         
            +
                  while true
         
     | 
| 
      
 208 
     | 
    
         
            +
                    @@douban_fm.add_to_mpd(options.remote_host, options.remote_port)
         
     | 
| 
      
 209 
     | 
    
         
            +
                    sleep 10
         
     | 
| 
      
 210 
     | 
    
         
            +
                  end
         
     | 
| 
       125 
211 
     | 
    
         
             
                end
         
     | 
| 
       126 
212 
     | 
    
         
             
              end
         
     | 
| 
       127 
213 
     | 
    
         
             
            end
         
     | 
| 
       128 
214 
     | 
    
         | 
| 
       129 
     | 
    
         
            -
            main
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
      
 215 
     | 
    
         
            +
            DoubanFMCLI.new.main
         
     | 
| 
       131 
216 
     | 
    
         
             
            sleep
         
     | 
    
        data/lib/douban.fm/douban_fm.rb
    CHANGED
    
    | 
         @@ -97,7 +97,17 @@ module DoubanFM 
     | 
|
| 
       97 
97 
     | 
    
         
             
                end
         
     | 
| 
       98 
98 
     | 
    
         | 
| 
       99 
99 
     | 
    
         
             
                def add_to_mpd(host = 'localhost', port = 6600)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  if host.nil?
         
     | 
| 
      
 101 
     | 
    
         
            +
                    host = 'localhost'
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
                  if port.nil?
         
     | 
| 
      
 104 
     | 
    
         
            +
                    port = 6600
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
       100 
107 
     | 
    
         
             
                  mpd = MPD.new(host, port)
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  @logger.log("connecting to mpd at #{host}:#{port}")
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
       101 
111 
     | 
    
         
             
                  mpd.connect
         
     | 
| 
       102 
112 
     | 
    
         | 
| 
       103 
113 
     | 
    
         
             
                  # remove after played
         
     | 
| 
         @@ -143,14 +153,36 @@ module DoubanFM 
     | 
|
| 
       143 
153 
     | 
    
         
             
                      fetch_next_playlist
         
     | 
| 
       144 
154 
     | 
    
         
             
                    end
         
     | 
| 
       145 
155 
     | 
    
         | 
| 
       146 
     | 
    
         
            -
                     
     | 
| 
      
 156 
     | 
    
         
            +
                    add_current_playlist_to_mpd(mpd)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
       147 
158 
     | 
    
         | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
      
 159 
     | 
    
         
            +
                  mpd.disconnect
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
       150 
161 
     | 
    
         | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
                     
     | 
| 
      
 162 
     | 
    
         
            +
                def clear_mpd_playlist(host = 'localhost', port = 6600)
         
     | 
| 
      
 163 
     | 
    
         
            +
                  if host.nil?
         
     | 
| 
      
 164 
     | 
    
         
            +
                    host = 'localhost'
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end
         
     | 
| 
      
 166 
     | 
    
         
            +
                  if port.nil?
         
     | 
| 
      
 167 
     | 
    
         
            +
                    port = 6600
         
     | 
| 
      
 168 
     | 
    
         
            +
                  end
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                  mpd = MPD.new(host, port)
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  @logger.log("connecting to mpd at #{host}:#{port}")
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                  mpd.connect
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                  @logger.log('crop or clear current playlist')
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                  status = mpd.status
         
     | 
| 
      
 179 
     | 
    
         
            +
                  mpd.clear # this will stop mpd if it is playing
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  fetch_next_playlist
         
     | 
| 
      
 182 
     | 
    
         
            +
                  add_current_playlist_to_mpd(mpd)
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                  if status[:state] == :play
         
     | 
| 
      
 185 
     | 
    
         
            +
                    mpd.play
         
     | 
| 
       154 
186 
     | 
    
         
             
                  end
         
     | 
| 
       155 
187 
     | 
    
         | 
| 
       156 
188 
     | 
    
         
             
                  mpd.disconnect
         
     | 
| 
         @@ -166,5 +198,30 @@ module DoubanFM 
     | 
|
| 
       166 
198 
     | 
    
         
             
                    end
         
     | 
| 
       167 
199 
     | 
    
         
             
                  end
         
     | 
| 
       168 
200 
     | 
    
         
             
                end
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                private
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                def add_current_playlist_to_mpd(mpd)
         
     | 
| 
      
 205 
     | 
    
         
            +
                  @logger.log("add more songs to mpd")
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                  @current_playlist['song'].each do |song|
         
     | 
| 
      
 208 
     | 
    
         
            +
                    @logger.log("send [#{song['url'].gsub('\\', '')}] to mpd")
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                    mpd.add(song['url'].gsub('\\', ''))
         
     | 
| 
      
 211 
     | 
    
         
            +
                  end
         
     | 
| 
      
 212 
     | 
    
         
            +
                end
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                # currently not used
         
     | 
| 
      
 215 
     | 
    
         
            +
                def crop(mpd, status)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  total = status[:playlistlength]
         
     | 
| 
      
 217 
     | 
    
         
            +
                  current = status[:song]
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  total.downto(current + 2) do |i|
         
     | 
| 
      
 220 
     | 
    
         
            +
                    mpd.delete(i)
         
     | 
| 
      
 221 
     | 
    
         
            +
                  end
         
     | 
| 
      
 222 
     | 
    
         
            +
                  current.downto(1) do |i|
         
     | 
| 
      
 223 
     | 
    
         
            +
                    mpd.delete(i)
         
     | 
| 
      
 224 
     | 
    
         
            +
                  end
         
     | 
| 
      
 225 
     | 
    
         
            +
                end
         
     | 
| 
       169 
226 
     | 
    
         
             
              end  
         
     | 
| 
       170 
227 
     | 
    
         
             
            end
         
     | 
    
        data/lib/douban.fm/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: douban.fm
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.1
         
     | 
| 
       5 
5 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
         @@ -9,11 +9,11 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2013-01- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2013-01-18 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: ruby-mpd
         
     | 
| 
       16 
     | 
    
         
            -
              requirement: & 
     | 
| 
      
 16 
     | 
    
         
            +
              requirement: &70103937077020 !ruby/object:Gem::Requirement
         
     | 
| 
       17 
17 
     | 
    
         
             
                none: false
         
     | 
| 
       18 
18 
     | 
    
         
             
                requirements:
         
     | 
| 
       19 
19 
     | 
    
         
             
                - - =
         
     | 
| 
         @@ -21,10 +21,10 @@ dependencies: 
     | 
|
| 
       21 
21 
     | 
    
         
             
                    version: 0.1.5
         
     | 
| 
       22 
22 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       23 
23 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       24 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 24 
     | 
    
         
            +
              version_requirements: *70103937077020
         
     | 
| 
       25 
25 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       26 
26 
     | 
    
         
             
              name: highline
         
     | 
| 
       27 
     | 
    
         
            -
              requirement: & 
     | 
| 
      
 27 
     | 
    
         
            +
              requirement: &70103937076420 !ruby/object:Gem::Requirement
         
     | 
| 
       28 
28 
     | 
    
         
             
                none: false
         
     | 
| 
       29 
29 
     | 
    
         
             
                requirements:
         
     | 
| 
       30 
30 
     | 
    
         
             
                - - =
         
     | 
| 
         @@ -32,7 +32,7 @@ dependencies: 
     | 
|
| 
       32 
32 
     | 
    
         
             
                    version: 1.6.15
         
     | 
| 
       33 
33 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       34 
34 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       35 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 35 
     | 
    
         
            +
              version_requirements: *70103937076420
         
     | 
| 
       36 
36 
     | 
    
         
             
            description: douban.fm
         
     | 
| 
       37 
37 
     | 
    
         
             
            email:
         
     | 
| 
       38 
38 
     | 
    
         
             
            - hxliang1982@gmail.com
         
     |