/Application/Core/YouTubeManager.cs
http://yet-another-music-application.googlecode.com/ · C# · 391 lines · 226 code · 51 blank · 114 comment · 20 complexity · 6216d6651ab50769c4d206d01b32473e MD5 · raw file
- /**
- * YouTubeManager.cs
- *
- * Takes care of searching and finding music on YouTube
- * as well as converting results into TrackData structures.
- *
- * * * * * * * * *
- *
- * Copyright 2011 Simplare
- *
- * This code is part of the Stoffi Music Player Project.
- * Visit our website at: stoffiplayer.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 3 of the License, or (at your option) any later version.
- *
- * See stoffiplayer.com/license for more information.
- **/
-
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
-
- using Google.GData.Client;
- using Google.GData.Extensions;
- using Google.GData.YouTube;
- using Google.GData.Extensions.MediaRss;
- using Google.YouTube;
-
- namespace Stoffi
- {
- /// <summary>
- /// Represents a manager that takes care of talking to YouTube
- /// </summary>
- public static class YouTubeManager
- {
- #region Members
- private static YouTubeRequestSettings settings = new YouTubeRequestSettings("Stoffi", "AI39si4y_vkAW2Ngyc2BlMdgkBghua2w5hheyesEI-saNU_CNDIMs5YMPpIBk-HpmFG4qDPAHAvE_YYNWH5qV5S1x5euKKRodw");
- #endregion
-
- #region Properties
- /// <summary>
- /// Gets or sets whether the user has Adobe Flash installed or not
- /// </summary>
- public static bool HasFlash { get; set; }
-
- /// <summary>
- /// Gets the current source of tracks used as ItemsSource for the YouTube track list.
- /// </summary>
- public static ObservableCollection<TrackData> TrackSource { get; private set; }
- #endregion
-
- #region Methods
-
- #region Public
-
- /// <summary>
- /// Returns a list of tracks from one of the YouTube feeds
- /// </summary>
- /// <param name="feed">The feed</param>
- /// <returns>An observable collection of TrackData that represents the most viewed YouTube tracks</returns>
- public static ObservableCollection<TrackData> TopFeed(string feed)
- {
- ObservableCollection<TrackData> tracks = new ObservableCollection<TrackData>();
- YouTubeRequest request = new YouTubeRequest(settings);
-
- int maxFeedItems = 50;
-
- int i = 1;
- Feed<Video> videoFeed = request.Get<Video>(new Uri("http://gdata.youtube.com/feeds/api/standardfeeds/" + feed + "?format=5"));
- foreach (Video entry in videoFeed.Entries)
- {
- if (i++ > maxFeedItems) break;
- tracks.Add(CreateTrack(entry));
- }
-
- TrackSource = tracks;
-
- return tracks;
- }
-
- /// <summary>
- /// Searches YouTube for tracks matching a certain query
- /// </summary>
- /// <param name="query">The query to search for</param>
- /// <returns>An observable collection of TrackData with all YouTube tracks that match query</returns>
- public static ObservableCollection<TrackData> Search(string query)
- {
- ObservableCollection<TrackData> tracks = new ObservableCollection<TrackData>();
-
- YouTubeQuery q = new YouTubeQuery(YouTubeQuery.DefaultVideoUri);
- q.OrderBy = "relevance";
- q.Query = query;
- q.Formats.Add(YouTubeQuery.VideoFormat.Embeddable);
- q.NumberToRetrieve = 50;
- q.SafeSearch = YouTubeQuery.SafeSearchValues.None;
-
- YouTubeRequest request = new YouTubeRequest(settings);
-
- Feed<Video> videoFeed = request.Get<Video>(q);
- foreach (Video entry in videoFeed.Entries)
- {
- tracks.Add(CreateTrack(entry));
- }
-
- TrackSource = tracks;
-
- return tracks;
- }
-
- /// <summary>
- /// Retrieves the URL to the thumbnail for a YouTube track
- /// </summary>
- /// <param name="track">The YouTube track</param>
- public static string GetThumbnail(TrackData track)
- {
- if (IsYouTube(track))
- return "https://img.youtube.com/vi/" + GetYouTubeID(track.Path) + "/1.jpg";
- else
- return "";
- }
-
- /// <summary>
- /// Retrieves the URL for a YouTube track
- /// </summary>
- /// <param name="track">The YouTube track</param>
- public static string GetURL(TrackData track)
- {
- if (IsYouTube(track))
- return "https://www.youtube.com/watch?v=" + GetYouTubeID(track.Path);
- else
- return "";
- }
-
- /// <summary>
- /// Creates a track using a YouTube video ID
- /// </summary>
- /// <param name="id">The video ID</param>
- /// <returns>A TrackData structure representing the YouTube track</returns>
- public static TrackData CreateTrack(string id)
- {
- YouTubeRequest request = new YouTubeRequest(settings);
- Uri url = new Uri("http://gdata.youtube.com/feeds/api/videos/" + id);
- Video v = request.Retrieve<Video>(url);
- if (v == null)
- {
- U.L(LogLevel.Warning, "YOUTUBE", "Could not find video with ID '" + id + "'");
- return null;
- }
- return CreateTrack(v);
- }
-
- /// <summary>
- /// Creates a track using a YouTube video entry
- /// </summary>
- /// <param name="v">The video entry</param>
- /// <returns>A TrackData structure representing the YouTube track</returns>
- public static TrackData CreateTrack(Video v)
- {
- TrackData track = new TrackData();
- track.Path = "youtube://" + v.VideoId;
- track.Icon = "pack://application:,,,/Platform/Windows/GUI/Images/Icons/YouTube.ico";
- track.Bookmarks = new List<double>();
- track.Processed = true;
- int len = Convert.ToInt32(v.Media.Duration.Seconds);
- track.Length = U.TimeSpanToString(new TimeSpan(0, 0, len));
- string[] str = splitTitle(v.Title);
- track.Artist = str[0];
- track.Title = str[1];
- track.RawViews = v.ViewCount;
- track.RawLength = len;
- return track;
- }
-
- /// <summary>
- /// Checks whether a given track is a youtube track
- /// </summary>
- /// <param name="t">The track to check</param>
- /// <returns>True if the track is a youtube track</returns>
- public static bool IsYouTube(TrackData t)
- {
- return (t != null && IsYouTube(t.Path));
- }
-
- /// <summary>
- /// Checks whether a given track path corresponds to a youtube track
- /// </summary>
- /// <param name="path">The path of the track to check</param>
- /// <returns>True if the track is a youtube track</returns>
- public static bool IsYouTube(string path)
- {
- return path.StartsWith("youtube://");
- }
-
- /// <summary>
- /// Extracts the video ID of a YouTube track's path
- /// </summary>
- /// <param name="path">The path of the track</param>
- /// <returns>The video ID</returns>
- public static string GetYouTubeID(string path)
- {
- if (IsYouTube(path))
- return path.Substring(10);
-
- throw new Exception("Trying to extract YouTube video ID from non-YouTube track: " + path);
- }
-
- #endregion
-
- #region Private
-
- /// <summary>
- /// Separates a title by a list of separators
- /// and identifies artist and title.
- /// </summary>
- /// <param name="title">The title to split</param>
- /// <returns>An array holding artist and title</returns>
- private static string[] splitTitle(string title)
- {
- foreach (string sep in new[] { "-", ":" })
- {
- string[] variants = new[]
- {
- " " + sep + " ",
- " " + sep,
- sep + " "
- };
- foreach (string var in variants)
- {
- if (title.Contains(var))
- {
- string[] str = title.Split(new[] { var }, 2, StringSplitOptions.None);
-
- string[] prefixes = new[]
- {
- "by ",
- "ft ",
- "ft.",
- "feat ",
- "feat."
- };
-
- foreach (string pref in prefixes)
- {
- if (str[0].ToLower().StartsWith(pref))
- return new[] { str[0].Substring(pref.Length), str[1] };
- else if (str[1].ToLower().StartsWith(pref))
- return new[] { str[1].Substring(pref.Length), str[0] };
- }
- return new[] { str[0], str[1] };
- }
- }
- }
- return new[] { "", title };
- }
-
- #endregion
-
- #endregion
- }
-
- /// <summary>
- /// Describes the interface that the chromeless YouTube player can call via JavaScript
- /// </summary>
- [ComVisibleAttribute(true)]
- public class YouTubePlayerInterface
- {
- /// <summary>
- /// Invoked when an error occurs within the YouTube player
- /// </summary>
- /// <param name="errorCode">The error code</param>
- public void OnVideoError(int errorCode)
- {
- switch (errorCode)
- {
- case 2:
- U.L(LogLevel.Error, "YOUTUBE", "Player reported that we used bad parameters");
- break;
-
- case 100:
- U.L(LogLevel.Error, "YOUTUBE", "Player reported that the track has either been removed or marked as private");
- break;
-
- case 101:
- case 150:
- U.L(LogLevel.Error, "YOUTUBE", "Player reported that the track is restricted");
- break;
-
- default:
- U.L(LogLevel.Error, "YOUTUBE", "Player reported an unknown error code: " + errorCode);
- break;
- }
- DispatchError(errorCode.ToString());
- }
-
- /// <summary>
- /// Invoked when user tries to play a youtube track but doesn't have flash installed
- /// </summary>
- public void OnNoFlash()
- {
- DispatchNoFlashDetected();
- }
-
- /// <summary>
- /// Invoked when the player changes state
- /// </summary>
- /// <param name="state">The new state of the player</param>
- public void OnStateChanged(int state)
- {
- switch (state)
- {
- case -1: // unstarted
- break;
-
- case 0: // ended
- SettingsManager.MediaState = MediaState.Ended;
- break;
-
- case 1: // playing
- SettingsManager.MediaState = MediaState.Playing;
- break;
-
- case 2: // paused
- SettingsManager.MediaState = MediaState.Paused;
- break;
-
- case 3: // buffering
- break;
-
- case 5: // cued
- break;
- }
- }
-
- /// <summary>
- /// Invoked when player is ready
- /// </summary>
- public void OnPlayerReady()
- {
- DispatchPlayerReady();
- }
-
- /// <summary>
- /// Dispatches the ErrorOccured event
- /// </summary>
- /// <param name="message">The error message</param>
- private void DispatchError(string message)
- {
- if (ErrorOccured != null)
- ErrorOccured(this, message);
- }
-
- /// <summary>
- /// Dispatches the NoFlashDetected event
- /// </summary>
- private void DispatchNoFlashDetected()
- {
- if (NoFlashDetected != null)
- NoFlashDetected(this, new EventArgs());
- }
-
- /// <summary>
- /// Dispatches the PlayerReady event
- /// </summary>
- private void DispatchPlayerReady()
- {
- if (PlayerReady != null)
- PlayerReady(this, new EventArgs());
- }
-
- /// <summary>
- /// Occurs when there's an error from the player
- /// </summary>
- public event ErrorEventHandler ErrorOccured;
-
- /// <summary>
- /// Occurs when the user tries to play a youtube track but there's no flash installed
- /// </summary>
- public event EventHandler NoFlashDetected;
-
- /// <summary>
- /// Occurs when the player is ready
- /// </summary>
- public event EventHandler PlayerReady;
- }
- }