diff --git a/arecord-launcher-scripts/README b/arecord-launcher-scripts/README deleted file mode 100644 index 65640b52..00000000 --- a/arecord-launcher-scripts/README +++ /dev/null @@ -1,2 +0,0 @@ -For the moment we can use those two scritps in order to record while writing or just view and listen to the recorded files.. -A more integrated solution would be better, but I haven't got much time now. diff --git a/arecord-launcher-scripts/usr/local/bin/xournalpp-ts-launcher.sh b/arecord-launcher-scripts/usr/local/bin/xournalpp-ts-launcher.sh deleted file mode 100755 index c19b74e6..00000000 --- a/arecord-launcher-scripts/usr/local/bin/xournalpp-ts-launcher.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -record_audio() -{ - directory="$HOME/Musica/recordings/" - - if ! [ -d "$directory" ]; - then - mkdir "$directory" - fi - - xournalpp-ts -f $directory $1 -} - -main() -{ - record_audio $1 -} - -main "$@" diff --git a/arecord-launcher-scripts/usr/local/bin/xournalpp-ts-recorder.sh b/arecord-launcher-scripts/usr/local/bin/xournalpp-ts-recorder.sh deleted file mode 100755 index a5601190..00000000 --- a/arecord-launcher-scripts/usr/local/bin/xournalpp-ts-recorder.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -#!/bin/bash -# Author: Serg Kolo -# Date: Dec 1, 2016 -# Purpose: simple script for recording audio with arecord -# Written for: https://askubuntu.com/q/855893/295286 - - - -record_audio() -{ - # Set up some variables to control arecord here - # Please remember to quote the variables - # and pay attention to slashes in file paths - - filetype="wav" - filename="record_$(date +%H_%M_%m_%d_%Y)" - directory="$HOME/Musica/recordings/" - - if ! [ -d "$directory" ]; - then - mkdir "$directory" - fi - - # This part will initiate recording of timestamped - # please see arecord's man page for other options - notify-send "Recording started" - exec arecord -f cd -d 3600 -t wav |lame --preset 56 -mm - "$directory""$filename".mp3 & - xournalpp-ts -a $filename.mp3 -f $directory $1 - pkill -f "arecord" && notify-send "Recording stopped" -} - -main() -{ -# if pgrep -f "arecord" ; -# then -# pkill -f "arecord" && notify-send "Recording stopped" -# else - record_audio $1 -# fi -} - -main "$@" diff --git a/launcher/usr/local/bin/xopp-recording.sh b/launcher/usr/local/bin/xopp-recording.sh new file mode 100755 index 00000000..a67e5eb5 --- /dev/null +++ b/launcher/usr/local/bin/xopp-recording.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +filetype="wav" +#filename="record_$(date +%H_%M_%m_%d_%Y)" +directory="$HOME/Musica/recordings/" + +if ! [ -d "$directory" ]; +then + mkdir "$directory" +fi + +if [[ $1 == "start" ]] && [[ $# -eq 2 ]] +then + filename=$2 + notify-send "Recording started" + amixer sset 'Capture' 35% + exec arecord -f cd -d 3600 -t wav |lame --preset 56 -mm - "$directory""$filename" & +elif [[ $1 == "stop" ]] +then + pkill -f "arecord" && notify-send "Recording stopped" +fi + + diff --git a/launcher/usr/local/bin/xournalpp-ts-launcher.sh b/launcher/usr/local/bin/xournalpp-ts-launcher.sh new file mode 100755 index 00000000..860714eb --- /dev/null +++ b/launcher/usr/local/bin/xournalpp-ts-launcher.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +xournalpp -f /home/morro/Musica/recordings/ diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json index 0bc39969..b0818b5e 100644 --- a/src/.vscode/settings.json +++ b/src/.vscode/settings.json @@ -55,6 +55,7 @@ "typeindex": "cpp", "typeinfo": "cpp", "utility": "cpp", - "variant": "cpp" + "variant": "cpp", + "hash_map": "cpp" } } \ No newline at end of file diff --git a/src/control/Actions.h b/src/control/Actions.h index af3fdc1d..ebba96c4 100644 --- a/src/control/Actions.h +++ b/src/control/Actions.h @@ -89,6 +89,8 @@ enum ActionType ACTION_TOOL_SELECT_OBJECT, ACTION_TOOL_VERTICAL_SPACE, ACTION_TOOL_HAND, + ACTION_TOOL_PLAY_OBJECT, + //ACTION_TOOL_DRAW_RECT, //ACTION_TOOL_DRAW_CIRCLE, //ACTION_TOOL_DRAW_ARROW, @@ -142,6 +144,7 @@ enum ActionType ACTION_VIEW_PRESENTATION_MODE, ACTION_MANAGE_TOOLBAR, ACTION_CUSTOMIZE_TOOLBAR, + ACTION_RECSTOP, // Menu Help ACTION_ABOUT = 800, @@ -153,7 +156,6 @@ enum ActionType ACTION_FOOTER_ZOOM_SLIDER, ACTION_FOOTER_LAYER, - // Used to select no item in a group... ACTION_NOT_SELECTED = 1 }; diff --git a/src/control/Control.cpp b/src/control/Control.cpp index 8fc0f283..f72f776d 100644 --- a/src/control/Control.cpp +++ b/src/control/Control.cpp @@ -61,6 +61,8 @@ using std::endl; #include using std::vector; +extern gint sttime; + // TODO Check for error log on startup, also check for emergency save document! Control::Control(GladeSearchpath* gladeSearchPath) @@ -612,6 +614,12 @@ void Control::actionPerformed(ActionType type, ActionGroup group, GdkEvent* even selectTool(TOOL_SELECT_OBJECT); } break; + case ACTION_TOOL_PLAY_OBJECT: + if (enabled) + { + selectTool(TOOL_PLAY_OBJECT); + } + break; case ACTION_TOOL_VERTICAL_SPACE: clearSelection(); if (enabled) @@ -828,6 +836,10 @@ void Control::actionPerformed(ActionType type, ActionGroup group, GdkEvent* even enableFullscreen(enabled); break; + case ACTION_RECSTOP: + recToggle(); + break; + // Footer, not really an action, but need an identifier to case ACTION_FOOTER_PAGESPIN: case ACTION_FOOTER_ZOOM_SLIDER: @@ -1156,6 +1168,53 @@ void Control::setShapeRecognizerEnabled(bool enabled) } } +#include +#include + +using namespace std; + +void Control::recStartStop(bool rec) +{ + string command = ""; + + if(rec){ + + char buffer [50]; + time_t secs=time(0); + tm *t=localtime(&secs); + //This prints the date and time in ISO format. + sprintf(buffer, "%04d-%02d-%02d_%02d:%02d:%02d", + t->tm_year+1900,t->tm_mon+1,t->tm_mday, + t->tm_hour,t->tm_min,t->tm_sec); + string data(buffer); + data +=".mp3"; + + audioFilename = data; + + printf("Start recording\n"); + command="xopp-recording.sh start "+data; + }else{ + printf("Stop recording\n"); + command="xopp-recording.sh stop"; + } + system(command.c_str()); +} + +void Control::recToggle() +{ + XOJ_CHECK_TYPE(Control); + + if(!this->recording){ + sttime = (g_get_monotonic_time()/1000000); + this->recording = true; + recStartStop(true); + }else{ + this->recording = false; + recStartStop(false); + } + +} + void Control::enableFullscreen(bool enabled, bool presentation) { XOJ_CHECK_TYPE(Control); @@ -2812,6 +2871,7 @@ void Control::quit() this->scheduler->lock(); + recStartStop(false); settings->save(); this->scheduler->removeAllJobs(); diff --git a/src/control/Control.h b/src/control/Control.h index a5c20cf1..6642a5f3 100644 --- a/src/control/Control.h +++ b/src/control/Control.h @@ -33,6 +33,9 @@ #include +extern string audioFilename; +extern string audioFolder; + class Sidebar; class CallbackData; class PageView; @@ -107,6 +110,8 @@ public: void manageToolbars(); void customizeToolbars(); void enableFullscreen(bool enabled, bool presentation = false); + void recToggle(); + void recStartStop(bool record); void gotoPage(); @@ -316,6 +321,8 @@ private: MetadataManager* metadata; + bool recording = false; + }; class CallbackData diff --git a/src/control/Tool.cpp b/src/control/Tool.cpp index eaef3de6..1a566329 100644 --- a/src/control/Tool.cpp +++ b/src/control/Tool.cpp @@ -205,6 +205,7 @@ string toolTypeToString(ToolType type) case TOOL_SELECT_RECT: return "selectRect"; case TOOL_SELECT_REGION: return "selectRegion"; case TOOL_SELECT_OBJECT: return "selectObject"; + case TOOL_PLAY_OBJECT: return "PlayObject"; case TOOL_VERTICAL_SPACE: return "verticalSpace"; case TOOL_HAND: return "hand"; /* @@ -226,6 +227,7 @@ ToolType toolTypeFromString(string type) else if (type == "selectRect") return TOOL_SELECT_RECT; else if (type == "selectRegion") return TOOL_SELECT_REGION; else if (type == "selectObject") return TOOL_SELECT_OBJECT; + else if (type == "playObject") return TOOL_PLAY_OBJECT; else if (type == "verticalSpace") return TOOL_VERTICAL_SPACE; else if (type == "hand") return TOOL_HAND; /* diff --git a/src/control/Tool.h b/src/control/Tool.h index e05b8d86..1c60aa3e 100644 --- a/src/control/Tool.h +++ b/src/control/Tool.h @@ -30,6 +30,7 @@ enum ToolType TOOL_SELECT_OBJECT = 8, TOOL_VERTICAL_SPACE = 9, TOOL_HAND = 10, + TOOL_PLAY_OBJECT = 11, /* TOOL_DRAW_RECT = 11, TOOL_DRAW_CIRCLE = 12, @@ -38,7 +39,7 @@ enum ToolType }; // The count of tools -#define TOOL_COUNT 10 +#define TOOL_COUNT 11 //#define TOOL_COUNT 13 diff --git a/src/control/ToolHandler.cpp b/src/control/ToolHandler.cpp index 17c573c8..08dfffaa 100644 --- a/src/control/ToolHandler.cpp +++ b/src/control/ToolHandler.cpp @@ -82,6 +82,9 @@ void ToolHandler::initTools() t = new Tool("hand", TOOL_HAND, 0x000000, false, false, false, false, false, false, false, NULL); tools[TOOL_HAND - TOOL_PEN] = t; + t = new Tool("playObject", TOOL_PLAY_OBJECT, 0x000000, false, false, false, false, false, false, false, NULL); + tools[TOOL_PLAY_OBJECT - TOOL_PEN] = t; + /* t = new Tool("drawRect", TOOL_DRAW_RECT, 0x000000, false, false, false, false, false, false, false, NULL); tools[TOOL_DRAW_RECT - TOOL_PEN] = t; @@ -684,7 +687,8 @@ void ToolHandler::setSelectionEditTools(bool setColor, bool setSize) if (this->current->type == TOOL_SELECT_RECT || this->current->type == TOOL_SELECT_REGION || - this->current->type == TOOL_SELECT_OBJECT) + this->current->type == TOOL_SELECT_OBJECT || + this->current->type == TOOL_PLAY_OBJECT) { this->listener->toolColorChanged(); this->listener->toolSizeChanged(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 3d9fec1b..b42835ba 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -25,7 +25,7 @@ using std::cout; using std::endl; //those two have to be moved somewhere else in the future -gint sttime; +gint sttime = 0; string audioFilename = ""; string audioFolder = ""; //gchar* audioFilename; @@ -697,9 +697,6 @@ void MainWindow::createToolbarAndMenu(bool initial) { XOJ_CHECK_TYPE(MainWindow); - /** this will be moved to a "start" button */ - sttime = (g_get_monotonic_time()/1000000); - GtkMenuShell* menubar = GTK_MENU_SHELL(get("menuViewToolbar")); g_return_if_fail(menubar != NULL); diff --git a/src/gui/PageView.cpp b/src/gui/PageView.cpp index 51300319..303396cb 100644 --- a/src/gui/PageView.cpp +++ b/src/gui/PageView.cpp @@ -336,6 +336,60 @@ void PageView::selectObjectAt(double x, double y) // clear old selection anyway this->xournal->getControl()->clearSelection(); + for (Layer* l : *this->page->getLayers()) + { + for (Element* e : *l->getElements()) + { + if (e->intersectsArea(&matchRect)) + { + if (e->getType() == ELEMENT_STROKE) + { + Stroke* s = (Stroke*) e; + double tmpGap = 0; + if ((s->intersects(x, y, 5, &tmpGap)) && (gap > tmpGap)) + { + gap = tmpGap; + strokeMatch = s; + } + } + else + { + elementMatch = e; + } + } + } + + selected--; + } + + if (strokeMatch) + { + elementMatch = strokeMatch; + } + + if (elementMatch) + { + xournal->setSelection(new EditSelection(xournal->getControl()->getUndoRedoHandler(), elementMatch, this, page)); + + repaintPage(); + } +} + +void PageView::playObjectAt(double x, double y) +{ + XOJ_CHECK_TYPE(PageView); + + int selected = this->page->getSelectedLayerId(); + GdkRectangle matchRect = { gint(x - 10), gint(y - 10), 20, 20 }; + + Stroke* strokeMatch = NULL; + double gap = 1000000000; + + Element* elementMatch = NULL; + + // clear old selection anyway + this->xournal->getControl()->clearSelection(); + for (Layer* l : *this->page->getLayers()) { for (Element* e : *l->getElements()) @@ -482,7 +536,8 @@ bool PageView::onButtonPressEvent(GtkWidget* widget, GdkEventButton* event) */ else if (h->getToolType() == TOOL_SELECT_RECT || h->getToolType() == TOOL_SELECT_REGION || - h->getToolType() == TOOL_SELECT_OBJECT) + h->getToolType() == TOOL_SELECT_OBJECT || + h->getToolType() == TOOL_PLAY_OBJECT) { if (h->getToolType() == TOOL_SELECT_RECT) { @@ -508,6 +563,10 @@ bool PageView::onButtonPressEvent(GtkWidget* widget, GdkEventButton* event) { selectObjectAt(x, y); } + else if (h->getToolType() == TOOL_PLAY_OBJECT) + { + playObjectAt(x, y); + } } else if (h->getToolType() == TOOL_TEXT) { diff --git a/src/gui/PageView.h b/src/gui/PageView.h index 55123be0..629ce14d 100644 --- a/src/gui/PageView.h +++ b/src/gui/PageView.h @@ -156,6 +156,7 @@ private: void startText(double x, double y); void selectObjectAt(double x, double y); + void playObjectAt(double x, double y); void addRerenderRect(double x, double y, double width, double height); diff --git a/src/gui/toolbarMenubar/ToolMenuHandler.cpp b/src/gui/toolbarMenubar/ToolMenuHandler.cpp index 32eb20ae..bc4a5e99 100644 --- a/src/gui/toolbarMenubar/ToolMenuHandler.cpp +++ b/src/gui/toolbarMenubar/ToolMenuHandler.cpp @@ -345,6 +345,9 @@ void ToolMenuHandler::initToolItems() addToolItem(new ToolButton(listener, gui, "FULLSCREEN", ACTION_FULLSCREEN, GROUP_FULLSCREEN, false, "fullscreen.svg", _C("Toggle fullscreen"), gui->get("menuViewFullScreen"))); + addToolItem(new ToolButton(listener, gui, "RECSTOP", ACTION_RECSTOP, GROUP_FULLSCREEN, false, + "rec.svg", _C("Rec / Stop"), gui->get("menuRecStop"))); + addToolItem(new ColorToolItem(listener, toolHandler, this->parent, 0xff0000, true)); addToolItem(new ToolButton(listener, gui, "PEN", ACTION_TOOL_PEN, GROUP_TOOL, true, "tool_pencil.svg", _C("Pen"), @@ -421,6 +424,9 @@ void ToolMenuHandler::initToolItems() addToolItem(new ToolButton(listener, gui, "SELECT_OBJECT", ACTION_TOOL_SELECT_OBJECT, GROUP_TOOL, true, "object-select.svg", _C("Select Object"), gui->get("menuToolsSelectObject"))); + addToolItem(new ToolButton(listener, gui, "PLAY_OBJECT", ACTION_TOOL_PLAY_OBJECT, GROUP_TOOL, true, + "object-play.svg", _C("Play Object"), gui->get("menuToolsPlayObject"))); + addToolItem(new ToolButton(listener, gui, "DRAW_CIRCLE", ACTION_TOOL_DRAW_CIRCLE, GROUP_RULER, false, "circle-draw.svg", _C("Draw Circle"), gui->get("menuToolsDrawCircle"))); addToolItem(new ToolButton(listener, gui, "DRAW_RECTANGLE", ACTION_TOOL_DRAW_RECT, GROUP_RULER, false, diff --git a/src/gui/toolbarMenubar/ToolSelectCombocontrol.cpp b/src/gui/toolbarMenubar/ToolSelectCombocontrol.cpp index c353364b..da12b4fb 100644 --- a/src/gui/toolbarMenubar/ToolSelectCombocontrol.cpp +++ b/src/gui/toolbarMenubar/ToolSelectCombocontrol.cpp @@ -22,9 +22,11 @@ ToolSelectCombocontrol::ToolSelectCombocontrol(ToolMenuHandler* th, ActionHandle this->iconSelectRect = gui->loadIconPixbuf("rect-select.svg"); this->iconSelectRgion = gui->loadIconPixbuf("lasso.svg"); this->iconSelectObject = gui->loadIconPixbuf("object-select.svg"); + this->iconPlayObject = gui->loadIconPixbuf("object-play.svg"); g_object_ref(this->iconSelectRect); g_object_ref(this->iconSelectRgion); g_object_ref(this->iconSelectObject); + g_object_ref(this->iconPlayObject); menuItem = gtk_image_menu_item_new_with_label(_C("Select Rectangle")); gtk_container_add(GTK_CONTAINER(popup), menuItem); @@ -47,6 +49,13 @@ ToolSelectCombocontrol::ToolSelectCombocontrol(ToolMenuHandler* th, ActionHandle gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuItem), gui->loadIcon("object-select.svg")); gtk_widget_show_all(menuItem); + menuItem = gtk_image_menu_item_new_with_label(_C("Play Object")); + gtk_container_add(GTK_CONTAINER(popup),menuItem); + th->registerMenupoint(menuItem,ACTION_TOOL_PLAY_OBJECT, GROUP_TOOL); + gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(menuItem), true); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuItem), gui->loadIcon("object-play.svg")); + gtk_widget_show_all(menuItem); + setPopupMenu(popup); } @@ -57,6 +66,7 @@ ToolSelectCombocontrol::~ToolSelectCombocontrol() g_object_unref(this->iconSelectRect); g_object_unref(this->iconSelectRgion); g_object_unref(this->iconSelectObject); + g_object_unref(this->iconPlayObject); XOJ_RELEASE_TYPE(ToolSelectCombocontrol); } @@ -96,6 +106,13 @@ void ToolSelectCombocontrol::selected(ActionGroup group, ActionType action) description = _("Select Object"); } + else if (action == ACTION_TOOL_PLAY_OBJECT && this->action != ACTION_TOOL_PLAY_OBJECT) + { + this->action = ACTION_TOOL_PLAY_OBJECT; + gtk_image_set_from_pixbuf(GTK_IMAGE(iconWidget), this->iconPlayObject); + + description = _("Play Object"); + } gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(item), description.c_str()); diff --git a/src/gui/toolbarMenubar/ToolSelectCombocontrol.h b/src/gui/toolbarMenubar/ToolSelectCombocontrol.h index 04d3c28f..89855cd9 100644 --- a/src/gui/toolbarMenubar/ToolSelectCombocontrol.h +++ b/src/gui/toolbarMenubar/ToolSelectCombocontrol.h @@ -39,4 +39,5 @@ private: GdkPixbuf* iconSelectRect; GdkPixbuf* iconSelectRgion; GdkPixbuf* iconSelectObject; + GdkPixbuf* iconPlayObject; }; diff --git a/ui/main.glade b/ui/main.glade index 2900eda9..9a597899 100644 --- a/ui/main.glade +++ b/ui/main.glade @@ -307,6 +307,16 @@ True + + + + True + False + False + Rec-Stop + + + True @@ -931,6 +941,18 @@ + + + + True + False + False + Play Object + True + True + + + True diff --git a/ui/pixmaps/object-play.svg b/ui/pixmaps/object-play.svg new file mode 100644 index 00000000..1ca4aa01 --- /dev/null +++ b/ui/pixmaps/object-play.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/ui/pixmaps/rec.svg b/ui/pixmaps/rec.svg new file mode 100644 index 00000000..f675ac7b --- /dev/null +++ b/ui/pixmaps/rec.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ui/pixmaps/stop.svg b/ui/pixmaps/stop.svg new file mode 100644 index 00000000..aa84bacd --- /dev/null +++ b/ui/pixmaps/stop.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ui/toolbar.ini b/ui/toolbar.ini index 63437ef0..bc6234f4 100755 --- a/ui/toolbar.ini +++ b/ui/toolbar.ini @@ -47,9 +47,9 @@ toolbarBottom1 = PAGE_SPIN,SEPARATOR,LAYER,GOTO_FIRST,GOTO_NEXT_ANNOTATED_PAGE,G [Toolbar Left] name = Toolbar Left name[de] = Toolbar Links -toolbarTop1 = SAVE,NEW,OPEN,SEPARATOR, CUT,COPY,PASTE,SEPARATOR, UNDO,REDO,SEPARATOR, PEN,ERASER,HILIGHTER,IMAGE,TEXT,SEPARATOR, DEFAULT_TOOL,SEPARATOR, PAGE_SPIN,SEPARATOR,INSERT_NEW_PAGE,DELETE_CURRENT_PAGE,SEPARATOR,GOTO_BACK,GOTO_NEXT,SEPARATOR,FULLSCREEN +toolbarTop1 = SAVE,NEW,OPEN,SEPARATOR, CUT,COPY,PASTE,SEPARATOR, UNDO,REDO,SEPARATOR, PEN,ERASER,HILIGHTER,IMAGE,TEXT,SEPARATOR, DEFAULT_TOOL,SEPARATOR, PAGE_SPIN,SEPARATOR,INSERT_NEW_PAGE,DELETE_CURRENT_PAGE,SEPARATOR,GOTO_BACK,GOTO_NEXT,SEPARATOR,FULLSCREEN,RECSTOP toolbarLeft1 = COLOR(0xffff00),COLOR(0xff8000),COLOR(0xff00ff),COLOR(0x00ff00),COLOR(0x00c0ff),COLOR(0x808080),COLOR(0x008000),COLOR(0xff0000),COLOR(0x3333cc),COLOR(0x000000),COLOR_SELECT,SEPARATOR,ZOOM_100,ZOOM_FIT,ZOOM_IN,ZOOM_SLIDER,ZOOM_OUT -toolbarLeft2 = FINE,MEDIUM,THICK, SEPARATOR,ZOOM_100,ZOOM_FIT,ZOOM_OUT,ZOOM_SLIDER,ZOOM_IN,DRAW_CIRCLE,DRAW_RECTANGLE,DRAW_ARROW,RULER,DRAW_RECTANGLE,SEPARATOR,VERTICAL_SPACE,SELECT_REGION,SELECT_RECTANGLE,SELECT_OBJECT +toolbarLeft2 = FINE,MEDIUM,THICK, SEPARATOR,ZOOM_100,ZOOM_FIT,ZOOM_OUT,ZOOM_SLIDER,ZOOM_IN,DRAW_CIRCLE,DRAW_RECTANGLE,DRAW_ARROW,RULER,DRAW_RECTANGLE,SEPARATOR,VERTICAL_SPACE,SELECT_REGION,SELECT_RECTANGLE,SELECT_OBJECT,PLAY_OBJECT [Toolbar Right]