Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show stream details in video information #675

Merged
merged 7 commits into from
Aug 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mps_youtube/commands/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def download(dltype, num):
g.content = content.generate_songlist_display()


@command(r'(da|dv)\s+((?:\d+\s\d+|-\d|\d+-|\d,)(?:[\d\s,-]*))')
@command(r'(da|dv)\s+(?<![-\d\[\]])(\d+-\d+|-\d+|\d+-|\d+)(?:\[(\d+)\])?(?![-\d\[\]])')
def down_many(dltype, choice, subdir=None):
""" Download multiple items. """
choice = util.parse_multi(choice)
Expand Down
69 changes: 63 additions & 6 deletions mps_youtube/commands/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import traceback
from urllib.request import urlopen
from urllib.error import HTTPError, URLError
from .. import player

try:
# pylint: disable=F0401
Expand Down Expand Up @@ -132,8 +133,8 @@ def comments(number):


@command(r'x\s*(\d+)')
def clip_copy(num):
""" Copy item to clipboard. """
def clipcopy_video(num):
""" Copy video/playlist url to clipboard. """
if g.browse_mode == "ytpl":

p = g.ytpls[int(num) - 1]
Expand Down Expand Up @@ -166,9 +167,41 @@ def clip_copy(num):
g.content = generate_songlist_display()


@command(r'X\s*(\d+)')
def clipcopy_stream(num):
""" Copy content stream url to clipboard. """
if g.browse_mode == "normal":

item = (g.model[int(num) - 1])
details = player.stream_details(item)[1]
stream = details['url']

else:
g.message = "clipboard copy not valid in this mode"
g.content = generate_songlist_display()
return

if has_pyperclip:

try:
pyperclip.copy(stream)
g.message = c.y + stream + c.w + " copied"
g.content = generate_songlist_display()

except Exception as e:
g.content = generate_songlist_display()
g.message = stream + "\nError - couldn't copy to clipboard.\n" + \
''.join(traceback.format_exception_only(type(e), e))

else:
g.message = "pyperclip module must be installed for clipboard support\n"
g.message += "see https://pypi.python.org/pypi/pyperclip/"
g.content = generate_songlist_display()


@command(r'i\s*(\d{1,4})')
def info(num):
""" Get video description. """
def video_info(num):
""" Get video information. """
if g.browse_mode == "ytpl":
p = g.ytpls[int(num) - 1]

Expand Down Expand Up @@ -210,8 +243,8 @@ def info(num):
screen.writestatus("Fetched")
out = c.ul + "Video Info" + c.w + "\n\n"
out += p.title or ""
out += "\n" + (p.description or "")
out += "\n\nAuthor : " + str(p.author)
out += "\n" + (p.description or "") + "\n"
out += "\nAuthor : " + str(p.author)
out += "\nPublished : " + pub.strftime("%c")
out += "\nView count : " + str(p.viewcount)
out += "\nRating : " + str(p.rating)[:4]
Expand All @@ -223,6 +256,30 @@ def info(num):
g.content = out


@command(r's\s*(\d{1,4})')
def stream_info(num):
""" Get stream information. """
if g.browse_mode == "normal":
g.content = logo(c.b)
screen.update()
screen.writestatus("Fetching stream metadata..")
item = (g.model[int(num) - 1])
streams.get(item)
p = util.get_pafy(item)
setattr(p, 'ytid', p.videoid)
details = player.stream_details(p)[1]
screen.writestatus("Fetched")
out = "\n\n" + c.ul + "Stream Info" + c.w + "\n"
out += "\nExtension : " + details['ext']
out += "\nSize : " + str(details['size'])
out += "\nQuality : " + details['quality']
out += "\nRaw bitrate : " + str(details['rawbitrate'])
out += "\nMedia type : " + details['mtype']
out += "\nLink : " + details['url']
out += "\n\n%s[%sPress enter to go back%s]%s" % (c.y, c.w, c.y, c.w)
g.content = out


@command(r'history')
def view_history(duplicates=True):
""" Display the user's play history """
Expand Down
43 changes: 25 additions & 18 deletions mps_youtube/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ def play_range(songlist, shuffle=False, repeat=False, override=False):
softrepeat = repeat and len(songlist) == 1

