├── Images
└── UI.jpg
├── GoogleCast
├── Channels
│ ├── IHeartbeatChannel.cs
│ ├── INextMessageChannel.cs
│ ├── IPreviousMessageChannel.cs
│ ├── NextMessageChannel.cs
│ ├── PreviousMessageChannel.cs
│ ├── IApplicationChannel.cs
│ ├── IConnectionChannel.cs
│ ├── IStatusChannel.cs
│ ├── IChannel.cs
│ ├── HeartbeatChannel.cs
│ ├── ConnectionChannel.cs
│ ├── IReceiverChannel.cs
│ ├── StatusChannel.cs
│ ├── Channel.cs
│ ├── ReceiverChannel.cs
│ ├── IMediaChannel.cs
│ └── MediaChannel.cs
├── Messages
│ ├── Hearbeat
│ │ ├── PongMessage.cs
│ │ └── PingMessage.cs
│ ├── Receiver
│ │ ├── StopMessage.cs
│ │ ├── GetStatusMessage.cs
│ │ ├── ReceiverStatusMessage.cs
│ │ ├── LaunchMessage.cs
│ │ └── SetVolumeMessage.cs
│ ├── Connection
│ │ ├── ConnectMessage.cs
│ │ └── CloseMessage.cs
│ ├── Media
│ │ ├── QueueMessage.cs
│ │ ├── GetStatusMessage.cs
│ │ ├── StopMessage.cs
│ │ ├── PauseMessage.cs
│ │ ├── SkipForwardMessage.cs
│ │ ├── SkipBackwardMessage.cs
│ │ ├── PlayMessage.cs
│ │ ├── NextMessage.cs
│ │ ├── GetQueueItemIdsMessage.cs
│ │ ├── PreviousMessage.cs
│ │ ├── MediaStatusMessage.cs
│ │ ├── PositionChangeMessage.cs
│ │ ├── QueueRemoveMessage.cs
│ │ ├── LoadFailedMessage.cs
│ │ ├── QueueReorderMessage.cs
│ │ ├── LoadCancelledMessage.cs
│ │ ├── QueueItemIdsMessage.cs
│ │ ├── MediaSessionMessage.cs
│ │ ├── QueueItemsMessage.cs
│ │ ├── SetPlaybackRateMessage.cs
│ │ ├── SeekMessage.cs
│ │ ├── InvalidRequestMessage.cs
│ │ ├── GetQueueItemsMessage .cs
│ │ ├── QueueInsertMessage.cs
│ │ ├── QueueUpdateMessage.cs
│ │ ├── QueueChangeMessage.cs
│ │ ├── LoadMessage.cs
│ │ ├── EditTracksInfoMessage.cs
│ │ └── QueueLoadMessage.cs
│ ├── IMessage.cs
│ ├── ReceptionMessageAttribute.cs
│ ├── IMessageWithId.cs
│ ├── IStatusMessage.cs
│ ├── SessionMessage.cs
│ ├── StatusMessage.cs
│ ├── Message.cs
│ └── MessageWithId.cs
├── ProtocolVersion.cs
├── IMessageTypes.cs
├── PayloadType.cs
├── Models
│ ├── Receiver
│ │ ├── Namespace.cs
│ │ ├── ReceiverStatus.cs
│ │ └── Application.cs
│ ├── Media
│ │ ├── TrackType.cs
│ │ ├── StreamType.cs
│ │ ├── TextTrackWindowType.cs
│ │ ├── MetadataType.cs
│ │ ├── TextTrackFontStyle.cs
│ │ ├── MovieMetadata.cs
│ │ ├── TextTrackEdgeType.cs
│ │ ├── QueueChangeType.cs
│ │ ├── TextTrackFontGenericFamily.cs
│ │ ├── QueueStatus.cs
│ │ ├── RepeatMode.cs
│ │ ├── TextTrackType.cs
│ │ ├── MusicTrackMediaMetadata.cs
│ │ ├── GenericMediaMetadata.cs
│ │ ├── QueueItem.cs
│ │ ├── Track.cs
│ │ ├── MediaInformation.cs
│ │ ├── MediaStatus.cs
│ │ └── TextTrackStyle.cs
│ ├── Image.cs
│ └── Volume.cs
├── IReceiver.cs
├── DefaultIdentifiers.cs
├── IDeviceLocator.cs
├── ServiceCollectionExtensions.cs
├── MessageTypes.cs
├── Receiver.cs
├── TaskExtensions.cs
├── DeviceLocator.cs
├── CastMessage.cs
├── ColorHelper.cs
├── GoogleCast.csproj
├── StringExtensions.cs
├── EnumHelper.cs
├── JsonSerializer.cs
└── ISender.cs
├── MBCCRules
├── MBCCRules.csproj
├── app.manifest
└── Program.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
└── Resources.resx
├── app.config
├── packages.config
├── Settings.cs
├── WebServer.cs
├── ChromecastPanel.Designer.cs
├── CSharp.sln
├── README.md
├── CAF Receiver
├── css
│ └── style.css
├── build
│ └── receiver.html
└── receiver.html
├── ChromecastPanel.cs
├── Settings.Designer.cs
├── Settings.resx
├── ChromecastPanel.resx
└── .gitignore
/Images/UI.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TroyFernandes/MusicBeeChromecast/HEAD/Images/UI.jpg
--------------------------------------------------------------------------------
/GoogleCast/Channels/IHeartbeatChannel.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Channels
2 | {
3 | ///
4 | /// Interface for the heartbeat channel
5 | ///
6 | interface IHeartbeatChannel : IChannel
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/GoogleCast/Channels/INextMessageChannel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace GoogleCast.Channels
6 | {
7 | interface INextMessageChannel: IChannel
8 | {
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/IPreviousMessageChannel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace GoogleCast.Channels
6 | {
7 | public interface IPreviousMessageChannel: IChannel
8 | {
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Hearbeat/PongMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Heartbeat
4 | {
5 | ///
6 | /// Pong message
7 | ///
8 | [DataContract]
9 | class PongMessage : Message
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Receiver/StopMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Receiver
4 | {
5 | ///
6 | /// Stop message
7 | ///
8 | [DataContract]
9 | class StopMessage : SessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/ProtocolVersion.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast
2 | {
3 | ///
4 | /// Protocol version
5 | ///
6 | enum ProtocolVersion
7 | {
8 | ///
9 | /// CastV2_1_0
10 | ///
11 | CastV2_1_0 = 0
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Connection/ConnectMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Connection
4 | {
5 | ///
6 | /// Connect message
7 | ///
8 | [DataContract]
9 | class ConnectMessage : Message
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/IMessageTypes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace GoogleCast
5 | {
6 | ///
7 | /// Interface for message types dictionary
8 | ///
9 | public interface IMessageTypes : IDictionary
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Queue message
7 | ///
8 | [DataContract]
9 | abstract class QueueMessage : MediaSessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Receiver/GetStatusMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Receiver
4 | {
5 | ///
6 | /// Get status message
7 | ///
8 | [DataContract]
9 | class GetStatusMessage : MessageWithId
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Hearbeat/PingMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Heartbeat
4 | {
5 | ///
6 | /// Ping message
7 | ///
8 | [DataContract]
9 | [ReceptionMessage]
10 | class PingMessage : Message
11 | {
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Connection/CloseMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Connection
4 | {
5 | ///
6 | /// Close message
7 | ///
8 | [DataContract]
9 | [ReceptionMessage]
10 | class CloseMessage : Message
11 | {
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/GetStatusMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to retrieve the media status
7 | ///
8 | [DataContract]
9 | class GetStatusMessage : MediaSessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/StopMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to stop playback of the current content
7 | ///
8 | [DataContract]
9 | class StopMessage : MediaSessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/IMessage.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Messages
2 | {
3 | ///
4 | /// Interface for a message
5 | ///
6 | public interface IMessage
7 | {
8 | ///
9 | /// Gets the message type
10 | ///
11 | string Type { get; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/PauseMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to pause playback of the current content
7 | ///
8 | [DataContract]
9 | class PauseMessage : MediaSessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/NextMessageChannel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace GoogleCast.Channels
6 | {
7 | class NextMessageChannel : Channel, INextMessageChannel
8 | {
9 | public NextMessageChannel() : base("next")
10 | {
11 |
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/SkipForwardMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to skip to the next item in the queue
7 | ///
8 | [DataContract]
9 | class QueueNextMessage : MediaSessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/SkipBackwardMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to skip to the previous item in the queue
7 | ///
8 | [DataContract]
9 | class QueuePrevMessage : MediaSessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/ReceptionMessageAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GoogleCast.Messages
4 | {
5 | ///
6 | /// Attribute for received messages
7 | ///
8 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
9 | public class ReceptionMessageAttribute : Attribute
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/PlayMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to begin playback of the content that was loaded with the load call
7 | ///
8 | [DataContract]
9 | class PlayMessage : MediaSessionMessage
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/PreviousMessageChannel.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages;
2 | using System;
3 | using System.Threading.Tasks;
4 |
5 | namespace GoogleCast.Channels
6 | {
7 | class PreviousMessageChannel : Channel, IPreviousMessageChannel
8 | {
9 | public PreviousMessageChannel() : base("previous")
10 | {
11 | }
12 |
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/GoogleCast/PayloadType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast
2 | {
3 | ///
4 | /// Payload type
5 | ///
6 | enum PayloadType
7 | {
8 | ///
9 | /// String
10 | ///
11 | String = 0,
12 |
13 | ///
14 | /// Binary
15 | ///
16 | Binary = 1
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/IMessageWithId.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Messages
2 | {
3 | ///
4 | /// Interface for messages with request identifier
5 | ///
6 | public interface IMessageWithId : IMessage
7 | {
8 | ///
9 | /// Gets the request identifier
10 | ///
11 | int RequestId { get; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/IApplicationChannel.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Channels
2 | {
3 | ///
4 | /// Interface for application channels
5 | ///
6 | public interface IApplicationChannel : IChannel
7 | {
8 | ///
9 | /// Gets the application identifier
10 | ///
11 | string ApplicationId { get; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/NextMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 | using System.Text;
5 |
6 | namespace GoogleCast.Messages.Media
7 | { ///
8 | /// Chromecast Next Command
9 | ///
10 | [DataContract]
11 | [ReceptionMessage]
12 | class NextMessage : Message
13 | {
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/GetQueueItemIdsMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages.Media;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// A request to retrieve all of the item ids currently in the queue
8 | ///
9 | [DataContract]
10 | class QueueGetItemIdsMessage : MediaSessionMessage
11 | {
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/PreviousMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 | using System.Text;
5 |
6 | namespace GoogleCast.Messages.Media
7 |
8 | { ///
9 | /// Custom Message
10 | ///
11 | [DataContract]
12 | [ReceptionMessage]
13 | class PreviousMessage : Message
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Receiver/ReceiverStatusMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Receiver;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Receiver
5 | {
6 | ///
7 | /// Receiver status message
8 | ///
9 | [DataContract]
10 | [ReceptionMessage]
11 | class ReceiverStatusMessage : StatusMessage
12 | {
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/IStatusMessage.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Messages
2 | {
3 | ///
4 | /// Interface for status messages
5 | ///
6 | /// status type
7 | public interface IStatusMessage : IMessageWithId
8 | {
9 | ///
10 | /// Gets the status
11 | ///
12 | TStatus Status { get; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/MediaStatusMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 |
5 | namespace GoogleCast.Messages.Media
6 | {
7 | ///
8 | /// Message to retrieve the media status
9 | ///
10 | [DataContract]
11 | [ReceptionMessage]
12 | class MediaStatusMessage : StatusMessage>
13 | {
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Receiver/Namespace.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Models.Receiver
4 | {
5 | ///
6 | /// Namespace
7 | ///
8 | [DataContract]
9 | public class Namespace
10 | {
11 | ///
12 | /// Gets or sets the name
13 | ///
14 | [DataMember(Name = "name")]
15 | public string Name { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GoogleCast/IReceiver.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 |
3 | namespace GoogleCast
4 | {
5 | ///
6 | /// Interface for a receiver
7 | ///
8 | public interface IReceiver
9 | {
10 | ///
11 | /// Gets the friendly name
12 | ///
13 | string FriendlyName { get; }
14 |
15 | ///
16 | /// Gets the network endpoint
17 | ///
18 | IPEndPoint IPEndPoint { get; }
19 | }
20 | }
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/TrackType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Track type
5 | ///
6 | public enum TrackType
7 | {
8 | ///
9 | /// Text
10 | ///
11 | Text,
12 |
13 | ///
14 | /// Audio
15 | ///
16 | Audio,
17 |
18 | ///
19 | /// Video
20 | ///
21 | Video
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/PositionChangeMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// Message to retrieve all changed queued item ids
8 | ///
9 | [DataContract]
10 | [ReceptionMessage]
11 | class PositionChangeMessage : MessageWithId
12 | {
13 | [DataMember(Name = "position")]
14 | public double Position { get; set; }
15 |
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Receiver/LaunchMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Receiver
4 | {
5 | ///
6 | /// Launch message
7 | ///
8 | [DataContract]
9 | class LaunchMessage : MessageWithId
10 | {
11 | ///
12 | /// Gets or sets the application identifier
13 | ///
14 | [DataMember(Name = "appId")]
15 | public string ApplicationId { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/StreamType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Stream type
5 | ///
6 | public enum StreamType
7 | {
8 | ///
9 | /// None
10 | ///
11 | None,
12 |
13 | ///
14 | /// Live
15 | ///
16 | Live,
17 |
18 | ///
19 | /// Buffered
20 | ///
21 | Buffered
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/SessionMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages
4 | {
5 | ///
6 | /// Session message base class
7 | ///
8 | [DataContract]
9 | public abstract class SessionMessage : MessageWithId
10 | {
11 | ///
12 | /// Gets or sets the session identifier
13 | ///
14 | [DataMember(Name = "sessionId")]
15 | public string SessionId { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Receiver/SetVolumeMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Receiver
5 | {
6 | ///
7 | /// Volume Message
8 | ///
9 | [DataContract]
10 | class SetVolumeMessage : MessageWithId
11 | {
12 | ///
13 | /// Gets or sets the volume
14 | ///
15 | [DataMember(Name = "volume")]
16 | public Volume Volume { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/GoogleCast/DefaultIdentifiers.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast
2 | {
3 | ///
4 | /// Default identifiers
5 | ///
6 | static class DefaultIdentifiers
7 | {
8 | ///
9 | /// Default sender identifier
10 | ///
11 | public const string SENDER_ID = "sender-0";
12 |
13 | ///
14 | /// Default destination identifier
15 | ///
16 | public const string DESTINATION_ID = "receiver-0";
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueRemoveMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to remove given queued item ids
7 | ///
8 | [DataContract]
9 | class QueueRemoveMessage : QueueMessage
10 | {
11 | ///
12 | /// Gets or sets the item id array
13 | ///
14 | [DataMember(Name = "itemIds")]
15 | public int[] ItemIds { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/IConnectionChannel.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace GoogleCast.Channels
4 | {
5 | ///
6 | /// Interface for the connection channel
7 | ///
8 | public interface IConnectionChannel : IChannel
9 | {
10 | ///
11 | /// Connects
12 | ///
13 | /// destination identifier
14 | Task ConnectAsync(string destinationId = DefaultIdentifiers.DESTINATION_ID);
15 | }
16 | }
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/LoadFailedMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// Load failed message
8 | ///
9 | [DataContract]
10 | [ReceptionMessage]
11 | class LoadFailedMessage : MessageWithId
12 | {
13 | [OnDeserializing]
14 | private void OnDeserializing(StreamingContext context)
15 | {
16 | throw new Exception("Load failed");
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueReorderMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to reorder the given queued item ids
7 | ///
8 | [DataContract]
9 | class QueueReorderMessage : QueueMessage
10 | {
11 | ///
12 | /// Gets or sets the item id array
13 | ///
14 | [DataMember(Name = "itemIds")]
15 | public int[] ItemIds { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/LoadCancelledMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// Load cancelled message
8 | ///
9 | [DataContract]
10 | [ReceptionMessage]
11 | class LoadCancelledMessage : MessageWithId
12 | {
13 | [OnDeserializing]
14 | private void OnDeserializing(StreamingContext context)
15 | {
16 | throw new Exception("Load cancelled");
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/TextTrackWindowType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Text track window types
5 | ///
6 | public enum TextTrackWindowType
7 | {
8 | ///
9 | /// None
10 | ///
11 | None,
12 |
13 | ///
14 | /// Normal
15 | ///
16 | Normal,
17 |
18 | ///
19 | /// Rounded corners
20 | ///
21 | RoundedCorners
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueItemIdsMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to retrieve all queued item ids
7 | ///
8 | [DataContract]
9 | [ReceptionMessage]
10 | class QueueItemIdsMessage : MessageWithId
11 | {
12 | ///
13 | /// Gets or sets the item id array
14 | ///
15 | [DataMember(Name = "itemIds")]
16 | public int[] ItemIds { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/MediaSessionMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Media session message
7 | ///
8 | [DataContract]
9 | abstract class MediaSessionMessage : MessageWithId
10 | {
11 | ///
12 | /// Gets or sets the media session identifier
13 | ///
14 | [DataMember(Name = "mediaSessionId", EmitDefaultValue = false)]
15 | public long? MediaSessionId { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueItemsMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// Message to retrieve all queued item ids
8 | ///
9 | [DataContract]
10 | [ReceptionMessage]
11 | class QueueItemsMessage : MessageWithId
12 | {
13 | ///
14 | /// Gets or sets the item id array
15 | ///
16 | [DataMember(Name = "items")]
17 | public QueueItem[] Items { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/StatusMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages
4 | {
5 | ///
6 | /// Status message base class
7 | ///
8 | /// status type
9 | [DataContract]
10 | public abstract class StatusMessage : MessageWithId, IStatusMessage
11 | {
12 | ///
13 | /// Gets or sets the status
14 | ///
15 | [DataMember(Name = "status")]
16 | public TStatus Status { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/MetadataType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Metadata type
5 | ///
6 | public enum MetadataType
7 | {
8 | ///
9 | /// Default
10 | ///
11 | Default = 0,
12 |
13 | ///
14 | /// Movie
15 | ///
16 | Movie = 2,
17 |
18 | ///
19 | /// Music
20 | ///
21 | Music = 3,
22 |
23 | ///
24 | /// Photo
25 | ///
26 | Photo = 4
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/IStatusChannel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace GoogleCast.Channels
5 | {
6 | ///
7 | /// Interface for a status channel
8 | ///
9 | /// status type
10 | public interface IStatusChannel : IChannel
11 | {
12 | ///
13 | /// Raised when the status has changed
14 | ///
15 | event EventHandler StatusChanged;
16 |
17 | ///
18 | /// Gets the status
19 | ///
20 | TStatus Status { get; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/MBCCRules/MBCCRules.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net461
6 | app.manifest
7 |
8 |
9 |
10 |
11 | 58fbcf7c-e7a9-467c-80b3-fc65e8fcca08
12 | 1
13 | 0
14 | 0
15 | tlbimp
16 | false
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/TextTrackFontStyle.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Possible text track font styles
5 | ///
6 | public enum TextTrackFontStyle
7 | {
8 | ///
9 | /// Normal
10 | ///
11 | Normal,
12 |
13 | ///
14 | /// Bold
15 | ///
16 | Bold,
17 |
18 | ///
19 | /// Bold italic
20 | ///
21 | BoldItalic,
22 |
23 | ///
24 | /// Italic
25 | ///
26 | Italic
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/SetPlaybackRateMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to set the current playback rate of the stream
7 | ///
8 | [DataContract]
9 | class SetPlaybackRateMessage : MediaSessionMessage
10 | {
11 | ///
12 | /// Gets or sets the relative playback rate
13 | ///
14 | /// the given playback will affect the current playback rate
15 | [DataMember(Name = "playbackRate")]
16 | public double PlaybackRate { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/SeekMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Messages.Media
4 | {
5 | ///
6 | /// Message to set the current position in the stream
7 | ///
8 | [DataContract]
9 | class SeekMessage : MediaSessionMessage
10 | {
11 | ///
12 | /// Gets or sets the seconds since beginning of content
13 | ///
14 | /// if the content is live content, and position is not specifed, the stream will start at the live position
15 | [DataMember(Name = "currentTime")]
16 | public double CurrentTime { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/InvalidRequestMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// Invalid request message
8 | ///
9 | [DataContract]
10 | [ReceptionMessage]
11 | class InvalidRequestMessage : MessageWithId
12 | {
13 | ///
14 | /// Gets or sets the reason
15 | ///
16 | [DataMember(Name = "reason")]
17 | public string Reason { get; set; }
18 |
19 | [OnDeserialized]
20 | private void OnDeserialized(StreamingContext context)
21 | {
22 | throw new InvalidOperationException(Reason);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/MovieMetadata.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Models.Media
4 | {
5 | ///
6 | /// Movie metadata
7 | ///
8 | [DataContract]
9 | public class MovieMetadata : GenericMediaMetadata
10 | {
11 | ///
12 | /// Initializes a new instance of class
13 | ///
14 | public MovieMetadata()
15 | {
16 | MetadataType = MetadataType.Movie;
17 | }
18 |
19 | ///
20 | /// Gets or sets the studio
21 | ///
22 | [DataMember(Name = "studio")]
23 | public string Studio { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/GetQueueItemsMessage .cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 |
5 | namespace GoogleCast.Messages.Media
6 | {
7 | ///
8 | /// A request to to retrieve the information of the given list of queue item ids
9 | ///
10 | [DataContract]
11 | class QueueGetItemsMessage : MediaSessionMessage
12 | {
13 | ///
14 | /// Gets or sets the array of item ids of which to retrieve the info
15 | ///
16 | /// must not be null or empty
17 | [DataMember(Name = "itemIds")]
18 | public IEnumerable ItemIds { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Receiver/ReceiverStatus.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Models.Receiver
5 | {
6 | ///
7 | /// Receiver status
8 | ///
9 | [DataContract]
10 | public class ReceiverStatus
11 | {
12 | ///
13 | /// Gets or sets the applications collection
14 | ///
15 | [DataMember(Name = "applications")]
16 | public IEnumerable Applications { get; set; }
17 |
18 | ///
19 | /// Gets or sets the volume
20 | ///
21 | [DataMember(Name = "volume")]
22 | public Volume Volume { get; set; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/TextTrackEdgeType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Possible text track edge types
5 | ///
6 | public enum TextTrackEdgeType
7 | {
8 | ///
9 | /// None
10 | ///
11 | None,
12 |
13 | ///
14 | /// Outline
15 | ///
16 | Outline,
17 |
18 | ///
19 | /// Drop shadow
20 | ///
21 | DropShadow,
22 |
23 | ///
24 | /// Raised
25 | ///
26 | Raised,
27 |
28 | ///
29 | /// Depressed
30 | ///
31 | Depressed
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/QueueChangeType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Queue change type
5 | ///
6 | public enum QueueChangeType
7 | {
8 | ///
9 | /// Insert
10 | ///
11 | Insert = 0,
12 |
13 | ///
14 | /// Remove
15 | ///
16 | Remove = 1,
17 |
18 | ///
19 | /// Items Change
20 | ///
21 | ItemsChange = 2,
22 |
23 | ///
24 | /// Update
25 | ///
26 | Update = 3,
27 |
28 | ///
29 | /// No Change
30 | ///
31 | NoChange = 4
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/GoogleCast/IDeviceLocator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace GoogleCast
6 | {
7 | ///
8 | /// Interface for the device locator
9 | ///
10 | public interface IDeviceLocator
11 | {
12 | ///
13 | /// Finds the available receivers
14 | ///
15 | /// a collection of receivers
16 | Task> FindReceiversAsync();
17 |
18 | ///
19 | /// Finds the available receivers in continuous way
20 | ///
21 | /// a provider for notifications
22 | IObservable FindReceiversContinuous();
23 | }
24 | }
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueInsertMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 |
5 | namespace GoogleCast.Messages.Media
6 | {
7 | ///
8 | /// A request to load and optionally start playback of a new ordered list of media items
9 | ///
10 | [DataContract]
11 | class QueueInsertMessage : QueueMessage
12 | {
13 | ///
14 | /// Gets or sets the array of items to insert into the queue. It is sorted (first element will be played first)
15 | ///
16 | /// must not be null or empty
17 | [DataMember(Name = "items")]
18 | public IEnumerable Items { get; set; }
19 | }
20 | }
--------------------------------------------------------------------------------
/GoogleCast/Channels/IChannel.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages;
2 | using System.Threading.Tasks;
3 |
4 | namespace GoogleCast.Channels
5 | {
6 | ///
7 | /// Interface for a channel
8 | ///
9 | public interface IChannel
10 | {
11 | ///
12 | /// Gets or sets the sender
13 | ///
14 | ISender Sender { get; set; }
15 |
16 | ///
17 | /// Gets the full namespace
18 | ///
19 | string Namespace { get; }
20 |
21 | ///
22 | /// Called when a message for this channel is received
23 | ///
24 | /// message to process
25 | Task OnMessageReceivedAsync(IMessage message);
26 | }
27 | }
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueUpdateMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// Message to update the queue
8 | ///
9 | [DataContract]
10 | class QueueUpdateMessage : MediaSessionMessage
11 | {
12 | ///
13 | /// Gets or sets the item id of the currently playing media
14 | ///
15 | [DataMember(Name = "currentItemId")]
16 | public int? CurrentItemId { get; set; }
17 |
18 | ///
19 | /// Gets or sets the shuffle state
20 | ///
21 | [DataMember(Name = "shuffle")]
22 | public bool? Shuffle { get; set; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueChangeMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages.Media
5 | {
6 | ///
7 | /// Message to retrieve all changed queued item ids
8 | ///
9 | [DataContract]
10 | [ReceptionMessage]
11 | class QueueChangeMessage : MessageWithId
12 | {
13 | ///
14 | /// Gets or sets the item id array
15 | ///
16 | [DataMember(Name = "itemIds")]
17 | public int[] ItemIds { get; set; }
18 |
19 | ///
20 | /// Gets or sets the item id array
21 | ///
22 | [DataMember(Name = "changeType")]
23 | public string ChangeType { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Image.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Models
4 | {
5 | ///
6 | /// Image
7 | ///
8 | [DataContract]
9 | public class Image
10 | {
11 | ///
12 | /// Gets or sets the URI for the image
13 | ///
14 | [DataMember(Name = "url")]
15 | public string Url { get; set; }
16 |
17 | ///
18 | /// Gets or sets the height of the image
19 | ///
20 | [DataMember(Name = "height")]
21 | public int? Height { get; set; }
22 |
23 | ///
24 | /// Gets or sets the width of the image
25 | ///
26 | [DataMember(Name = "width")]
27 | public int? Width { get; set; }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Volume.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Models
4 | {
5 | ///
6 | /// Volume
7 | ///
8 | [DataContract]
9 | public class Volume
10 | {
11 | ///
12 | /// Gets or sets the volume level
13 | ///
14 | [DataMember(Name = "level", EmitDefaultValue = false)]
15 | public float? Level { get; set; }
16 |
17 | ///
18 | /// Gets or sets a value indicating whether the audio is muted
19 | ///
20 | [DataMember(Name = "muted", EmitDefaultValue = false)]
21 | public bool? IsMuted { get; set; }
22 |
23 | ///
24 | /// Gets or sets the step interval
25 | ///
26 | [DataMember(Name = "stepInterval")]
27 | public float StepInterval { get; set; }
28 | }
29 | }
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/TextTrackFontGenericFamily.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Text track font generic family
5 | ///
6 | public enum TextTrackFontGenericFamily
7 | {
8 | ///
9 | /// Sans serif
10 | ///
11 | SansSerif,
12 |
13 | ///
14 | /// Monospaced sans serif
15 | ///
16 | MonospacedSansSerif,
17 |
18 | ///
19 | /// Serif
20 | ///
21 | Serif,
22 |
23 | ///
24 | /// Monospaced serif
25 | ///
26 | MonospacedSerif,
27 |
28 | ///
29 | /// Casual
30 | ///
31 | Casual,
32 |
33 | ///
34 | /// Cursive
35 | ///
36 | Cursive,
37 |
38 | ///
39 | /// Small capitals
40 | ///
41 | SmallCapitals
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Message.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Messages
5 | {
6 | ///
7 | /// Message base class
8 | ///
9 | [DataContract]
10 | public abstract class Message : IMessage
11 | {
12 | ///
13 | /// Initialization
14 | ///
15 | public Message()
16 | {
17 | Type = GetMessageType(GetType());
18 | }
19 |
20 | ///
21 | /// Gets the message type
22 | ///
23 | [DataMember(Name = "type")]
24 | public string Type { get; set; }
25 |
26 | ///
27 | /// Gets the message type
28 | ///
29 | /// message class type
30 | public static string GetMessageType(Type type)
31 | {
32 | var typeName = type.Name;
33 | return typeName.Substring(0, typeName.LastIndexOf(nameof(Message))).ToUnderscoreUpperInvariant();
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/GoogleCast/Channels/HeartbeatChannel.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages;
2 | using GoogleCast.Messages.Heartbeat;
3 | using System.Threading.Tasks;
4 |
5 | namespace GoogleCast.Channels
6 | {
7 | ///
8 | /// Heartbeat channel
9 | ///
10 | class HeartbeatChannel : Channel, IHeartbeatChannel
11 | {
12 | ///
13 | /// Initializes a new instance of class
14 | ///
15 | public HeartbeatChannel() : base("tp.heartbeat")
16 | {
17 | }
18 |
19 | ///
20 | /// Called when a message for this channel is received
21 | ///
22 | /// message to process
23 | public override async Task OnMessageReceivedAsync(IMessage message)
24 | {
25 | switch (message)
26 | {
27 | case PingMessage pingMessage:
28 | await SendAsync(new PongMessage());
29 | break;
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/MessageWithId.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 | using System.Threading;
4 |
5 | namespace GoogleCast.Messages
6 | {
7 | ///
8 | /// Message with request identifier
9 | ///
10 | [DataContract]
11 | public class MessageWithId : Message, IMessageWithId
12 | {
13 | private static int _id = new Random().Next();
14 |
15 | ///
16 | /// Gets a value indicating whether the message has a request identifier
17 | ///
18 | public bool HasRequestId
19 | {
20 | get { return _requestId != null; }
21 | }
22 |
23 | private int? _requestId;
24 | ///
25 | /// Gets or sets the request identifier
26 | ///
27 | [DataMember(Name = "requestId")]
28 | public int RequestId
29 | {
30 | get { return (int)(_requestId ?? (_requestId = Interlocked.Increment(ref _id))); }
31 | set { _requestId = value; }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/QueueStatus.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Models.Media
5 | {
6 | ///
7 | /// Queue status
8 | ///
9 | [DataContract]
10 | public class QueueStatus
11 | {
12 | ///
13 | /// Gets or sets the item id array
14 | ///
15 | [DataMember(Name = "itemIds")]
16 | public int[] ItemIds { get; set; }
17 |
18 | ///
19 | /// Gets or sets the type of media artifact
20 | ///
21 | [IgnoreDataMember]
22 | public QueueChangeType ChangeType { get; set; }
23 |
24 | ///
25 | /// Gets or sets the item id array
26 | ///
27 | [DataMember(Name = "changeType")]
28 | public string ChangeTypeString
29 | {
30 | get { return ChangeType.GetName(); }
31 | set { ChangeType = EnumHelper.Parse(value); }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/RepeatMode.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Possible states of queue repeat mode
5 | ///
6 | public enum RepeatMode
7 | {
8 | ///
9 | /// Items are played in order, and when the queue is completed (the last item has ended) the media session is terminated
10 | ///
11 | RepeatOff,
12 |
13 | ///
14 | /// The items in the queue will be played indefinitely. When the last item has ended, the first item will be played again
15 | ///
16 | RepeatAll,
17 |
18 | ///
19 | /// The current item will be repeated indefinitely
20 | ///
21 | RepeatSingle,
22 |
23 | ///
24 | /// The items in the queue will be played indefinitely.
25 | /// When the last item has ended, the list of items will be randomly shuffled by the receiver,
26 | /// and the queue will continue to play starting from the first item of the shuffled items.
27 | ///
28 | RepeatAllAndShuffle
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/GoogleCast/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Channels;
2 | using Microsoft.Extensions.DependencyInjection;
3 | using System.Linq;
4 | using System.Reflection;
5 |
6 | namespace GoogleCast
7 | {
8 | ///
9 | /// Services registration
10 | ///
11 | public static class ServiceCollectionExtensions
12 | {
13 | ///
14 | /// Registers the services
15 | ///
16 | /// services to register
17 | /// the service descriptors collection
18 | public static IServiceCollection AddGoogleCast(this IServiceCollection services)
19 | {
20 | services.AddSingleton();
21 |
22 | // Add channels
23 | var channelType = typeof(IChannel);
24 | foreach (var type in Assembly.GetExecutingAssembly().GetTypes().Where(t =>
25 | t.IsClass && !t.IsAbstract && channelType.IsAssignableFrom(t)))
26 | {
27 | services.AddTransient(channelType, type);
28 | }
29 |
30 | return services;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/TextTrackType.cs:
--------------------------------------------------------------------------------
1 | namespace GoogleCast.Models.Media
2 | {
3 | ///
4 | /// Possible text track types
5 | ///
6 | public enum TextTrackType
7 | {
8 | ///
9 | /// Transcription or translation of the dialogue, suitable for when the sound is available but not understood
10 | ///
11 | Subtitles,
12 |
13 | ///
14 | /// Transcription or translation of the dialogue, sound effects, relevant musical cues, and other relevant audio information,
15 | /// suitable for when the soundtrack is unavailable
16 | ///
17 | Captions,
18 |
19 | ///
20 | /// Textual descriptions of the video component of the media resource, intended for audio synthesis when
21 | /// the visual component is unavailable
22 | ///
23 | Descriptions,
24 |
25 | ///
26 | /// Chapter titles, intended to be used for navigating the media resource
27 | ///
28 | Chapters,
29 |
30 | ///
31 | /// Tracks intended for use from script
32 | ///
33 | Metadata
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/LoadMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 |
5 | namespace GoogleCast.Messages.Media
6 | {
7 | ///
8 | /// Message to load new content into the media player
9 | ///
10 | [DataContract]
11 | class LoadMessage : SessionMessage
12 | {
13 | ///
14 | /// Gets or sets the metadata (including contentId) of the media to load
15 | ///
16 | [DataMember(Name = "media")]
17 | public MediaInformation Media { get; set; }
18 |
19 | ///
20 | /// Gets or sets a value indicating whether the media player will begin playing the content when it is loaded or not
21 | ///
22 | [DataMember(Name = "autoplay")]
23 | public bool AutoPlay { get; set; }
24 |
25 | ///
26 | /// Gets or sets the identifiers of the tracks that should be active.
27 | ///
28 | /// if the array is not provided, the default tracks will be active
29 | [DataMember(Name = "activeTrackIds")]
30 | public IEnumerable ActiveTrackIds { get; set; }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/GoogleCast/MessageTypes.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 |
7 | namespace GoogleCast
8 | {
9 | ///
10 | /// Dictionary of message types
11 | ///
12 | public class MessageTypes : Dictionary, IMessageTypes
13 | {
14 | ///
15 | /// Initializes a new instance of class
16 | ///
17 | public MessageTypes()
18 | {
19 | AddMessageTypes(Assembly.GetExecutingAssembly());
20 | }
21 |
22 | ///
23 | /// Adds all the message types of a given assembly
24 | ///
25 | /// assembly
26 | public void AddMessageTypes(Assembly assembly)
27 | {
28 | var messageInterfaceType = typeof(IMessage);
29 | var receptionMessageAttributeType = typeof(ReceptionMessageAttribute);
30 | foreach (var type in assembly.GetTypes().Where(t =>
31 | t.IsClass && !t.IsAbstract && t.IsDefined(receptionMessageAttributeType) && messageInterfaceType.IsAssignableFrom(t)))
32 | {
33 | Add(Message.GetMessageType(type), type);
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/ConnectionChannel.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages;
2 | using GoogleCast.Messages.Connection;
3 | using System.Threading.Tasks;
4 |
5 | namespace GoogleCast.Channels
6 | {
7 | ///
8 | /// Connection channel
9 | ///
10 | class ConnectionChannel : Channel, IConnectionChannel
11 | {
12 | ///
13 | /// Initializes a new instance of class
14 | ///
15 | public ConnectionChannel() : base("tp.connection")
16 | {
17 | }
18 |
19 | ///
20 | /// Connects
21 | ///
22 | /// destination identifier
23 | public async Task ConnectAsync(string destinationId)
24 | {
25 | await SendAsync(new ConnectMessage(), destinationId);
26 | }
27 |
28 | ///
29 | /// Called when a message for this channel is received
30 | ///
31 | /// message to process
32 | public async override Task OnMessageReceivedAsync(IMessage message)
33 | {
34 | if (message is CloseMessage)
35 | {
36 | await Sender.DisconnectAsync();
37 | }
38 | await base.OnMessageReceivedAsync(message);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/GoogleCast/Receiver.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 |
3 | namespace GoogleCast
4 | {
5 | ///
6 | /// GoogleCast receiver
7 | ///
8 | public class Receiver : IReceiver
9 | {
10 | ///
11 | /// Gets or sets the friendly name
12 | ///
13 | public string FriendlyName { get; set; }
14 |
15 | ///
16 | /// Gets or sets the network endpoint
17 | ///
18 | public IPEndPoint IPEndPoint { get; set; }
19 |
20 | ///
21 | /// Determines whether the specified object is equal to the current object
22 | ///
23 | /// The object to compare with the current object
24 | /// true if the specified object is equal to the current object; otherwise, false
25 | public override bool Equals(object obj)
26 | {
27 | return (obj is Receiver receiver && receiver.FriendlyName == FriendlyName &&
28 | (receiver.IPEndPoint != null && receiver.IPEndPoint.Equals(IPEndPoint) || receiver.IPEndPoint == null && IPEndPoint == null));
29 | }
30 |
31 | ///
32 | /// Serves as the default hash function
33 | ///
34 | /// A hash code for the current object
35 | public override int GetHashCode()
36 | {
37 | return IPEndPoint.GetHashCode();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/EditTracksInfoMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 |
5 | namespace GoogleCast.Messages.Media
6 | {
7 | ///
8 | /// Media event EDIT_TRACKS_INFO request data
9 | ///
10 | [DataContract]
11 | class EditTracksInfoMessage : MediaSessionMessage
12 | {
13 | ///
14 | /// Gets or sets the track identifiers that should be active
15 | ///
16 | [DataMember(Name = "activeTrackIds")]
17 | public IEnumerable ActiveTrackIds { get; set; }
18 |
19 | ///
20 | /// Gets or sets a value indicating whether the text tracks should be enabled or not
21 | ///
22 | [DataMember(Name = "enableTextTracks")]
23 | public bool EnableTextTracks { get; set; }
24 |
25 | ///
26 | /// Gets or sets the language for the tracks that should be active
27 | ///
28 | [DataMember(Name = "language")]
29 | public string Language { get; set; }
30 |
31 | ///
32 | /// Gets or sets the text track style.
33 | /// If it is not provided the existing style will be used (if no style was provided in previous calls, it will be the default receiver style)
34 | ///
35 | [DataMember(Name = "textTrackStyle")]
36 | public TextTrackStyle TextTrackStyle { get; set; }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/GoogleCast/Messages/Media/QueueLoadMessage.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Media;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 |
5 | namespace GoogleCast.Messages.Media
6 | {
7 | ///
8 | /// A request to load and optionally start playback of a new ordered list of media items
9 | ///
10 | [DataContract]
11 | class QueueLoadMessage : SessionMessage
12 | {
13 | ///
14 | /// Gets or sets the array of items to load. It is sorted (first element will be played first)
15 | ///
16 | /// must not be null or empty
17 | [DataMember(Name = "items")]
18 | public IEnumerable Items { get; set; }
19 |
20 | ///
21 | /// Gets or sets the algorithm for selection of the next item when the current item has ended
22 | ///
23 | [IgnoreDataMember]
24 | public RepeatMode RepeatMode { get; set; }
25 |
26 | [DataMember(Name = "repeatMode")]
27 | private string RepeatModeString
28 | {
29 | get { return RepeatMode.GetName(); }
30 | set { RepeatMode = EnumHelper.Parse(value); }
31 | }
32 |
33 | ///
34 | /// Gets or sets the index of the item in the items array that must be the first currentItem (the item that will be played first)
35 | ///
36 | [DataMember(Name = "startIndex")]
37 | public int StartIndex { get; set; }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("TestCSharpDll")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("TestCSharpDll")]
13 | [assembly: AssemblyCopyright("Copyright © 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("c1acdbd8-6b22-4807-bba3-d0237ccd74c1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/GoogleCast/TaskExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace GoogleCast
5 | {
6 | ///
7 | /// Extensions methods for Task class
8 | ///
9 | public static class TaskExtensions
10 | {
11 | ///
12 | /// Throws a TimeoutException if a task is not completed before a delay
13 | ///
14 | /// return type
15 | /// task
16 | /// the delay in milliseconds
17 | /// T
18 | public static async Task TimeoutAfter(this Task task, int delay)
19 | {
20 | await Task.WhenAny(task, Task.Delay(delay));
21 | if (!task.IsCompleted)
22 | {
23 | throw new TimeoutException();
24 | }
25 |
26 | return await task;
27 | }
28 |
29 | ///
30 | /// Throws a TimeoutException if a task is not completed before a delay
31 | ///
32 | /// task
33 | /// the delay in milliseconds
34 | /// T
35 | public static async Task TimeoutAfter(this Task task, int delay)
36 | {
37 | await Task.WhenAny(task, Task.Delay(delay));
38 | if (!task.IsCompleted)
39 | {
40 | throw new TimeoutException();
41 | }
42 |
43 | await task;
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/GoogleCast/DeviceLocator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Reactive.Linq;
6 | using System.Threading.Tasks;
7 | using Zeroconf;
8 |
9 | namespace GoogleCast
10 | {
11 | ///
12 | /// Device locator
13 | ///
14 | public class DeviceLocator : IDeviceLocator
15 | {
16 | private const string PROTOCOL = "_googlecast._tcp.local.";
17 |
18 | private Receiver CreateReceiver(IZeroconfHost host)
19 | {
20 | var service = host.Services[PROTOCOL];
21 | return new Receiver()
22 | {
23 | FriendlyName = service.Properties[0]["fn"],
24 | IPEndPoint = new IPEndPoint(IPAddress.Parse(host.IPAddress), service.Port)
25 | };
26 | }
27 |
28 | ///
29 | /// Finds the available receivers
30 | ///
31 | /// a collection of receivers
32 | public async Task> FindReceiversAsync()
33 | {
34 | return (await ZeroconfResolver.ResolveAsync(PROTOCOL)).Select(CreateReceiver);
35 | }
36 |
37 | ///
38 | /// Finds the available receivers in continuous way
39 | ///
40 | /// a provider for notifications
41 | public IObservable FindReceiversContinuous()
42 | {
43 | return ZeroconfResolver.ResolveContinuous(PROTOCOL).Select(CreateReceiver);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/MusicTrackMediaMetadata.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Models.Media
4 | {
5 | ///
6 | /// Music metadata
7 | ///
8 | [DataContract]
9 | public class MusicTrackMediaMetadata : GenericMediaMetadata
10 | {
11 | ///
12 | /// Initializes a new instance of class
13 | ///
14 | public MusicTrackMediaMetadata()
15 | {
16 | MetadataType = MetadataType.Music;
17 | }
18 |
19 | [DataMember(Name = "albumArtist", EmitDefaultValue = false)]
20 | public string AlbumArtist { get; set; }
21 |
22 | [DataMember(Name = "albumName", EmitDefaultValue = false)]
23 | public string AlbumName { get; set; }
24 |
25 | [DataMember(Name = "artist", EmitDefaultValue = false)]
26 | public string Artist { get; set; }
27 |
28 | [DataMember(Name = "composer", EmitDefaultValue = false)]
29 | public string Composer { get; set; }
30 |
31 | [DataMember(Name = "discNumber", EmitDefaultValue = false)]
32 | public int? DiscNumber { get; set; }
33 |
34 | [DataMember(Name = "releaseDate", EmitDefaultValue = false)]
35 | public string ReleaseDate { get; set; }
36 |
37 | [DataMember(Name = "songName", EmitDefaultValue = false)]
38 | public string SongName { get; set; }
39 |
40 | [DataMember(Name = "trackNumber", EmitDefaultValue = false)]
41 | public int? TrackNumber { get; set; }
42 | }
43 | }
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/GenericMediaMetadata.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Models.Media
4 | {
5 | ///
6 | /// Media metadata
7 | ///
8 | [DataContract]
9 | [KnownType(typeof(GenericMediaMetadata))]
10 | [KnownType(typeof(MovieMetadata))]
11 | [KnownType(typeof(MusicTrackMediaMetadata))]
12 | public class GenericMediaMetadata
13 | {
14 | ///
15 | /// Initializes a new instance of class
16 | ///
17 | public GenericMediaMetadata()
18 | {
19 | MetadataType = MetadataType.Default;
20 | }
21 |
22 | ///
23 | /// Gets the metadata type
24 | ///
25 | [DataMember(Name = "metadataType")]
26 | public MetadataType MetadataType { get; protected set; }
27 |
28 | ///
29 | /// Gets or sets the descriptive title of the content
30 | ///
31 | [DataMember(Name = "title")]
32 | public string Title { get; set; }
33 |
34 | ///
35 | /// Gets or sets the descriptive subtitle of the content
36 | ///
37 | [DataMember(Name = "subtitle")]
38 | public string Subtitle { get; set; }
39 |
40 | ///
41 | /// Gets or sets an array of URL(s) to an image associated with the content
42 | ///
43 | [DataMember(Name = "images")]
44 | public Image[] Images { get; set; }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Receiver/Application.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Models.Receiver
5 | {
6 | ///
7 | /// Application
8 | ///
9 | [DataContract]
10 | public class Application
11 | {
12 | ///
13 | /// Gets or sets the application identifier
14 | ///
15 | [DataMember(Name = "appId")]
16 | public string AppId { get; set; }
17 |
18 | ///
19 | /// Gets or sets the display name
20 | ///
21 | [DataMember(Name = "displayName")]
22 | public string DisplayName { get; set; }
23 |
24 | ///
25 | /// Gets or sets a value indicating whether the backdrop app is running or not
26 | ///
27 | [DataMember(Name = "isIdleScreen")]
28 | public bool IsIdleScreen { get; set; }
29 |
30 | ///
31 | /// Gets or sets the namespaces
32 | ///
33 | [DataMember(Name = "namespaces")]
34 | public IEnumerable Namespaces { get; set; }
35 |
36 | ///
37 | /// Gets or sets the session identifier
38 | ///
39 | [DataMember(Name = "sessionId")]
40 | public string SessionId { get; set; }
41 |
42 | ///
43 | /// Gets or sets the status text
44 | ///
45 | [DataMember(Name = "statusText")]
46 | public string StatusText { get; set; }
47 |
48 | ///
49 | /// Gets or sets the transport identifier
50 | ///
51 | [DataMember(Name = "transportId")]
52 | public string TransportId { get; set; }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/GoogleCast/CastMessage.cs:
--------------------------------------------------------------------------------
1 | using ProtoBuf;
2 |
3 | namespace GoogleCast
4 | {
5 | ///
6 | /// Cast message
7 | ///
8 | [ProtoContract]
9 | class CastMessage
10 | {
11 | ///
12 | /// Gets or sets the protocol version
13 | ///
14 | [ProtoMember(1, IsRequired = true, Name = "protocol_version")]
15 | public ProtocolVersion ProtocolVersion { get; set; }
16 |
17 | ///
18 | /// Gets or sets the source identifier
19 | ///
20 | [ProtoMember(2, IsRequired = true, Name = "source_id")]
21 | public string SourceId { get; set; } = "sender-0";
22 |
23 | ///
24 | /// Gets or sets the destination identifier
25 | ///
26 | [ProtoMember(3, IsRequired = true, Name = "destination_id")]
27 | public string DestinationId { get; set; } = "receiver-0";
28 |
29 | ///
30 | /// Gets or sets the namespace
31 | ///
32 | [ProtoMember(4, IsRequired = true, Name = "namespace")]
33 | public string Namespace { get; set; }
34 |
35 | ///
36 | /// Gets or sets the payload type
37 | ///
38 | [ProtoMember(5, IsRequired = true, Name = "payload_type")]
39 | public PayloadType PayloadType { get; set; }
40 |
41 | ///
42 | /// Gets or sets the UTF-8 payload
43 | ///
44 | [ProtoMember(6, IsRequired = false, Name = "payload_utf8")]
45 | public string PayloadUtf8 { get; set; }
46 |
47 | ///
48 | /// Gets or sets the binary payload
49 | ///
50 | [ProtoMember(7, IsRequired = false, Name = "payload_binary")]
51 | public byte[] PayloadBinary { get; set; }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/IReceiverChannel.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Models.Receiver;
2 | using System.Threading.Tasks;
3 |
4 | namespace GoogleCast.Channels
5 | {
6 | ///
7 | /// Interface for the receiver channel
8 | ///
9 | public interface IReceiverChannel : IStatusChannel
10 | {
11 | ///
12 | /// Retrieves the status
13 | ///
14 | /// the status
15 | Task GetStatusAsync();
16 |
17 | ///
18 | /// Launches an application
19 | ///
20 | /// application identifier
21 | /// receiver status
22 | Task LaunchAsync(string applicationId);
23 |
24 | ///
25 | /// Checks the connection is well established
26 | ///
27 | /// namespace
28 | /// an application object
29 | Task EnsureConnectionAsync(string ns);
30 |
31 | ///
32 | /// Sets the volume
33 | ///
34 | /// volume level (0.0 to 1.0)
35 | /// receiver status
36 | Task SetVolumeAsync(float level);
37 |
38 | ///
39 | /// Sets a value indicating whether the audio should be muted
40 | ///
41 | /// true if audio should be muted; otherwise, false
42 | /// receiver status
43 | Task SetIsMutedAsync(bool isMuted);
44 |
45 | ///
46 | /// Stops the current applications
47 | ///
48 | /// applications to stop
49 | /// ReceiverStatus
50 | Task StopAsync(params Application[] applications);
51 | }
52 | }
--------------------------------------------------------------------------------
/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Settings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 | using System.Threading;
5 | using System.Windows.Forms;
6 | using System.Xml;
7 |
8 | namespace MusicBeePlugin
9 | {
10 | public partial class Settings : Form
11 | {
12 | private static string SettingsPath { get; set; }
13 |
14 | public Settings(string @path)
15 | {
16 | SettingsPath = path;
17 | InitializeComponent();
18 | ReadSettings();
19 |
20 | }
21 |
22 | private void folderBrowserDialog1_HelpRequest(object sender, EventArgs e)
23 | {
24 |
25 | }
26 |
27 |
28 |
29 | public void CreateSettings()
30 | {
31 | using (var writer = new XmlTextWriter(SettingsPath + @"\MB_Chromecast_Settings.xml", Encoding.UTF8))
32 | {
33 | writer.Formatting = Formatting.Indented;
34 | //Write the root element
35 | writer.WriteStartElement("settings");
36 |
37 | //Write sub-elements
38 | writer.WriteElementString("server_port", ((int)serverPortSelect.Value).ToString());
39 |
40 | // end the root element
41 | writer.WriteEndElement();
42 | }
43 |
44 | }
45 |
46 | private void ReadSettings()
47 | {
48 | if (File.Exists(SettingsPath + @"\MB_Chromecast_Settings.xml"))
49 | {
50 | XmlDocument doc = new XmlDocument();
51 | doc.Load(SettingsPath + @"\MB_Chromecast_Settings.xml");
52 | var temp = doc.GetElementsByTagName("server_port")[0].InnerText;
53 | if (!string.IsNullOrEmpty(temp))
54 | {
55 | serverPortSelect.Value = Convert.ToDecimal(temp);
56 | }
57 | }
58 | }
59 |
60 | private void closeText_Click(object sender, EventArgs e)
61 | {
62 | this.Close();
63 | }
64 |
65 | private void saveText_Click(object sender, EventArgs e)
66 | {
67 | CreateSettings();
68 | this.Close();
69 | }
70 |
71 |
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/QueueItem.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Models.Media
5 | {
6 | ///
7 | /// Queue item information
8 | ///
9 | [DataContract]
10 | public class QueueItem
11 | {
12 | ///
13 | /// Gets or sets the track identifiers that are active
14 | ///
15 | [DataMember(Name = "activeTrackIds", EmitDefaultValue = false)]
16 | public IEnumerable ActiveTrackIds { get; set; }
17 |
18 | ///
19 | /// Gets or sets a value indicating whether the media will automatically play
20 | ///
21 | [DataMember(Name = "autoplay")]
22 | public bool Autoplay { get; set; } = true;
23 |
24 | ///
25 | /// Gets or sets the unique identifier of the item in the queue
26 | ///
27 | /// the attribute is optional because for LOAD or INSERT should not be provided
28 | /// (as it will be assigned by the receiver when an item is first created/inserted).
29 | [DataMember(Name = "itemId", EmitDefaultValue = false)]
30 | public int? ItemId { get; set; }
31 |
32 | ///
33 | /// Gets or sets the metadata (including contentId) of the playlist element
34 | ///
35 | [DataMember(Name = "media")]
36 | public MediaInformation Media { get; set; }
37 |
38 | ///
39 | /// Gets or sets the seconds from the beginning of the media to start playback
40 | ///
41 | [DataMember(Name = "startTime", EmitDefaultValue = false)]
42 | public int? StartTime { get; set; }
43 |
44 | ///
45 | /// Gets or sets the seconds from the beginning of the media to start playback
46 | ///
47 | [DataMember(Name = "preloadTime", EmitDefaultValue = false)]
48 | public int? PreloadTime { get; set; }
49 |
50 | ///
51 | /// Gets or sets the ordered number of the queue item
52 | ///
53 | [DataMember(Name = "orderId", EmitDefaultValue = false)]
54 | public int? OrderId { get; set; }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/GoogleCast/ColorHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 |
4 | namespace GoogleCast
5 | {
6 | ///
7 | /// Helper for class
8 | ///
9 | public static class ColorHelper
10 | {
11 | ///
12 | /// Converts a string to a
13 | ///
14 | /// color string to convert
15 | /// the color object
16 | public static Color FromHexString(string color)
17 | {
18 | return Color.FromArgb(
19 | Convert.ToInt32(color.Substring(7, 2), 16),
20 | Convert.ToInt32(color.Substring(1, 2), 16),
21 | Convert.ToInt32(color.Substring(3, 2), 16),
22 | Convert.ToInt32(color.Substring(5, 2), 16));
23 | }
24 |
25 | ///
26 | /// Converts a string to a nullable
27 | ///
28 | /// color string to convert
29 | /// the nullable color object
30 | public static Color? FromNullableHexString(string color)
31 | {
32 | if (string.IsNullOrEmpty(color))
33 | {
34 | return null;
35 | }
36 |
37 | return FromHexString(color);
38 | }
39 |
40 | ///
41 | /// Converts a color to an hexadecimal string (#RRGGBBAA)
42 | ///
43 | /// color to convert
44 | /// the hexadecimal string
45 | public static string ToHexString(this Color color)
46 | {
47 | return $"#{color.R.ToString("X2", null)}{color.G.ToString("X2", null)}{color.B.ToString("X2", null)}{color.A.ToString("X2", null)}";
48 | }
49 |
50 | ///
51 | /// Converts a nullable color to an hexadecimal string (#RRGGBBAA)
52 | ///
53 | /// nullable color to convert
54 | /// the hexadecimal string
55 | public static string ToHexString(this Color? color)
56 | {
57 | return color == null ? null : ToHexString((Color)color);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/StatusChannel.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace GoogleCast.Channels
7 | {
8 | ///
9 | /// Base class for status channels
10 | ///
11 | /// status type
12 | /// status message type
13 | public abstract class StatusChannel : Channel, IStatusChannel
14 | where TStatusMessage : IStatusMessage
15 | {
16 | ///
17 | /// Raised when the status has changed
18 | ///
19 | public event EventHandler StatusChanged;
20 |
21 | ///
22 | /// Initialization
23 | ///
24 | /// namespace
25 | public StatusChannel(string ns) : base(ns)
26 | {
27 | }
28 |
29 | private TStatus _status;
30 | ///
31 | /// Gets or sets the status
32 | ///
33 | public TStatus Status
34 | {
35 | get { return _status; }
36 | protected set
37 | {
38 | if (!EqualityComparer.Default.Equals(_status, value))
39 | {
40 | _status = value;
41 | OnStatusChanged();
42 | }
43 | }
44 | }
45 |
46 | ///
47 | /// Called when a message for this channel is received
48 | ///
49 | /// message to process
50 | public override Task OnMessageReceivedAsync(IMessage message)
51 | {
52 | switch (message)
53 | {
54 | case TStatusMessage statusMessage:
55 | Status = statusMessage.Status;
56 | break;
57 | }
58 |
59 | return base.OnMessageReceivedAsync(message);
60 | }
61 |
62 | ///
63 | /// Raises the StatusChanged event
64 | ///
65 | protected virtual void OnStatusChanged()
66 | {
67 | StatusChanged?.Invoke(this, EventArgs.Empty);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/GoogleCast/Channels/Channel.cs:
--------------------------------------------------------------------------------
1 | using GoogleCast.Messages;
2 | using System.Threading.Tasks;
3 |
4 | namespace GoogleCast.Channels
5 | {
6 | ///
7 | /// Channel base class
8 | ///
9 | public abstract class Channel : IChannel
10 | {
11 | private const string BASE_NAMESPACE = "urn:x-cast:com.google.cast";
12 |
13 | ///
14 | /// Initialization
15 | ///
16 | protected Channel()
17 | {
18 | }
19 |
20 | ///
21 | /// Initialization
22 | ///
23 | /// namespace
24 | protected Channel(string ns)
25 | {
26 | Namespace = $"{BASE_NAMESPACE}.{ns}";
27 | }
28 |
29 | ///
30 | /// Gets or sets the sender
31 | ///
32 | public virtual ISender Sender { get; set; }
33 |
34 | ///
35 | /// Gets the full namespace
36 | ///
37 | public string Namespace { get; protected set; }
38 |
39 | ///
40 | /// Sends a message
41 | ///
42 | /// message to send
43 | /// destination identifier
44 | protected async Task SendAsync(IMessage message, string destinationId = DefaultIdentifiers.DESTINATION_ID)
45 | {
46 | await Sender.SendAsync(Namespace, message, destinationId);
47 | }
48 |
49 | ///
50 | /// Sends a message and waits the result
51 | ///
52 | /// response type
53 | /// message to send
54 | /// destination identifier
55 | /// the result
56 | protected async Task SendAsync(IMessageWithId message, string destinationId = DefaultIdentifiers.DESTINATION_ID) where TResponse : IMessageWithId
57 | {
58 | return await Sender.SendAsync(Namespace, message, destinationId);
59 | }
60 |
61 | ///
62 | /// Called when a message for this channel is received
63 | ///
64 | /// message to process
65 | public virtual Task OnMessageReceivedAsync(IMessage message)
66 | {
67 | return Task.CompletedTask;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/Track.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace GoogleCast.Models.Media
4 | {
5 | ///
6 | /// Track metadata information
7 | ///
8 | [DataContract]
9 | public class Track
10 | {
11 | ///
12 | /// Gets or sets the unique identifier of the track
13 | ///
14 | [DataMember(Name = "trackId")]
15 | public int TrackId { get; set; }
16 |
17 | ///
18 | /// Gets or sets the type of track
19 | ///
20 | [IgnoreDataMember]
21 | public TrackType Type { get; set; } = TrackType.Text;
22 |
23 | [DataMember(Name = "type")]
24 | private string TypeString
25 | {
26 | get { return Type.GetName(); }
27 | set { Type = EnumHelper.Parse(value); }
28 | }
29 |
30 | ///
31 | /// Gets or sets the MIME type of the track content
32 | ///
33 | [DataMember(Name = "trackContentType")]
34 | public string TrackContentType { get; set; } = "text/vtt";
35 |
36 | ///
37 | /// Gets or sets the identifier of the track’s content
38 | ///
39 | /// it can be the url of the track or any other identifier that allows the receiver to find the content
40 | /// (when the track is not inband or included in the manifest)
41 | [DataMember(Name = "trackContentId")]
42 | public string TrackContentId { get; set; }
43 |
44 | ///
45 | /// Gets or sets the type of text track
46 | ///
47 | [IgnoreDataMember]
48 | public TextTrackType SubType { get; set; }
49 |
50 | [DataMember(Name = "subType")]
51 | private string SubTypeString
52 | {
53 | get { return SubType.GetName(); }
54 | set { SubType = EnumHelper.Parse(value); }
55 | }
56 |
57 | ///
58 | /// Gets or sets a descriptive, human readable name for the track
59 | ///
60 | [DataMember(Name = "name")]
61 | public string Name { get; set; }
62 |
63 | ///
64 | /// Gets or sets the language tag as per RFC 5646
65 | ///
66 | /// mandatory when the subtype is Subtitles
67 | [DataMember(Name = "language")]
68 | public string Language { get; set; }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/GoogleCast/Models/Media/MediaInformation.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Runtime.Serialization;
3 |
4 | namespace GoogleCast.Models.Media
5 | {
6 | ///
7 | /// Describes a media stream
8 | ///
9 | [DataContract]
10 | public class MediaInformation
11 | {
12 | ///
13 | /// Gets or sets the service-specific identifier of the content currently loaded by the media player
14 | ///
15 | [DataMember(Name = "contentId")]
16 | public string ContentId { get; set; }
17 |
18 | ///
19 | /// Gets or sets the type of media artifact
20 | ///
21 | [IgnoreDataMember]
22 | public StreamType StreamType { get; set; } = StreamType.Buffered;
23 |
24 | [DataMember(Name = "streamType")]
25 | private string StreamTypeString
26 | {
27 | get { return StreamType.GetName(); }
28 | set { StreamType = EnumHelper.Parse(value); }
29 | }
30 |
31 | ///
32 | /// Gets or sets the MIME content type of the media being played
33 | ///
34 | [DataMember(Name = "contentType", EmitDefaultValue = false)]
35 | public string ContentType { get; set; }
36 |
37 | ///
38 | /// Gets or sets the media metadata object
39 | ///
40 | [DataMember(Name = "metadata", EmitDefaultValue = false)]
41 | public GenericMediaMetadata Metadata { get; set; }
42 |
43 | ///
44 | /// Gets or sets the duration of the currently playing stream in seconds
45 | ///
46 | [DataMember(Name = "duration", EmitDefaultValue = false)]
47 | public double? Duration { get; set; }
48 |
49 | ///
50 | /// Gets or sets the custom data
51 | ///
52 | [DataMember(Name = "customData", EmitDefaultValue = false)]
53 | public IDictionary CustomData { get; set; }
54 |
55 | ///
56 | /// Gets or sets the tracks
57 | ///
58 | [DataMember(Name = "tracks", EmitDefaultValue = false)]
59 | public IEnumerable