1/*
2 * Copyright (C) 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#import "config.h"
27#import "RemoteCommandListenerIOS.h"
28
29#if PLATFORM(IOS)
30
31#import <MediaPlayer/MPRemoteCommandCenter.h>
32#import <MediaPlayer/MPRemoteCommandEvent.h>
33#import <MediaPlayer/MPRemoteCommand.h>
34#import <WebCore/SoftLinking.h>
35
36SOFT_LINK_FRAMEWORK(MediaPlayer)
37SOFT_LINK_CLASS(MediaPlayer, MPRemoteCommandCenter)
38SOFT_LINK_CLASS(MediaPlayer, MPSeekCommandEvent)
39
40namespace WebCore {
41
42std::unique_ptr<RemoteCommandListener> RemoteCommandListener::create(RemoteCommandListenerClient& client)
43{
44    return std::make_unique<RemoteCommandListenerIOS>(client);
45}
46
47RemoteCommandListenerIOS::RemoteCommandListenerIOS(RemoteCommandListenerClient& client)
48    : RemoteCommandListener(client)
49    , m_weakPtrFactory(this)
50{
51    MPRemoteCommandCenter *center = [getMPRemoteCommandCenterClass() sharedCommandCenter];
52    auto weakThis = createWeakPtr();
53
54    m_pauseTarget = [[center pauseCommand] addTargetWithHandler:^(MPRemoteCommandEvent *) {
55        callOnMainThread([weakThis] {
56            if (!weakThis)
57                return;
58            weakThis->m_client.didReceiveRemoteControlCommand(MediaSession::PauseCommand);
59        });
60
61        return MPRemoteCommandHandlerStatusSuccess;
62    }];
63
64    m_playTarget = [[center playCommand] addTargetWithHandler:^(MPRemoteCommandEvent *) {
65        callOnMainThread([weakThis] {
66            if (!weakThis)
67                return;
68            weakThis->m_client.didReceiveRemoteControlCommand(MediaSession::PlayCommand);
69        });
70
71        return MPRemoteCommandHandlerStatusSuccess;
72    }];
73
74    m_togglePlayPauseTarget = [[center togglePlayPauseCommand] addTargetWithHandler:^(MPRemoteCommandEvent *) {
75        callOnMainThread([weakThis] {
76            if (!weakThis)
77                return;
78            weakThis->m_client.didReceiveRemoteControlCommand(MediaSession::TogglePlayPauseCommand);
79        });
80
81        return MPRemoteCommandHandlerStatusSuccess;
82    }];
83
84    m_seekBackwardTarget = [[center seekBackwardCommand] addTargetWithHandler:^(MPRemoteCommandEvent *event) {
85        ASSERT([event isKindOfClass:getMPSeekCommandEventClass()]);
86
87        MPSeekCommandEvent* seekEvent = static_cast<MPSeekCommandEvent *>(event);
88        MediaSession::RemoteControlCommandType command = [seekEvent type] == MPSeekCommandEventTypeBeginSeeking ? MediaSession::BeginSeekingBackwardCommand : MediaSession::EndSeekingBackwardCommand;
89
90        callOnMainThread([weakThis, command] {
91            if (!weakThis)
92                return;
93            weakThis->m_client.didReceiveRemoteControlCommand(command);
94        });
95
96        return MPRemoteCommandHandlerStatusSuccess;
97    }];
98
99    m_seekForwardTarget = [[center seekForwardCommand] addTargetWithHandler:^(MPRemoteCommandEvent *event) {
100        ASSERT([event isKindOfClass:getMPSeekCommandEventClass()]);
101        MPSeekCommandEvent* seekEvent = static_cast<MPSeekCommandEvent *>(event);
102
103        MediaSession::RemoteControlCommandType command = [seekEvent type] == MPSeekCommandEventTypeBeginSeeking ? MediaSession::BeginSeekingForwardCommand : MediaSession::EndSeekingForwardCommand;
104
105        callOnMainThread([weakThis, command] {
106            if (!weakThis)
107                return;
108            weakThis->m_client.didReceiveRemoteControlCommand(command);
109        });
110
111        return MPRemoteCommandHandlerStatusSuccess;
112    }];
113}
114
115RemoteCommandListenerIOS::~RemoteCommandListenerIOS()
116{
117    MPRemoteCommandCenter *center = [getMPRemoteCommandCenterClass() sharedCommandCenter];
118    [[center pauseCommand] removeTarget:m_pauseTarget.get()];
119    [[center playCommand] removeTarget:m_playTarget.get()];
120    [[center togglePlayPauseCommand] removeTarget:m_togglePlayPauseTarget.get()];
121    [[center seekForwardCommand] removeTarget:m_seekForwardTarget.get()];
122    [[center seekBackwardCommand] removeTarget:m_seekBackwardTarget.get()];
123}
124
125}
126
127#endif
128