001/*
002 * Copyright (c) 2011-2017 Nexmo Inc
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a copy
005 * of this software and associated documentation files (the "Software"), to deal
006 * in the Software without restriction, including without limitation the rights
007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008 * copies of the Software, and to permit persons to whom the Software is
009 * furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
020 * THE SOFTWARE.
021 */
022package com.nexmo.client.voice.ncco;
023
024import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
025import com.fasterxml.jackson.annotation.JsonInclude;
026
027import java.util.Arrays;
028import java.util.Collection;
029
030/**
031 * An NCCO record action which allows for the call to be recorded.
032 */
033@JsonInclude(value = JsonInclude.Include.NON_NULL)
034@JsonIgnoreProperties(ignoreUnknown = true)
035public class RecordAction implements Action {
036    private static final String ACTION = "record";
037
038    private RecordingFormat format;
039    private Integer endOnSilence;
040    private Character endOnKey;
041    private Integer timeOut;
042    private Boolean beepStart;
043    private Collection<String> eventUrl;
044    private EventMethod eventMethod;
045    private SplitRecording split;
046    private Integer channels;
047
048    /**
049     * @deprecated Use {@link Builder}
050     */
051    @Deprecated
052    public RecordAction(Builder builder) {
053        this.format = builder.format;
054        this.endOnSilence = builder.endOnSilence;
055        this.endOnKey = builder.endOnKey;
056        this.timeOut = builder.timeOut;
057        this.beepStart = builder.beepStart;
058        this.eventUrl = builder.eventUrl;
059        this.eventMethod = builder.eventMethod;
060
061        // Split conversation must be enabled for multiple channels. Checked during construction to avoid
062        // method-chaining state confusion.
063        this.split = (builder.channels != null && builder.channels > 1) ? SplitRecording.CONVERSATION : builder.split;
064
065        this.channels = builder.channels;
066    }
067
068    @Override
069    public String getAction() {
070        return ACTION;
071    }
072
073    public RecordingFormat getFormat() {
074        return format;
075    }
076
077    public Integer getEndOnSilence() {
078        return endOnSilence;
079    }
080
081    public Character getEndOnKey() {
082        return endOnKey;
083    }
084
085    public Integer getTimeOut() {
086        return timeOut;
087    }
088
089    public Boolean getBeepStart() {
090        return beepStart;
091    }
092
093    public Collection<String> getEventUrl() {
094        return eventUrl;
095    }
096
097    public EventMethod getEventMethod() {
098        return eventMethod;
099    }
100
101    public SplitRecording getSplit() {
102        return split;
103    }
104
105    public Integer getChannels() {
106        return channels;
107    }
108
109    public static Builder builder() {
110        return new Builder();
111    }
112
113    public static class Builder {
114        private RecordingFormat format = null;
115        private Integer endOnSilence = null;
116        private Character endOnKey = null;
117        private Integer timeOut = null;
118        private Boolean beepStart = null;
119        private Collection<String> eventUrl = null;
120        private EventMethod eventMethod = null;
121        private SplitRecording split = null;
122        private Integer channels = null;
123
124        /**
125         * @param format Record the Call in a specific {@link RecordingFormat}.
126         *               <p>
127         *               The default value is {@link RecordingFormat#MP3}, or {@link RecordingFormat#WAV} when recording
128         *               more than 2 channels.
129         *
130         * @return The {@link Builder} to keep building.
131         */
132        public Builder format(RecordingFormat format) {
133            this.format = format;
134            return this;
135        }
136
137        /**
138         * @param endOnSilence Stop recording after n seconds of silence. Once the recording is stopped the recording
139         *                     data is sent to event_url. The range of possible values is between 3 and 10 inclusively.
140         *
141         * @return The {@link Builder} to keep building.
142         */
143        public Builder endOnSilence(Integer endOnSilence) {
144            this.endOnSilence = endOnSilence;
145            return this;
146        }
147
148        /**
149         * @param endOnKey Stop recording when a digit is pressed on the handset. Possible values are: *, # or any
150         *                 single digit e.g. 9
151         *
152         * @return The {@link Builder} to keep building.
153         */
154        public Builder endOnKey(Character endOnKey) {
155            this.endOnKey = endOnKey;
156            return this;
157        }
158
159        /**
160         * @param timeOut The maximum length of a recording in seconds. One the recording is stopped the recording data
161         *                is sent to event_url. The range of possible values is between 3 seconds and 7200 seconds (2
162         *                hours)
163         *
164         * @return The {@link Builder} to keep building.
165         */
166        public Builder timeOut(Integer timeOut) {
167            this.timeOut = timeOut;
168            return this;
169        }
170
171        /**
172         * @param beepStart Set to true to play a beep when a recording starts
173         *
174         * @return The {@link Builder} to keep building.
175         */
176        public Builder beepStart(Boolean beepStart) {
177            this.beepStart = beepStart;
178            return this;
179        }
180
181        /**
182         * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished.
183         *                 If the message recording is hosted by Nexmo, this webhook contains the URL you need to
184         *                 download the recording and other meta data.
185         *
186         * @return The {@link Builder} to keep building.
187         */
188        public Builder eventUrl(Collection<String> eventUrl) {
189            this.eventUrl = eventUrl;
190            return this;
191        }
192
193        /**
194         * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished.
195         *                 If the message recording is hosted by Nexmo, this webhook contains the URL you need to
196         *                 download the recording and other meta data.
197         *
198         * @return The {@link Builder} to keep building.
199         */
200        public Builder eventUrl(String... eventUrl) {
201            return eventUrl(Arrays.asList(eventUrl));
202        }
203
204        /**
205         * @param eventMethod The HTTP method used to make the request to eventUrl. The default value is POST.
206         *
207         * @return The {@link Builder} to keep building.
208         */
209        public Builder eventMethod(EventMethod eventMethod) {
210            this.eventMethod = eventMethod;
211            return this;
212        }
213
214        /**
215         * @param split Record the sent and received audio in separate channels of a stereo recording—set to {@link
216         *              SplitRecording#CONVERSATION} to enable this.
217         *
218         * @return The {@link Builder} to keep building.
219         */
220        public Builder split(SplitRecording split) {
221            this.split = split;
222            return this;
223        }
224
225        /**
226         * @param channels The number of channels to record (maximum 32). If the number of participants exceeds channels
227         *                 any additional participants will be added to the last channel in file. {@link #split} will be
228         *                 set to {@link SplitRecording#CONVERSATION} during the build process if channels is greater
229         *                 than 1.
230         *
231         * @return The {@link Builder} to keep building.
232         */
233        public Builder channels(Integer channels) {
234            this.channels = channels;
235            return this;
236        }
237
238        /**
239         * @return A new {@link RecordAction} object from the stored builder options.
240         */
241        public RecordAction build() {
242            return new RecordAction(this);
243        }
244    }
245}