#define APP_CONTROL_OPERATION_TIMEOUT "http://tizen.org/appcontrol/operation/timeout"
#define APP_CONTROL_OPERATION_ALARM "http://tizen.org/appcontrol/operation/alarm"
+#define RINGTONE_APP_PACKAGE_ID "org.tizen.setting-ringtone"
+
+#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0])
+#define DEFAULT_RINGTONE_PATH "ringtones/alarm.mp3"
#define SOUND_DEFAULT "settings/ringtone_sdk.mp3"
--- /dev/null
+/*
+* Copyright 2016 Samsung Electronics Co., Ltd
+*
+* Licensed under the Flora License, Version 1.1 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://floralicense.org/license/
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _CLOCK_UTILS_RINGTONE_PICKER_H_
+#define _CLOCK_UTILS_RINGTONE_PICKER_H_
+
+#include <app_control.h>
+#include <functional>
+
+namespace utils {
+
+class RingtonePicker {
+ public:
+ /**
+ * @brief Default constructor.
+ */
+ RingtonePicker();
+
+ /**
+ * @brief Shows rigntone picker view.
+ *
+ * @return true on success, false if unable to show view.
+ */
+ bool ShowDialog();
+
+ /**
+ * @brief Gets chosen ringtone file path.
+ *
+ * @return return absolute file path to ringtone. Value remains valid
+ * until class is destructed or function subscribed with
+ * RegisterPathUpdateSignalHandler is called.
+ */
+ const std::string& GetRingtonePath() const { return ringtone_; }
+
+ /**
+ * @brief Register callback called when ringtone path changes.
+ * New path will be returned by GetRingtonePath method.
+ */
+ void RegisterPathUpdateSignalHandler(std::function<void(void)> cb);
+ private:
+ std::string ringtone_;
+ std::function<void(void)> update_cb_;
+ bool initialized_;
+ static void AppControlCb(app_control_h request, app_control_h reply, app_control_result_e result, void *priv);
+};
+
+} /* utils */
+
+#endif
#include "Model/WeekFlags.h"
#include "Model/Alarm.h"
#include "View/WeekFlagsView.h"
+#include "Utils/RingtonePicker.h"
namespace view {
class EditAlarmView : public PageView {
Elm_Object_Item *type_it_;
Elm_Object_Item *repeat_it_;
Elm_Object_Item *volume_it_;
+ Elm_Object_Item *tone_it_;
AlarmViewInfo data_;
bool is_muted_;
static void PopupListItemSelectedCallback(void *data, Evas_Object *obj, void *event);
static void PopupHide(void *data, Evas_Object *obj, void *event);
static void SnoozeItemSelectedCallback(void *data, Evas_Object *obj, void *event);
+ static void ChooseAlarmToneItemSelectedCallback(void *data, Evas_Object *obj, void *event);
void CreateGenlistItems();
void ShowSetTypePopup();
void OnWeekFlagsPagePopped();
void UpdateVolumeIcon(bool mute);
+ utils::RingtonePicker picker_;
+ void RingtonePathUpdateCallback();
};
} /* view */
model_->Run();
animator_.Start();
view_->EnableSnooze(false);
- view_->PlayMusic(utils::Utils::GetAppResourcePath(utils::Utils::APP_DIR_RESOURCE, SOUND_DEFAULT), 1.0);
+ view_->PlayMusic(utils::Utils::GetAppResourcePath(utils::Utils::APP_DIR_SHARED_RESOURCE, SOUND_DEFAULT), 1.0);
view_->StartVibration();
}
else {
DBG("Invalid alarm's sound path. Playing default.");
view_->PlayMusic(utils::Utils::GetAppResourcePath(
- utils::Utils::APP_DIR_RESOURCE, SOUND_DEFAULT),
+ utils::Utils::APP_DIR_SHARED_RESOURCE, SOUND_DEFAULT),
alarm_->GetVolume());
}
--- /dev/null
+/*
+* Copyright 2016 Samsung Electronics Co., Ltd
+*
+* Licensed under the Flora License, Version 1.1 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://floralicense.org/license/
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "Common/Defines.h"
+#include "Utils/Log.h"
+#include "Utils/RingtonePicker.h"
+#include "Utils/Utils.h"
+
+namespace utils {
+
+RingtonePicker::RingtonePicker() :
+ initialized_(false)
+{
+}
+
+void RingtonePicker::AppControlCb(app_control_h request, app_control_h reply,
+ app_control_result_e result, void *priv)
+{
+ char **ringtone_path;
+ int len;
+
+ RingtonePicker *instance = static_cast<RingtonePicker*>(priv);
+ instance->initialized_ = false;
+
+ if (result != APP_CONTROL_RESULT_SUCCEEDED) {
+ ERR("app_control '%s' operation failed", APP_CONTROL_OPERATION_PICK);
+ return;
+ }
+
+ int err = app_control_get_extra_data_array(reply, APP_CONTROL_DATA_SELECTED,
+ &ringtone_path, &len);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_get_extra_data_array failed: %s", get_error_message(err));
+ return;
+ }
+
+ if (len != 1) {
+ ERR("Invalid ringtones paths count, expected 1, got %d", len);
+ free(ringtone_path);
+ return;
+ }
+
+ // when replay contains extra data -> pick operation was successfull
+ DBG("Recieved ringthone path: %s", ringtone_path[0]);
+ instance->ringtone_ = ringtone_path[0];
+ free(ringtone_path);
+ if (instance->update_cb_)
+ instance->update_cb_();
+}
+
+bool RingtonePicker::ShowDialog()
+{
+ app_control_h handle;
+ const char *arr[2];
+
+ if (initialized_)
+ return true;
+
+ // Request remote RINGTONE_APP_PACKAGE_ID app to choose ringtone for us
+ int err = app_control_create(&handle);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_create failed: %s", get_error_message(err));
+ return false;
+ }
+
+ err = app_control_set_app_id(handle, RINGTONE_APP_PACKAGE_ID);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_set_app_id failed: %s", get_error_message(err));
+ app_control_destroy(handle);
+ return false;
+ }
+
+ err = app_control_set_operation(handle, APP_CONTROL_OPERATION_PICK);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_set_operation failed: %s", get_error_message(err));
+ app_control_destroy(handle);
+ return false;
+ }
+
+ // allow RINGTONE_APP_PACKAGE_ID app to select only one item
+ err = app_control_add_extra_data(handle, APP_CONTROL_DATA_SELECTION_MODE, "single");
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_add_extra_data failed: %s", get_error_message(err));
+ app_control_destroy(handle);
+ return false;
+ }
+
+ // pass default ringtone to settings-ringtone (will be included on list)
+ arr[0] = Utils::GetAppResourcePath(Utils::APP_DIR_SHARED_RESOURCE, DEFAULT_RINGTONE_PATH);
+ // FIXME pass directory information, since settings are not interpreting
+ // APP_CONTROL_DATA_PATH values correctly (scans dir for files)
+ arr[1] = Utils::GetAppResourcePath(Utils::APP_DIR_SHARED_RESOURCE, "ringtones");
+ err = app_control_add_extra_data_array(handle, APP_CONTROL_DATA_PATH, arr,
+ ARRAY_SIZE(arr));
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_add_extra_data_array failed: %s", get_error_message(err));
+ app_control_destroy(handle);
+ return false;
+ }
+
+ err = app_control_set_launch_mode(handle, APP_CONTROL_LAUNCH_MODE_GROUP);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_set_launch_mode failed: %s", get_error_message(err));
+ app_control_destroy(handle);
+ return false;
+ }
+
+ err = app_control_send_launch_request(handle, AppControlCb, this);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_send_launch_request failed: %s", get_error_message(err));
+ app_control_destroy(handle);
+ return false;
+ }
+
+ app_control_destroy(handle);
+ initialized_ = true;
+ return true;
+}
+
+void RingtonePicker::RegisterPathUpdateSignalHandler(std::function<void(void)> cb)
+{
+ update_cb_ = cb;
+}
+
+};
*/
#include "Utils/Log.h"
-#include "View/EditAlarmView.h"
+#include "Utils/RingtonePicker.h"
#include "Utils/Utils.h"
#include "Utils/ThemeExtension.h"
+#include "View/EditAlarmView.h"
#include <efl_extension.h>
#include <Elementary.h>
{
week_flags_view_.RegisterPoppedCallback(
std::bind(&EditAlarmView::OnWeekFlagsPagePopped, this));
+ picker_.RegisterPathUpdateSignalHandler(
+ std::bind(&EditAlarmView::RingtonePathUpdateCallback, this));
}
EditAlarmView::~EditAlarmView()
elm_genlist_item_selected_set(it, EINA_FALSE);
}
+void EditAlarmView::ChooseAlarmToneItemSelectedCallback(void *data, Evas_Object *obj, void *event)
+{
+ Elm_Object_Item *it = static_cast<Elm_Object_Item*>(event);
+ EditAlarmView *view = static_cast<EditAlarmView*>(data);
+
+ if (!view->picker_.ShowDialog())
+ ERR("RingtonePicker::ShowDialog failed");
+ elm_genlist_item_selected_set(it, EINA_FALSE);
+}
+
void EditAlarmView::CreateGenlistItems()
{
Elm_Genlist_Item_Class *itc;
if (!strcmp(part, "elm.text")) {
return strdup("Alarm tone");
} else if (!strcmp(part, "elm.text.sub")) {
- return strdup(view->data_.melody.c_str());
+ const char *basename = ecore_file_file_get(view->data_.melody.c_str());
+ return strdup(basename ? basename : view->data_.melody.c_str());
}
return NULL;
};
- elm_genlist_item_append(content_, itc, this, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ tone_it_ = elm_genlist_item_append(content_, itc, this, NULL, ELM_GENLIST_ITEM_NONE,
+ EditAlarmView::ChooseAlarmToneItemSelectedCallback, this);
elm_genlist_item_class_unref(itc);
// snooze configuration
is_muted_ = data_.volume <= 0.0 ? true : false;
elm_genlist_realized_items_update(content_);
}
+
+void EditAlarmView::RingtonePathUpdateCallback()
+{
+ if (ecore_file_can_read(picker_.GetRingtonePath().c_str())) {
+ data_.melody = picker_.GetRingtonePath();
+ elm_genlist_item_update(tone_it_);
+ } else {
+ ERR("Selected path cannot be read: %s", picker_.GetRingtonePath().c_str());
+ }
+}