try:
returncode = _playsong(song, override=override, softrepeat=softrepeat)
video, stream = stream_details(song, override=override, softrepeat=softrepeat)
returncode = _playsong(song, stream, video, override=override, softrepeat=softrepeat)

except KeyboardInterrupt:
logging.info("Keyboard Interrupt")
Expand Down Expand Up @@ -134,17 +135,8 @@ def _mplayer_help(short=True):
return lines.format(c.g, c.w)


def _playsong(song, failcount=0, override=False, softrepeat=False):
""" Play song using config.PLAYER called with args config.PLAYERARGS."""
# pylint: disable=R0911,R0912
if not config.PLAYER.get or not util.has_exefile(config.PLAYER.get):
g.message = "Player not configured! Enter %sset player <player_app> "\
"%s to set a player" % (c.g, c.w)
return

if config.NOTIFIER.get:
subprocess.Popen(shlex.split(config.NOTIFIER.get) + [song.title])

def stream_details(song, failcount=0, override=False, softrepeat=False):
"""Fetch stream details for a song."""
# don't interrupt preloading:
while song.ytid in g.preloading:
screen.writestatus("fetching item..")
Expand All @@ -154,7 +146,7 @@ def _playsong(song, failcount=0, override=False, softrepeat=False):
streams.get(song, force=failcount, callback=screen.writestatus)

except (IOError, URLError, HTTPError, socket.timeout) as e:
util.dbg("--ioerror in _playsong call to streams.get %s", str(e))
util.dbg("--ioerror in stream_details call to streams.get %s", str(e))

if "Youtube says" in str(e):
g.message = util.F('cant get track') % (song.title + " " + str(e))
Expand All @@ -163,15 +155,15 @@ def _playsong(song, failcount=0, override=False, softrepeat=False):
elif failcount < g.max_retries:
util.dbg("--ioerror - trying next stream")
failcount += 1
return _playsong(song, failcount=failcount, override=override, softrepeat=softrepeat)
return stream_details(song, failcount=failcount, override=override, softrepeat=softrepeat)

elif "pafy" in str(e):
g.message = str(e) + " - " + song.ytid
return

except ValueError:
g.message = util.F('track unresolved')
util.dbg("----valueerror in _playsong call to streams.get")
util.dbg("----valueerror in stream_details call to streams.get")
return

try:
Expand All @@ -192,13 +184,15 @@ def _playsong(song, failcount=0, override=False, softrepeat=False):
if not stream:
raise IOError("No streams available")

return (video, stream)

except (HTTPError) as e:

# Fix for invalid streams (gh-65)
util.dbg("----htterror in _playsong call to gen_real_args %s", str(e))
util.dbg("----htterror in stream_details call to gen_real_args %s", str(e))
if failcount < g.max_retries:
failcount += 1
return _playsong(song, failcount=failcount, override=override, softrepeat=softrepeat)
return stream_details(song, failcount=failcount, override=override, softrepeat=softrepeat)
else:
g.message = str(e)
return
Expand All @@ -210,6 +204,19 @@ def _playsong(song, failcount=0, override=False, softrepeat=False):
errmsg = e.message if hasattr(e, "message") else str(e)
g.message = c.r + str(errmsg) + c.w
return


def _playsong(song, stream, video, failcount=0, override=False, softrepeat=False):
""" Play song using config.PLAYER called with args config.PLAYERARGS."""
# pylint: disable=R0911,R0912
if not config.PLAYER.get or not util.has_exefile(config.PLAYER.get):
g.message = "Player not configured! Enter %sset player <player_app> "\
"%s to set a player" % (c.g, c.w)
return

if config.NOTIFIER.get:
subprocess.Popen(shlex.split(config.NOTIFIER.get) + [song.title])

size = streams.get_size(song.ytid, stream['url'])
songdata = (song.ytid, stream['ext'] + " " + stream['quality'],
int(size / (1024 ** 2)))
Expand All @@ -226,7 +233,7 @@ def _playsong(song, failcount=0, override=False, softrepeat=False):
screen.writestatus("error: retrying")
time.sleep(1.2)
failcount += 1
return _playsong(song, failcount=failcount, override=override, softrepeat=softrepeat)
return _playsong(song, stream, video, failcount=failcount, override=override, softrepeat=softrepeat)

history.add(song)
return returncode
Expand Down