Author: duncan
Date: Wed Sep 12 14:11:33 2007
New Revision: 9870

Log:
[ 1783643 ] Youtube / URL downloader webserver plugin.
Update from Don Lock added


Added:
   branches/rel-1/freevo/src/www/htdocs/downloadurl.py   (contents, props 
changed)
   branches/rel-1/freevo/src/www/htdocs/youtube-dl   (contents, props changed)
   branches/rel-1/freevo/src/www/htdocs/youtube.js   (contents, props changed)
Modified:
   branches/rel-1/freevo/ChangeLog
   branches/rel-1/freevo/src/www/htdocs/youtube.rpy

Modified: branches/rel-1/freevo/ChangeLog
==============================================================================
--- branches/rel-1/freevo/ChangeLog     (original)
+++ branches/rel-1/freevo/ChangeLog     Wed Sep 12 14:11:33 2007
@@ -19,8 +19,9 @@
  * New Afrikaans translation (F#1790781)
  * Updated German translation (F#1770195)
  * New Eject CD-ROM plug-in, adding a menu item to the drive menu (F#1773418)
- * New Text Entry and Program Search (F#1768790)
- * New youtube plug-in for the webserver (F#1783643)
+ * New lastfm menu plug-in (F#1792494)
+ * New text entry and program search (F#1768790)
+ * New youtube plug-in for the webserver (F#1783643,F#1792819)
  * Updated lyrics grabber for scrollable lyrics (F#1786313)
  * Updated the LCD plug-in to allow a 16x4 mode (F#1776450)
  * Updated alsamixer with event args and synchronous mixer control (F#1767928)

Added: branches/rel-1/freevo/src/www/htdocs/downloadurl.py
==============================================================================
--- (empty file)
+++ branches/rel-1/freevo/src/www/htdocs/downloadurl.py Wed Sep 12 14:11:33 2007
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+
+__author__="Andrew Pennebaker ([EMAIL PROTECTED])"
+__date__="3 Nov 2005 - 14 Feb 2007"
+__copyright__="Copyright 2006 2007 Andrew Pennebaker"
+__license__="GPL"
+__version__="0.5"
+__URL__="http://snippets.dzone.com/posts/show/2887";
+
+from urllib import urlopen
+import os
+import math
+import time
+import sys
+from getopt import getopt
+
+def optimum_k_exp(num_bytes):
+    const_1k = 1024
+    if num_bytes == 0:
+        return 0
+    return long(math.log(num_bytes, const_1k))
+
+def format_bytes(num_bytes):
+    const_1k = 1024
+    try:
+        exp = optimum_k_exp(num_bytes)
+        suffix = 'bkMGTPEZY'[exp]
+        if exp == 0:
+            return '%s%s' % (num_bytes, suffix)
+        converted = float(num_bytes) / float(const_1k**exp)
+        return '%.2f%s' % (converted, suffix)
+    except IndexError:
+        sys.exit('Error: internal error formatting number of bytes.')
+
+
+# Calculate ETA and return it in string format as MM:SS
+def calc_eta(start, now, total, current):
+    if current == 0:
+        return '--:--'
+    rate = float(current) / (now - start)
+    eta = long((total - current) / rate)
+    eta_mins = eta / 60
+    eta_secs = eta % 60
+    if eta_mins > 99:
+        return '--:--'
+    return '%02d:%02d' % (eta_mins, eta_secs)
+
+# Calculate speed and return it in string format
+def calc_speed(start, now, bytes):
+    if bytes == 0:
+        return 'N/A b'
+    return format_bytes(float(bytes) / (now - start))
+
+def cond_print(str):
+    sys.stdout.write(str)
+    sys.stdout.flush()
+
+def getURLName(url):
+    name = url.split("/")[-1]
+    return name
+
+def createDownload(url, proxy=None):
+    instream=urlopen(url, None, proxy)
+
+    filename=instream.info().getheader("Content-Length")
+    if filename==None:
+        filename="temp"
+
+    return (instream, filename)
+
+def download(instream, outstream):
+    outstream.write(instream.read())
+
+    outstream.close()
+
+def usage():
+    print "Usage: %s [options] <url1 url2 url3 ...>" % (sys.argv[0])
+    print "\n--httpproxy <proxy>"
+    print "--ftpproxy <proxy>"
+    print "--gopherproxy <proxy>"
+    print "\n--help (usage)"
+
+    sys.exit()
+
+def main():
+    systemArgs=sys.argv[1:] # ignore program name
+    start_time = time.time()
+
+    urls=[]
+    proxies={}
+
+    optlist=[]
+    args=[]
+
+    try:
+        optlist, args=getopt(systemArgs, None, ["url=", "httpproxy=", 
"ftpproxy=", "gopherproxy=", "help"])
+    except Exception, e:
+        usage()
+
+    if len(args)<1:
+        usage()
+
+    for option, value in optlist:
+        if option=="--help":
+            usage()
+
+        elif option=="--httpproxy":
+            proxies["http"]=value
+        elif option=="--ftpproxy":
+            proxies["ftp"]=value
+        elif options=="--gopherproxy":
+            proxies["gopher"]=value
+
+    urls=args
+
+    for url in urls:
+
+        outfile = getURLName(url)
+        print outfile
+        fileName= outfile.split(os.sep)[-1]
+        fName = fileName
+        fileName= "partfile" + fileName
+        print "fName - " + fName
+        print "fileName - " + fileName
+
+#               try:
+
+        outfile=open(fileName, "wb")
+        url, length=createDownload(url, proxies)
+        if not length:
+            length="?"
+
+        print "Downloading %s (%s bytes) ..." % (url.url, length)
+        if length!="?":
+            length=float(length)
+        bytesRead=0.0
+
+        for line in url:
+            bytesRead+=len(line)
+
+            if length!="?":
+                status = "%s: %.02f/%.02f kb (%d%%)" % (
+                        fileName,
+                        bytesRead/1024.0,
+                        length/1024.0,
+                        100*bytesRead/length
+                )
+                percent = (100*bytesRead/length)
+                percent_str = '%.1f' % percent
+                counter = format_bytes(bytesRead)
+                video_len_str = format_bytes(length)
+                speed = calc_speed(start_time,time.time(),bytesRead)
+                eta = calc_eta(start_time, time.time(), length, bytesRead)
+                cond_print('\rRetrieving video data: %5s%% (%8s of %s) at %s 
ETA %s ' % (percent_str, counter, video_len_str,speed,eta))
+#                               print status
+
+            outfile.write(line)
+
+        url.close()
+        outfile.close()
+
+#               except Exception, e:
+#                       print "Error downloading %s: %s" % (url, e)
+        os.rename(fileName,fName)
+
+
+
+if __name__=="__main__":
+    main()

Added: branches/rel-1/freevo/src/www/htdocs/youtube-dl
==============================================================================
--- (empty file)
+++ branches/rel-1/freevo/src/www/htdocs/youtube-dl     Wed Sep 12 14:11:33 2007
@@ -0,0 +1,405 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2006-2007 Ricardo Garcia Gonzalez
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+# 
+# Except as contained in this notice, the name(s) of the above copyright
+# holders shall not be used in advertising or otherwise to promote the
+# sale, use or other dealings in this Software without prior written
+# authorization.
+#
+import getpass
+import httplib
+import math
+import netrc
+import optparse
+import os
+import re
+import socket
+import string
+import sys
+import time
+import urllib2
+
+# Global constants
+const_video_url_str = 'http://www.youtube.com/watch?v=%s'
+const_video_url_re = 
re.compile(r'^((?:http://)?(?:\w+\.)?youtube\.com/(?:v/|(?:watch(?:\.php)?)?\?(?:.+&)?v=))?([0-9A-Za-z_-]+)(?(1)[&/].*)?$')
+const_login_url_str = 'http://www.youtube.com/login?next=/watch%%3Fv%%3D%s'
+const_login_post_str = 
'current_form=loginForm&next=%%2Fwatch%%3Fv%%3D%s&username=%s&password=%s&action_login=Log+In'
+const_age_url_str = 
'http://www.youtube.com/verify_age?next_url=/watch%%3Fv%%3D%s'
+const_age_post_str = 'next_url=%%2Fwatch%%3Fv%%3D%s&action_confirm=Confirm'
+const_url_t_param_re = re.compile(r'[,{]t:\'([^\']*)\'')
+const_video_url_real_str = 'http://www.youtube.com/get_video?video_id=%s&t=%s'
+const_video_title_re = re.compile(r'<title>YouTube - ([^<]*)</title>', re.M | 
re.I)
+const_1k = 1024
+const_initial_block_size = 10 * const_1k
+
+# Print error message, followed by standard advice information, and then exit
+def error_advice_exit(error_text):
+       sys.stderr.write('Error: %s.\n' % error_text)
+       sys.stderr.write('Try again several times. It may be a temporary 
problem.\n')
+       sys.stderr.write('Other typical problems:\n\n')
+       sys.stderr.write('* Video no longer exists.\n')
+       sys.stderr.write('* Video requires age confirmation but you did not 
provide an account.\n')
+       sys.stderr.write('* You provided the account data, but it is not 
valid.\n')
+       sys.stderr.write('* The connection was cut suddenly for some reason.\n')
+       sys.stderr.write('* YouTube changed their system, and the program no 
longer works.\n')
+       sys.stderr.write('\nTry to confirm you are able to view the video using 
a web browser.\n')
+       sys.stderr.write('Use the same video URL and account information, if 
needed, with this program.\n')
+       sys.stderr.write('When using a proxy, make sure http_proxy has 
http://host:port format.\n')
+       sys.stderr.write('Try again several times and contact me if the problem 
persists.\n')
+       sys.exit('\n')
+
+# Wrapper to create custom requests with typical headers
+def request_create(url, data=None):
+       retval = urllib2.Request(url)
+       if data is not None:
+               retval.add_data(data)
+       # Try to mimic Firefox, at least a little bit
+       retval.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 
5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0')
+       retval.add_header('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7')
+       retval.add_header('Accept', 
'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5')
+       retval.add_header('Accept-Language', 'en-us,en;q=0.5')
+       return retval
+
+# Perform a request, process headers and return response
+def perform_request(url, data=None):
+       request = request_create(url, data)
+       response = urllib2.urlopen(request)
+       return response
+
+# Conditional print
+def cond_print(str):
+       global cmdl_opts
+       if not (cmdl_opts.quiet or cmdl_opts.get_url):
+               sys.stdout.write(str)
+               sys.stdout.flush()
+
+# Title string normalization
+def title_string_norm(title):
+       title = ''.join((x in string.ascii_letters or x in string.digits) and x 
or ' ' for x in title)
+       title = '_'.join(title.split())
+       title = title.lower()
+       return title
+
+# Title string minimal transformation
+def title_string_touch(title):
+       return title.replace(os.sep, '%')
+
+# Generic download step
+def download_step(return_data_flag, step_title, step_error, url, 
post_data=None):
+       try:
+               cond_print('%s... ' % step_title)
+               data = perform_request(url, post_data).read()
+               cond_print('done.\n')
+               if return_data_flag:
+                       return data
+               return None
+
+       except (urllib2.URLError, ValueError, httplib.HTTPException, TypeError, 
socket.error):
+               cond_print('failed.\n')
+               error_advice_exit(step_error)
+
+       except KeyboardInterrupt:
+               sys.exit('\n')
+
+# Generic extract step
+def extract_step(step_title, step_error, regexp, data):
+       try:
+               cond_print('%s... ' % step_title)
+               match = regexp.search(data)
+               
+               if match is None:
+                       cond_print('failed.\n')
+                       error_advice_exit(step_error)
+               
+               extracted_data = match.group(1)
+               cond_print('done.\n')
+               return extracted_data
+       
+       except KeyboardInterrupt:
+               sys.exit('\n')
+
+# Calculate new block size based on previous block size
+def new_block_size(before, after, bytes):
+       new_min = max(bytes / 2.0, 1.0)
+       new_max = max(bytes * 2.0, 1.0)
+       dif = after - before
+       if dif < 0.0001:
+               return int(new_max)
+       rate = bytes / dif
+       if rate > new_max:
+               return int(new_max)
+       if rate < new_min:
+               return int(new_min)
+       return int(rate)
+
+# Get optimum 1k exponent to represent a number of bytes
+def optimum_k_exp(num_bytes):
+       global const_1k
+       if num_bytes == 0:
+               return 0
+       return long(math.log(num_bytes, const_1k))
+
+# Get optimum representation of number of bytes
+def format_bytes(num_bytes):
+       global const_1k
+       try:
+               exp = optimum_k_exp(num_bytes)
+               suffix = 'bkMGTPEZY'[exp]
+               if exp == 0:
+                       return '%s%s' % (num_bytes, suffix)
+               converted = float(num_bytes) / float(const_1k**exp)
+               return '%.2f%s' % (converted, suffix)
+       except IndexError:
+               sys.exit('Error: internal error formatting number of bytes.')
+
+# Calculate ETA and return it in string format as MM:SS
+def calc_eta(start, now, total, current):
+       if current == 0:
+               return '--:--'
+       rate = float(current) / (now - start)
+       eta = long((total - current) / rate)
+       eta_mins = eta / 60
+       eta_secs = eta % 60
+       if eta_mins > 99:
+               return '--:--'
+       return '%02d:%02d' % (eta_mins, eta_secs)
+
+# Calculate speed and return it in string format
+def calc_speed(start, now, bytes):
+       if bytes == 0:
+               return 'N/A b'
+       return format_bytes(float(bytes) / (now - start))
+
+# Create the command line options parser and parse command line
+cmdl_usage = 'usage: %prog [options] video_url'
+cmdl_version = '2007.08.24'
+cmdl_parser = optparse.OptionParser(usage=cmdl_usage, version=cmdl_version, 
conflict_handler='resolve')
+cmdl_parser.add_option('-h', '--help', action='help', help='print this help 
text and exit')
+cmdl_parser.add_option('-v', '--version', action='version', help='print 
program version and exit')
+cmdl_parser.add_option('-u', '--username', dest='username', 
metavar='USERNAME', help='account username')
+cmdl_parser.add_option('-p', '--password', dest='password', 
metavar='PASSWORD', help='account password')
+cmdl_parser.add_option('-o', '--output', dest='outfile', metavar='FILE', 
help='output video file name')
+cmdl_parser.add_option('-q', '--quiet', action='store_true', dest='quiet', 
help='activates quiet mode')
+cmdl_parser.add_option('-s', '--simulate', action='store_true', 
dest='simulate', help='do not download video')
+cmdl_parser.add_option('-t', '--title', action='store_true', dest='use_title', 
help='use title in file name')
+cmdl_parser.add_option('-l', '--literal', action='store_true', 
dest='use_literal', help='use literal title in file name')
+cmdl_parser.add_option('-n', '--netrc', action='store_true', dest='use_netrc', 
help='use .netrc authentication data')
+cmdl_parser.add_option('-g', '--get-url', action='store_true', dest='get_url', 
help='print final video URL only')
+cmdl_parser.add_option('-2', '--title-too', action='store_true', 
dest='get_title', help='used with -g, print title too')
+cmdl_parser.add_option('-L','--logfile', action='store_true', dest='log_file', 
help='used to redirect output messages')
+
+(cmdl_opts, cmdl_args) = cmdl_parser.parse_args()
+
+# Get video URL
+if len(cmdl_args) != 1:
+       cmdl_parser.print_help()
+       sys.exit('\n')
+video_url_cmdl = cmdl_args[0]
+
+# Verify video URL format and convert to "standard" format
+video_url_mo = const_video_url_re.match(video_url_cmdl)
+if video_url_mo is None:
+       sys.exit('Error: URL does not seem to be a youtube video URL. If it is, 
report a bug.')
+video_url_id = video_url_mo.group(2)
+video_url = const_video_url_str % video_url_id
+
+# Check conflicting options
+if cmdl_opts.outfile is not None and (cmdl_opts.simulate or cmdl_opts.get_url):
+       sys.stderr.write('Warning: video file name given but will not be 
used.\n')
+
+if cmdl_opts.outfile is not None and (cmdl_opts.use_title or 
cmdl_opts.use_literal):
+       sys.exit('Error: using the video title conflicts with using a given 
file name.')
+
+if cmdl_opts.use_netrc and cmdl_opts.password is not None:
+       sys.exit('Error: using netrc conflicts with giving command line 
password.')
+
+if cmdl_opts.use_title and cmdl_opts.use_literal:
+       sys.exit('Error: cannot use title and literal title at the same time.')
+
+if cmdl_opts.quiet and cmdl_opts.get_url:
+       sys.exit('Error: cannot be quiet and print final URL at the same time.')
+
+# Incorrect option formatting
+if cmdl_opts.username is None and cmdl_opts.password is not None:
+       sys.exit('Error: password give but username is missing.')
+
+if cmdl_opts.get_url is None and cmdl_opts.get_title is not None:
+       sys.exit('Error: getting title requires getting URL.')
+
+# Get account information if any
+account_username = None
+account_password = None
+
+if cmdl_opts.use_netrc:
+       try:
+               info = netrc.netrc().authenticators('youtube')
+               if info is None:
+                       sys.exit('Error: no authenticators for machine 
youtube.')
+               netrc_username = info[0]
+               netrc_password = info[2]
+       except IOError:
+               sys.exit('Error: unable to read .netrc file.')
+       except netrc.NetrcParseError:
+               sys.exit('Error: unable to parse .netrc file.')
+
+if cmdl_opts.password is not None:
+       account_username = cmdl_opts.username
+       account_password = cmdl_opts.password
+else:
+       if cmdl_opts.username is not None and cmdl_opts.use_netrc:
+               if cmdl_opts.username != netrc_username:
+                       sys.exit('Error: conflicting username from .netrc and 
command line options.')
+               account_username = cmdl_opts.username
+               account_password = netrc_password
+       elif cmdl_opts.username is not None:
+               account_username = cmdl_opts.username
+               account_password = getpass.getpass('Type YouTube password and 
press return: ')
+       elif cmdl_opts.use_netrc:
+               if len(netrc_username) == 0:
+                       sys.exit('Error: empty username in .netrc file.')
+               account_username = netrc_username
+               account_password = netrc_password
+
+# Get output file name 
+if cmdl_opts.outfile is None:
+       video_filename = '%s.flv' % video_url_id
+else:
+       video_filename = cmdl_opts.outfile
+
+# Check name
+if not video_filename.lower().endswith('.flv'):
+       sys.stderr.write('Warning: video file name does not end in .flv\n')
+
+# Test writable file
+if not (cmdl_opts.simulate or cmdl_opts.get_url):
+       try:
+               disk_test = open(video_filename, 'wb')
+               disk_test.close()
+
+       except (OSError, IOError):
+               sys.exit('Error: unable to open %s for writing.' % 
video_filename)
+
+# Install cookie and proxy handlers
+urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()))
+urllib2.install_opener(urllib2.build_opener(urllib2.HTTPCookieProcessor()))
+
+# Log in and confirm age if needed
+if account_username is not None:
+       url = const_login_url_str % video_url_id
+       post = const_login_post_str % (video_url_id, account_username, 
account_password)
+       download_step(False, 'Logging in', 'unable to log in', url, post)
+
+       url = const_age_url_str % video_url_id
+       post = const_age_post_str % video_url_id
+       download_step(False, 'Confirming age', 'unable to confirm age', url, 
post)
+
+# Retrieve video webpage
+video_webpage = download_step(True, 'Retrieving video webpage', 'unable to 
retrieve video webpage', video_url)
+
+# Extract video title if needed
+if cmdl_opts.use_title or cmdl_opts.use_literal or cmdl_opts.get_title:
+       video_title = extract_step('Extracting video title', 'unable to extract 
video title', const_video_title_re, video_webpage)
+
+# Extract needed video URL parameters
+video_url_t_param = extract_step('Extracting URL "t" parameter', 'unable to 
extract URL "t" parameter', const_url_t_param_re, video_webpage)
+video_url_real = const_video_url_real_str % (video_url_id, video_url_t_param)
+
+# Retrieve video data
+try:
+       video_data = perform_request(video_url_real)
+       cond_print('Video data found at %s\n' % video_data.geturl())
+
+       if cmdl_opts.get_title:
+               print video_title
+
+       if cmdl_opts.get_url:
+               print video_data.geturl()
+
+       if cmdl_opts.simulate or cmdl_opts.get_url:
+               sys.exit()
+
+       video_file = open(video_filename, 'wb')
+       try:
+               video_len = long(video_data.info()['Content-length'])
+               video_len_str = format_bytes(video_len)
+       except KeyError:
+               video_len = None
+               video_len_str = 'N/A'
+
+       byte_counter = 0
+       block_size = const_initial_block_size
+       start_time = time.time()
+       while True:
+               if video_len is not None:
+                       percent = float(byte_counter) / float(video_len) * 100.0
+                       percent_str = '%.1f' % percent
+                       eta_str = calc_eta(start_time, time.time(), video_len, 
byte_counter)
+               else:
+                       percent_str = '---.-'
+                       eta_str = '--:--'
+               counter = format_bytes(byte_counter)
+               speed_str = calc_speed(start_time, time.time(), byte_counter)
+               cond_print('\rRetrieving video data: %5s%% (%8s of %s) at %8s/s 
ETA %s ' % (percent_str, counter, video_len_str, speed_str, eta_str))
+
+               before = time.time()
+               video_block = video_data.read(block_size)
+               after = time.time()
+               dl_bytes = len(video_block)
+               if dl_bytes == 0:
+                       break
+               byte_counter += dl_bytes
+               video_file.write(video_block)
+               block_size = new_block_size(before, after, dl_bytes)
+
+       if video_len is not None and byte_counter != video_len:
+               error_advice_exit('server did not send the expected ammount of 
data')
+
+       video_file.close()
+       cond_print('done.\n')
+       cond_print('Video data saved to %s\n' % video_filename)
+
+except (urllib2.URLError, ValueError, httplib.HTTPException, TypeError, 
socket.error):
+       cond_print('failed.\n')
+       error_advice_exit('unable to download video data')
+
+except KeyboardInterrupt:
+       sys.exit('\n')
+
+# Rename video file if needed
+if cmdl_opts.use_title or cmdl_opts.use_literal:
+       try:
+               if cmdl_opts.use_title:
+                       prefix = title_string_norm(video_title)
+               else:
+                       prefix = title_string_touch(video_title)
+               final_filename = '%s-%s.flv' % (prefix, video_url_id)
+               os.rename(video_filename, final_filename)
+               cond_print('Video file renamed to %s\n' % final_filename)
+       
+       except OSError:
+               sys.stderr.write('Warning: unable to rename file.\n')
+
+       except KeyboardInterrupt:
+               sys.exit('\n')
+
+# Finish
+sys.exit()

Added: branches/rel-1/freevo/src/www/htdocs/youtube.js
==============================================================================
--- (empty file)
+++ branches/rel-1/freevo/src/www/htdocs/youtube.js     Wed Sep 12 14:11:33 2007
@@ -0,0 +1,187 @@
+//enter refresh time in "minutes:seconds" Minutes should range from 0 to 
inifinity. Seconds should range from 0 to 59'
+//var limit="0:10"
+if (document.images){
+  var parselimit=5
+}
+
+function beginrefresh(){
+  if (!document.images)
+     return
+  if (parselimit==1) {
+       document.refreshForm.visited.value = "-1";
+       makeRequest('youtube.rpy?xml=1');
+       parselimit=5
+       setTimeout("beginrefresh()",1000)
+  }
+  else{ 
+     parselimit-=1
+     document.refreshForm.visited.value = parselimit
+     curmin=Math.floor(parselimit/60)
+     cursec=parselimit%60
+     if (curmin!=0)
+         curtime=curmin+" minutes and "+cursec+" seconds left until page 
refresh!"
+     else
+         curtime=cursec+" seconds left until page refresh!"
+     window.status=curtime
+     setTimeout("beginrefresh()",1000)
+  }
+}
+window.onload=beginrefresh
+
+function makeRequest(url) {
+    var httpRequest;
+
+    if (window.XMLHttpRequest) { // Mozilla, Safari, ...
+        httpRequest = new XMLHttpRequest();
+        if (httpRequest.overrideMimeType) {
+            httpRequest.overrideMimeType('text/xml');
+            // See note below about this line
+        }
+    } 
+    else if (window.ActiveXObject) { // IE
+        try {
+            httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
+        } 
+        catch (e) {
+            try {
+                httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
+            } 
+        catch (e) {}
+        }
+    }
+
+    if (!httpRequest) {
+        alert('Giving up :( Cannot create an XMLHTTP instance');
+        return false;
+    }
+    httpRequest.onreadystatechange = function() { alertContents(httpRequest); 
};
+    httpRequest.open('GET', url, true);
+    httpRequest.send('');
+
+}
+
+function TableAddRow(file,filesize,percent,amtdone,speed,eta) {
+    var tbl,lastrow,newrow,cellLeft;
+    var textNode;
+
+    tbl = document.getElementById("filelist")
+    lastrow = tbl.rows.length;
+    newrow = tbl.insertRow(lastrow);
+    newrow.id = file
+    newrow.className = "chanrow"
+
+    cellLeft = newrow.insertCell(0);
+    textNode = document.createTextNode("Delete");
+    cellLeft.appendChild(textNode);
+    cellLeft.className = "basic"
+
+    cellLeft = newrow.insertCell(1);
+    textNode = document.createTextNode(file);
+    cellLeft.appendChild(textNode);
+    cellLeft.className = "basic"
+
+    cellLeft = newrow.insertCell(2);
+    textNode = document.createTextNode(percent);
+    cellLeft.appendChild(textNode);
+    cellLeft.id = file + ".PERCENT"
+    cellLeft.className = "basic"
+
+    cellLeft = newrow.insertCell(3);
+    textNode = document.createTextNode(amtdone);
+    cellLeft.appendChild(textNode);
+    cellLeft.id = file + ".SOFAR"
+    cellLeft.className = "basic"
+
+    cellLeft = newrow.insertCell(4);
+    textNode = document.createTextNode(filesize);
+    cellLeft.appendChild(textNode);
+    cellLeft.id = file + ".FILESIZE"
+    cellLeft.className = "basic"
+
+    cellLeft = newrow.insertCell(5);
+    textNode = document.createTextNode(speed);
+    cellLeft.appendChild(textNode);
+    cellLeft.id = file + ".SPEED"
+    cellLeft.className = "basic"
+
+    cellLeft = newrow.insertCell(6);
+    textNode = document.createTextNode(eta);
+    cellLeft.appendChild(textNode);
+    cellLeft.id = file + ".ETA"
+    cellLeft.className = "basic"
+
+    lastrow = tbl.rows.length;
+}
+
+function RemoveRows(lfiles) {
+    var tbl,r,cnt,rfile,fnd,xfile ;
+    tbl = document.getElementById("filelist");
+    
+    for (r=1; r < tbl.rows.length; r++) {
+        rfile = tbl.rows[r].id
+        fnd = 0
+        for (j=0; j < lfiles.childNodes.length; j++) {
+            cfile = lfiles.childNodes[j]
+            xfile = cfile.childNodes[0].firstChild.nodeValue;
+            if (xfile == rfile) {
+                fnd = 1
+                j = lfiles.childNodes.length
+            }
+        }
+        if (fnd == 0) {
+            fnd = 1;
+            tbl.deleteRow(r);
+            //alert("Delete Row - " + rfile);
+        }
+        cnt = 0;
+    }
+    
+}
+
+function alertContents(httpRequest) {
+    var j,cellObj;
+    var cfile,filename,percent,amtdone,filesize,speed,eta;
+
+    if (httpRequest.readyState == 4) {
+        if (httpRequest.status == 200) {
+                
+            var filelist = httpRequest.responseXML.childNodes[0];
+            for (j=0; j < filelist.childNodes.length; j++) {
+                cfile = filelist.childNodes[j]
+                filename = cfile.childNodes[0].firstChild.nodeValue;
+                   
+                percent = cfile.childNodes[1].firstChild.nodeValue;
+                amtdone = cfile.childNodes[2].firstChild.nodeValue;
+                filesize = cfile.childNodes[3].firstChild.nodeValue;
+                speed = cfile.childNodes[4].firstChild.nodeValue;
+                eta = cfile.childNodes[5].firstChild.nodeValue;
+
+                // Check to see if a table row exists for the file.
+                cellObj = document.getElementById(filename + ".FILESIZE");
+                if (cellObj == null) {
+                      TableAddRow(filename,filesize,percent,amtdone,speed,eta)
+                }
+                else {
+                    cellObj = document.getElementById(filename + ".FILESIZE");
+                    cellObj.childNodes[0].nodeValue=filesize;
+                    cellObj = document.getElementById(filename + ".PERCENT");
+                    cellObj.childNodes[0].nodeValue=percent;
+                    cellObj = document.getElementById(filename + ".SOFAR");
+                    cellObj.childNodes[0].nodeValue=amtdone;
+                    cellObj = document.getElementById(filename + ".SPEED");
+                    cellObj.childNodes[0].nodeValue=speed;
+                    cellObj = document.getElementById(filename + ".ETA");
+                    cellObj.childNodes[0].nodeValue=eta;
+                }
+                    
+            }
+            RemoveRows(filelist);
+        } else {
+            alert('There was a problem with the request.');
+        }
+    }
+}
+    
+
+    
+    

Modified: branches/rel-1/freevo/src/www/htdocs/youtube.rpy
==============================================================================
--- branches/rel-1/freevo/src/www/htdocs/youtube.rpy    (original)
+++ branches/rel-1/freevo/src/www/htdocs/youtube.rpy    Wed Sep 12 14:11:33 2007
@@ -20,137 +20,287 @@
 #
 # -----------------------------------------------------------------------
 
-
 import sys
+import time
 import os
 import os.path
 import config
+import subprocess
+import string
+import math
+
 from www.web_types import HTMLResource, FreevoResource
 from urllib import urlopen
 from getopt import getopt
 
-def createDownload(url, proxy=None):
-    instream=urlopen(url, None, proxy)
+print "CONFIG====="
+print (config)
 
-    filename=instream.info().getheader("Content-Length")
-    if filename==None:
-        filename="temp"
+def xmlStatus(fstatus):
+    xmlstatus = ""
+    xmlstatus += "<PERCENT>" + fstatus['percent'] + "</PERCENT>"
+    xmlstatus += "<DOWNLOADED>" + fstatus['downloaded'] + "</DOWNLOADED>"
+    xmlstatus += "<FILESIZE>" + fstatus['filesize'] + "</FILESIZE>"
+    xmlstatus += "<SPEED>" + fstatus['speed'] + "</SPEED>"
+    xmlstatus += "<ETA>" + fstatus['eta'] + "</ETA>"
+
+    return xmlstatus
+
+# Get optimum 1k exponent to represent a number of bytes
+def optimum_k_exp(num_bytes):
+    const_1k = 1024
+    if num_bytes == 0:
+        return 0
+    return long(math.log(num_bytes, const_1k))
+
+
+# Get optimum representation of number of bytes
+def format_bytes(num_bytes):
+    const_1k = 1024
+    try:
+        exp = optimum_k_exp(num_bytes)
+        suffix = 'bkMGTPEZY'[exp]
+        if exp == 0:
+            return '%s%s' % (num_bytes, suffix)
+        converted = float(num_bytes) / float(const_1k**exp)
+        return '%.2f%s' % (converted, suffix)
+    except IndexError:
+        return "Error"
+
+
+def getStatus(ytfile):
+    fileStatus = {'percent': '--.-%', 'downloaded': 'done' , 'filesize': 
'DONE' ,'speed' : '--', 'eta' : '--:--'}
+    fileStatus['filesize'] = format_bytes(os.path.getsize(config.YOUTUBE_DIR + 
ytfile))
+    logfile = config.YOUTUBE_DIR + ".tmp/" + os.path.splitext(ytfile)[0] + 
".log"
+    if os.path.exists(logfile):
+        lfhandle = open(logfile, "r")
+        llines = lfhandle.readlines()
+        try :
+            if len(llines) == 5:
+                status = llines[4].split("\r")[-1]
+                status = status.split()
+                fileStatus['percent'] = status[3]
+                fileStatus['downloaded'] = status[5]
+                fileStatus['filesize'] = status[7].strip(")")
+                fileStatus['speed'] = status[9]
+                fileStatus['eta'] = status[11]
+            else:
+                fileStatus['percent'] = "NA"
+                fileStatus['downloaded'] = "NA"
+                fileStatus['speed'] = "NA"
+                fileStatus['eta'] = "Unknown"
+        except Exception, e:
+            fileStatus['percent'] = "NA"
+            fileStatus['downloaded'] = "NA"
+            fileStatus['speed'] = "NA"
+            fileStatus['eta'] = "Unknown"
+    return fileStatus
+
+
+def getXML():
+
+    dfiles = '<?xml version="1.0" encoding="ISO-8859-1" ?>'
+    dfiles += '<FILELIST>'
+    enablerefresh = False
+
+    filelist = os.listdir(config.YOUTUBE_DIR)
+    filelist.sort()
+    for fl in filelist :
+        if fl != ".tmp" and fl != "folder.fxd" :
+            # check for log file.
+            dfiles += '<FILE id="' + fl + '">'
+            dfiles += '<FILENAME>' + fl + '</FILENAME>'
+            fstats = getStatus(fl)
+            dfiles += xmlStatus(fstats)
+            dfiles += '</FILE>'
+    dfiles += "</FILELIST>"
+    retdfile = []
+    retdfile.append(dfiles)
+    retdfile.append(enablerefresh)
+    return retdfile
+
+def displayfiles(fvhtml):
+    fvhtml.res += ''
+    fvhtml.tableOpen('class="library" id="filelist"')
+    fvhtml.tableRowOpen('class="chanrow"')
+    fvhtml.tableCell('Current Downloads','class ="guidehead"  colspan="2"')
+    fvhtml.tableCell('% Done','class ="guidehead"  colspan="1"')
+    fvhtml.tableCell('','class ="guidehead"  colspan="1"')
+    fvhtml.tableCell('Size','class ="guidehead"  colspan="1"')
+    fvhtml.tableCell('Speed','class ="guidehead"  colspan="1"')
+    fvhtml.tableCell('ETA','class ="guidehead"  colspan="1"')
+    fvhtml.tableRowClose()
+
+    enablerefresh = False
+
+    filelist = os.listdir(config.YOUTUBE_DIR)
+    filelist.sort()
+    for fl in filelist :
+
+        # check to see if the file is currently being downloaded.
+        if fl != ".tmp" and fl != "folder.fxd" :
+
+            # check for log file.
+            flstatus = getStatus(fl)
+            fvhtml.tableRowOpen('class="chanrow" colspan="1" id="'+fl +'"')
+            fvhtml.tableCell('<a href="youtube.rpy?Delete=1&file=' + fl + 
'">DELETE</a>','class="basic" colspan="1"')
+            fvhtml.tableCell(fl,'class="basic" colspan="1"')
+            fvhtml.tableCell(flstatus['percent'],'class="basic" colspan="1" 
id="' + fl + '.PERCENT"')
+            fvhtml.tableCell(flstatus['downloaded'],'class="basic" colspan="1" 
id = "' + fl + '.SOFAR"')
+            fvhtml.tableCell(flstatus['filesize'],'class="basic" colspan="1" 
id="' + fl + '.FILESIZE"')
+            fvhtml.tableCell(flstatus['speed'],'class="basic" colspan="1" 
id="' + fl + '.SPEED"')
+            fvhtml.tableCell(flstatus['eta'],'class="basic" colspan="1" id="' 
+ fl + '.ETA"')
+            fvhtml.tableRowClose()
+
+    fvhtml.tableClose()
+    retdfile = []
+    retdfile.append(fvhtml.res)
+    retdfile.append(enablerefresh)
+    return retdfile
+
+
+def CleanupLogFiles():
+    logfiles = os.listdir(config.YOUTUBE_DIR + ".tmp/")
+
+    for lfile in logfiles:
+        # Check to see if the movie file exists.
+        vfile = config.YOUTUBE_DIR + os.path.splitext(lfile)[0] + ".flv"
+        if not os.path.exists(vfile):
+            os.remove(config.YOUTUBE_DIR + ".tmp/" + lfile)
 
-    return (instream, filename)
 
+def download_youtube(yt_url, yt_out):
 
-def getURLName(url):
-    directory=os.curdir
+    stime = time.localtime()
+    cmd = "python " + config.YOUTUBE_DL + " -t " + yt_url
+    pwdcur = os.getcwd()
+    os.chdir(config.YOUTUBE_DIR)
 
-    name="%s%s%s" % (
-        directory,
-        os.sep,
-        url.split("/")[-1]
-    )
+    # get the file name from the url.
+    logfile = config.YOUTUBE_DIR + ".tmp/" +  yt_url.split("=")[-1] + ".log"
+    ytpid = 0
+    lfile = open (logfile, "w")
+    ytpid = 
subprocess.Popen((config.YOUTUBE_DL,"-t",yt_url),universal_newlines=True,stdout=lfile).pid
+    os.chdir(pwdcur)
+    dlstatus = "<br><br>Starting download of " + yt_url + " <br>"
+    dlstatus = dlstatus + '<input type="text" name="pid" size="40" value="' + 
str(ytpid) + '" />'
 
-    print "NAME "
-    print name
-    return name
+    return dlstatus
 
-def download_url (dl_url):
-    print "Download URL - " + dl_url
-    url = dl_url
+def download_url(dl_url, dl_out):
 
-    try:
-        outfile=open(getURLName(url), "wb")
-        fileName=outfile.name.split(os.sep)[-1]
-        fileName = config.YOUTUBE_DIR + fileName
-        print "FILENAME - " + fileName
-
-        url, length=createDownload(url, None)
-        if not length:
-            length="?"
-        print "Downloading %s (%s bytes) ..." % (url.url, length)
-
-        if length!="?":
-            length=float(length)
-        bytesRead=0.0
-
-        for line in url:
-            bytesRead+=len(line)
-            outfile.write(line)
-
-        url.close()
-        outfile.close()
-        print "Done"
+    stime = time.localtime()
+    cmd = "python " + config.DOWNLOAD_DL + " " + dl_url
+    pwdcur = os.getcwd()
+    os.chdir(config.YOUTUBE_DIR)
 
-    except Exception, e:
-        return "Error downloading %s: %s" % (dl_url, e)
+    # get the file name from the url.
+    logfile = config.YOUTUBE_DIR + ".tmp/partfile" +  dl_url.split("/")[-1]
+    logfile = os.path.splitext(logfile)[0] + ".log"
+    ytpid = 0
+    lfile = open (logfile, "w")
+    ytpid = 
subprocess.Popen((config.DOWNLOAD_DL,dl_url),universal_newlines=True,stdout=lfile).pid
+    os.chdir(pwdcur)
+    dlstatus = ""
 
-    return "Done downloading - " + dl_url
+    return dlstatus
 
-def download_youtube(yt_url, yt_out):
 
-    cmd = "python " + config.YOUTUBE_DL + " -t  " + yt_url
-    pwdcur = os.getcwd()
-    pwddl = config.YOUTUBE_DIR
-    os.chdir(pwddl)
+def addPageRefresh():
 
-    cnt = 1
-    for ln in os.popen(cmd).readline():
-        print "COUNTING"
-        print cnt
-        cnt = cnt + 1
-        print ln
-
-#    child = os.popen(cmd)
-#    data = child.read()
-
-#    err = child.close()
-#    if err:
-#        raise RuntimeError, '%s failed w/ exit code %d' % (command, err)
-    os.chdir(pwdcur)
-    return "<br/><br/>Done downloading " + yt_url
+    prhtml = '<script type="text/JavaScript" 
src="scripts/youtube.js">window.onload=beginrefresh</script>'
+    prhtml += '\n<form name="refreshForm">'
+    prhtml += '\n    <div class="searchform"><br><b>Refresh In :</b>'
+    prhtml += '\n    <input type="text" name="visited" value="1" size="4" 
align="middle" />'
+    prhtml += '\n    </div>'
+    prhtml += '\n</form><br>'
+    return prhtml
 
 
 class YouTubeResource(FreevoResource):
 
     def _render(self, request):
         fv = HTMLResource()
-        fv.printHeader(_('YouTube'), 'styles/main.css',selected=_('YouTube'))
         form = request.args
 
-        # Check to see if youtube-dl script exists.
+        blxml = fv.formValue(form,"xml")
+        if blxml :
+            fdisplay = getXML()
+            fv.res += fdisplay[0]
+            return String( fv.res )
+
+        fv.printHeader(_('YouTube'), 'styles/main.css',selected=_('YouTube'))
+
+        yterrors = []
+        if (not config.__dict__.has_key('YOUTUBE_DIR')):
+            yterrors.append('Unable to Find YOUTUDE_DIR setting in 
local_conf.py')
+            yterrors.append('Add YOUTUBE_DIR = "Directory to Save Downloads." 
to your local_conf.py')
+            config.YOUTUBE_DIR = "MISSING"
+        if (not config.__dict__.has_key('YOUTUBE_DL')):
+            yterrors.append('Unable to Find YOUTUDE_DL setting in 
local_conf.py')
+            yterrors.append('Add YOUTUBE_DL = "Path to youtube-dl script" to 
your local_conf.py')
+            config.YOUTUBE_DL = "MISSING"
+        if (not config.__dict__.has_key('DOWNLOAD_DL')):
+            yterrors.append('Unable to Find DOWNLOAD_DL setting in 
local_conf.py')
+            yterrors.append('Add DOWNLOAD_DL = "Path to downloadurl.py script" 
to your local_conf.py')
+            config.DOWNLOAD_DL = "MISSING"
+
+        if len(yterrors) > 0:
+            fv.printMessages(yterrors)
+            return String( fv.res )
+
+
+        fldelete = fv.formValue(form,'Delete')
+        if fldelete:
+            filename = fv.formValue(form,'file')
+            if filename:
+                filename = config.YOUTUBE_DIR + filename
+                if os.path.exists(filename):
+                    os.remove(filename)
+                    fv.res += "DELETED FILE - " + filename
+
+        yturl = ""
         if not os.path.exists(config.YOUTUBE_DL):
-            fv.res += '<br/><br/><br/><b>Unable to locate youtube-dl script  
"' + config.YOUTUBE_DL + '" </b><br/>'
+            fv.res += '<br><br><br><b>Unable to locate youtube-dl script  "' + 
config.YOUTUBE_DL + '" </b><br>'
             fv.res += 'Download scripts from  <a 
href="http://www.arrakis.es/~rggi3/youtube-dl/";>http://www.arrakis.es/~rggi3/youtube-dl/</a>'
-            fv.res += '<br/>Add YOUTUBE_DL = "path and file name to youtube_dl 
script"<br/>'
+            fv.res += '<br>Add YOUTUBE_DL = "path and file name to youtube_dl 
script"<br>'
+        else:
+            fv.res  += '\n<br><form id="YouTube Download" action="youtube.rpy" 
method="get">'
+            fv.res  += '\n<div class="searchform"><br><b>Youtube URL 
:</b><input type="text" name="yt_url" size="40" value="' + yturl + '" />'
+            fv.res  += '\n<input type="submit" value=" Download! " />'
+            fv.res  += '\n</div>'
+            fv.res  += '\n</form>'
+
+            yturl = fv.formValue(form,'yt_url')
+            if yturl :
+                yt_status = str(download_youtube(yturl,""))
+                refreshon = True
 
         if not os.path.exists(config.YOUTUBE_DIR):
-            fv.res += '<br/><b>Unable to locate youtube download location "' + 
config.YOUTUBE_DIR + '" </b><br/>'
+            fv.res += '<br><b>Unable to locate youtube download location "' + 
config.YOUTUBE_DIR + '" </b><br>'
             fv.res += 'Add YOUTUBE_DIR = "download directory" to your 
local_conf.py'
 
 
-        yturl = fv.formValue(form,'yt_url')
-        if yturl :
-            print yturl
-            yt_status = download_youtube(yturl,"")
-            fv.res += "<br/>" + yt_status
-
-        yturl = ""
-        fv.res  += '<br/><form id="YouTube Download" action="youtube.rpy" 
method="get">'
-        fv.res  += '<div class="searchform"><br/><b>Youtube URL :</b><input 
type="text" name="yt_url" size="40" value="' + yturl + '" />'
-        fv.res  += '<input type="submit" value=" Download! " />'
-        fv.res  += '</div>'
-        fv.res  += '</form>'
+        if os.path.exists(config.YOUTUBE_DIR):
+            if not os.path.exists(config.YOUTUBE_DIR + ".tmp"):
+                os.mkdir(config.YOUTUBE_DIR + ".tmp")
 
         dlurl = fv.formValue(form,'dl_url')
         if dlurl :
-            dl_status = download_url(dlurl)
-            fv.res += "<br/>" + dl_status
-        else :
-            dlurl = ""
-
-        fv.res  += '<br/><form id="Url Download" action="youtube.rpy" 
method="get">'
-        fv.res  += '<div class="searchform"><br/><b>Download URL :</b><input 
type="text" name="dl_url" size="40" value="' + dlurl + '" />'
-        fv.res  += '<input type="submit" value=" Download! " />'
-        fv.res  += '</div>'
-        fv.res  += '</form>'
+            dl_status = download_url(dlurl,"")
+            fv.res += "<br>" + dl_status
+            refreshon = True
+
+        dlurl = ""
+        fv.res  += '\n<form id="Url Download" action="youtube.rpy" 
method="get">'
+        fv.res  += '\n    <div class="searchform"><br><b>Download URL :</b>'
+        fv.res  += '\n       <input type="text" name="dl_url" size="40" 
value="' + dlurl + '" />'
+        fv.res  += '\n       <input type="submit" value=" Download! " />'
+        fv.res  += '\n    </div>'
+        fv.res  += '\n</form><br>\n'
+
+        fdisplay = displayfiles(fv)
+        fv.res  +=  addPageRefresh()
 
         return String( fv.res )
 

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to