Java tutorial
/* * Copyright (C) 2011 aki@akjava.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. */ package com.akjava.gwt.subplayer.client; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.akjava.gwt.chrometts.client.ChromeTts; import com.akjava.gwt.chrometts.client.TtsEvent; import com.akjava.gwt.chrometts.client.TtsOption; import com.akjava.gwt.chrometts.client.TtsVoice; import com.akjava.gwt.chrometts.client.ChromeTts.GetVoiceHandler; import com.akjava.gwt.chrometts.client.ChromeTts.TtsEventHandler; import com.akjava.gwt.subplayer.client.resources.Binder; import com.akjava.gwt.subplayer.client.ui.HTML5InputRange; import com.akjava.subtitle.client.srt.SRTList; import com.akjava.subtitle.client.srt.SRTObject; import com.akjava.subtitle.client.srt.SRTParser; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.JsArray; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.LoadEvent; import com.google.gwt.event.dom.client.LoadHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.text.shared.Renderer; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.DisclosurePanel; import com.google.gwt.user.client.ui.DockLayoutPanel; import com.google.gwt.user.client.ui.FocusPanel; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootLayoutPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.TabLayoutPanel; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.ValueListBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; public class SubPlayer implements EntryPoint, SubContainer { private VerticalPanel itemPanel; private LoadPanel loadPanel; @Override public void onModuleLoad() { //pre load resource ImageResource icon = Binder.INSTANCE.loadanime(); loadImg = new Image(icon); loadImg.setVisible(false); loadImg.addLoadHandler(new LoadHandler() { @Override public void onLoad(LoadEvent event) { RootPanel.get().remove(loadImg); loadImg.setVisible(true); } }); RootPanel.get().add(loadImg); preference = new SubPlayerPreference(); preference.initialize(); tab = new TabLayoutPanel(2, Unit.EM); tab.setHeight("500px"); VerticalPanel root = new VerticalPanel(); root.setWidth("100%"); root.setHeight("100%"); //root.setHeight("200px"); DockLayoutPanel doc = new DockLayoutPanel(Unit.PX); doc.addSouth(new HTMLPanel( "<div align='center'>Subtitle TTS Player by <a href='http://www.akjava.com'>akjava.com</a></div>"), 40); doc.add(tab); RootLayoutPanel.get().add(doc); //RootLayoutPanel.get().add(new Label("hello")); tab.add(root, "PLAY"); noSubtitle = new Label("Subtitle is empty.load from Load tab"); noSubtitle.setStyleName("nosubtitle"); root.add(noSubtitle); loadPanel = new LoadPanel(); loadPanel.setWidth("100%"); loadPanel.setHeight("100%"); tab.add(loadPanel, "LOAD"); loadPanel.setText(preference.getSrtText()); itemPanel = new VerticalPanel(); itemPanel.setSpacing(8); itemPanelScroll = new ScrollPanel(itemPanel); itemPanelScroll.setWidth("100%"); itemPanelScroll.setHeight("350px"); root.add(itemPanelScroll); /* for(int i=0;i<5;i++){ String text=i+" hello world\n"; for(int j=0;j<i;j++){ text+="line\n"; } HTMLPanel label=new HTMLPanel(text.replace("\n", "<br/>")); FocusPanel panel=new FocusPanel(label); panel.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { unselectAll(); setlectWidget((Widget) event.getSource()); } }); //label.setHeight("100px"); itemPanel.add(panel); }*/ playerWidget = new PlayerWidget(this); root.add(playerWidget); DisclosurePanel ds = new DisclosurePanel("show subtitle time [start] - [end]"); timeLabel = new Label(); ds.add(timeLabel); //ds.add(new Label("0:0:0 - 0:0:12")); root.add(ds); selectWidgetHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { unselectAll(); setlectWidget((Widget) event.getSource()); } }; DisclosurePanel vs = new DisclosurePanel("Voice Settings"); root.add(vs); voiceSettings = new VoiceSettings(); vs.add(voiceSettings); //load data from preferences //if empty load mode. if (!loadPanel.getText().isEmpty()) { loadSrt(preference.getSrtSelectIndex()); } else { tab.selectTab(1); } } public class SRTItemPanel extends FocusPanel { SRTObject srt; public SRTObject getSrt() { return srt; } public SRTItemPanel(SRTObject srt) { this.srt = srt; HorizontalPanel hpanel = new HorizontalPanel(); hpanel.setSpacing(2); hpanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE); Button play = new Button("PLAY"); play.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int index = itemPanel.getWidgetIndex(SRTItemPanel.this); play(index); } }); hpanel.add(play); HTMLPanel html = new HTMLPanel(srt.getText().replace("\n", "<br/>")); hpanel.add(html); setWidget(hpanel); } } ClickHandler selectWidgetHandler; private TabLayoutPanel tab; private Label noSubtitle; private SubPlayerPreference preference; private Image loadImg; private PlayerWidget playerWidget; private ScrollPanel itemPanelScroll; private Label timeLabel; public class LoadPanel extends VerticalPanel { private TextArea textArea; public LoadPanel() { Label label = new Label("To load srt,copy and paste srt text from srt file and click load button."); add(label); setSpacing(4); textArea = new TextArea(); textArea.setWidth("100%"); textArea.setHeight("350px"); add(textArea); HorizontalPanel bcontrol = new HorizontalPanel(); add(bcontrol); Button load = new Button("LOAD"); load.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { loadSrt(0); } }); bcontrol.add(load); Button clear = new Button("CLEAR"); clear.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { clearSrt(); } }); bcontrol.add(clear); } public String getText() { return textArea.getText(); } public void setText(String text) { textArea.setText(text); } } private void clearSrt() { loadPanel.setText(""); itemPanel.clear(); initPlayerSettings(); preference.setSrtText(""); updateNoSubtitleWarning(); } private void updateNoSubtitleWarning() { if (itemPanel.getWidgetCount() > 0) { noSubtitle.setVisible(false); } else { noSubtitle.setVisible(true); } } private void loadSrt(final int selectIndex) { final String text = loadPanel.getText(); final DialogBox dialog = new DialogBox(); //dialog.setSize("200px", "200px"); dialog.setText("Subtitle Parsing"); //GWT.log(loadImg.getUrl()); //loadImg.setVisible(true); VerticalPanel vpanel = new VerticalPanel(); //Image img=new Image("../img/loadanime.gif"); //GWT.log(img.getUrl()); //loadImg.setVisible(true); vpanel.add(loadImg); dialog.setWidget(vpanel); dialog.setModal(true); dialog.setGlassEnabled(true); dialog.show(); dialog.center(); Timer timer = new Timer() { @Override public void run() { SRTParser parser = new SRTParser(); SRTList list = parser.parse(text.split("\n")); dialog.hide(); playerWidget.setSubLength(list.size()); if (list.size() > 0) { preference.setSrtText(text); preference.setSrtSelectIndex(0); playerWidget.setSubIndex(0); } itemPanel.clear(); for (int i = 0; i < list.size(); i++) { SRTObject srt = list.getSRTObjectAt(i); SRTItemPanel panel = new SRTItemPanel(srt); panel.addClickHandler(selectWidgetHandler); itemPanel.add(panel); } initPlayerSettings(); tab.selectTab(0);//switch to view //label mode updateNoSubtitleWarning(); selectWidget(selectIndex); } }; timer.schedule(100); } private void initPlayerSettings() { playerWidget.setSubIndex(0); } private void selectWidget(int index) { if (index < itemPanel.getWidgetCount()) { Widget widget = itemPanel.getWidget(index); setlectWidget(widget); } } private SRTItemPanel getSelectWidget() { return (SRTItemPanel) itemPanel.getWidget(playerWidget.getSubIndex()); } private SRTItemPanel getWidget(int index) { return (SRTItemPanel) itemPanel.getWidget(index); } private void setlectWidget(Widget widget) { widget.addStyleName("select"); int ind = itemPanel.getWidgetIndex(widget); playerWidget.setSubIndex(ind); SRTItemPanel srtItem = (SRTItemPanel) widget; SRTObject srt = srtItem.getSrt(); timeLabel.setText(srt.getStartTime().toString() + " - " + srt.getEndTime().toString()); } private void unselectAll() { for (int i = 0; i < itemPanel.getWidgetCount(); i++) { itemPanel.getWidget(i).removeStyleName("select"); } } private int calculateScrollY(int index) { int scroll = 0; for (int i = 0; i < index; i++) { scroll += itemPanel.getWidget(i).getOffsetHeight(); scroll += itemPanel.getSpacing(); } return scroll; } private Timer tmpTimer; private VoiceSettings voiceSettings; @Override public void autoPlay(int index) { play(index); } private void endPlay() { if (playerWidget.hasNext()) { playerWidget.doNext(); play(playerWidget.getSubIndex()); } else { playerWidget.endAutoPlay(); } } @Override public void moveTo(int index) { int sat = calculateScrollY(index); itemPanelScroll.setVerticalScrollPosition(sat); unselectAll(); setlectWidget(itemPanel.getWidget(index)); } TtsEventHandler eventHandler; @Override public void play(int index) { // TODO call tts if (eventHandler == null) { eventHandler = new TtsEventHandler() { @Override public void event(TtsEvent event) { if (event.getType().equals(TtsEvent.TYPE_END) || event.getType().equals(TtsEvent.TYPE_CANCELLED) || event.getType().equals(TtsEvent.TYPE_INTERRUPTED) || event.getType().equals(TtsEvent.TYPE_ERROR)) { // endPlay(); } } }; } ; if (ChromeTts.isAvaialbe()) { String text = getWidget(index).getSrt().getText(); TtsOption option = ChromeTts.options().rate(voiceSettings.getRate()).pitch(voiceSettings.getPitch()) .voiceName(voiceSettings.getVoiceName()); if (playerWidget.isAutoPlaying()) { option.onEvent(eventHandler); } ChromeTts.speak(text, option, null); } } @Override public void stop() { playerWidget.setAutoPlaying(false); ChromeTts.stop(); } public class VoiceSettings extends VerticalPanel { Label rateValue; private Label pitchValue; private HTML5InputRange pitchRange; private HTML5InputRange rateRange; private ValueListBox<String> voiceNames; public VoiceSettings() { voiceNames = new ValueListBox<String>(new Renderer<String>() { @Override public String render(String object) { return object; } @Override public void render(String object, Appendable appendable) throws IOException { } }); voiceNames.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { String value = event.getValue(); preference.setVoiceName(value); } }); add(voiceNames); updateVoiceNames(); HorizontalPanel voices = new HorizontalPanel(); add(voices); voices.add(new Label("Voices:")); voices.add(voiceNames); Button reset = new Button("Reset"); voices.add(reset); reset.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { preference.setVoiceName(""); preference.setVoiceRate(1); preference.setVoicePitch(1); updateVoiceNames(); rateRange.setValue(10); rateValue.setText("RATE:" + 1); pitchRange.setValue(10); pitchValue.setText("PITCH:" + 1); } }); HorizontalPanel settings = new HorizontalPanel(); add(settings); rateValue = new Label(); rateValue.setWidth("60px"); settings.add(rateValue); int drv = (int) (preference.getVoiceRate() * 10); rateValue.setText("RATE:" + drv); rateRange = new HTML5InputRange(1, 50, drv); rateRange.setWidth("100px"); rateRange.addMouseUpHandler(new MouseUpHandler() { @Override public void onMouseUp(MouseUpEvent event) { double rv = (double) rateRange.getValue() / 10; rateValue.setText("RATE:" + rv); preference.setVoiceRate(rv); } }); settings.add(rateRange); pitchValue = new Label(); pitchValue.setWidth("60px"); settings.add(pitchValue); int dpv = (int) (preference.getVoicePitch() * 10); pitchValue.setText("PITCH:" + dpv); pitchRange = new HTML5InputRange(1, 20, dpv); pitchRange.setWidth("100px"); pitchRange.addMouseUpHandler(new MouseUpHandler() { @Override public void onMouseUp(MouseUpEvent event) { double pv = (double) pitchRange.getValue() / 10; pitchValue.setText("PITCH:" + pv); preference.setVoicePitch(pv); } }); settings.add(pitchRange); } public String getVoiceName() { return voiceNames.getValue(); } private void updateVoiceNames() { if (ChromeTts.isAvaialbe()) { ChromeTts.getVoices(new GetVoiceHandler() { @Override public void voices(JsArray<TtsVoice> voices) { String dv = preference.getVoiceName(); List<String> names = new ArrayList<String>(); for (int i = 0; i < voices.length(); i++) { names.add(voices.get(i).getVoiceName()); } String vname = names.get(0); if (names.contains(dv)) { vname = dv; } voiceNames.setValue(vname); voiceNames.setAcceptableValues(names); } }); } } public double getPitch() { return (double) pitchRange.getValue() / 10; } public double getRate() { return (double) rateRange.getValue() / 10; } } }